home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / unix / sit_shar / sit.c < prev    next >
C/C++ Source or Header  |  1991-01-30  |  6KB  |  284 lines

  1. /*
  2.  * sit - Stuffit for UNIX
  3.  *  Puts unix data files into stuffit archive suitable for downloading
  4.  *    to a Mac.  Automatically processes files output from xbin.
  5.  *
  6.  *  Reverse engineered from unsit by Allan G. Weber, which was based on
  7.  *  macput, which was based on ...
  8.  *  Just like unsit this uses the host's version of compress to do the work.
  9.  *
  10.  * Examples:
  11.  *   1) take collection of UNIX text files and make them LSC text files 
  12.  *    when uncompressed on the mac:
  13.  *       sit -u -T TEXT -C KAHL file ...
  14.  *   2) Process output from xbin:
  15.  *       xbin file1     (produces FileOne.{info,rsrc,data})
  16.  *       sit file1
  17.  *
  18.  *  Tom Bereiter
  19.  *    ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
  20.  */
  21. #define BSD
  22.  
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <stdio.h>
  26. #include "sit.h"
  27. #ifdef BSD
  28. #include <sys/time.h>
  29. #include <sys/timeb.h>
  30. #else
  31. #include <time.h>
  32. extern long timezone;
  33. #endif
  34.  
  35. #ifndef min
  36. #define min(a,b) ((a)<(b)?(a):(b))
  37. #endif
  38.  
  39. /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
  40. #define TIMEDIFF 0x7c25b080
  41.  
  42. struct sitHdr sh;
  43. struct fileHdr fh;
  44.  
  45. char buf[BUFSIZ];
  46. char *defoutfile = "archive.sit";
  47. int ofd;
  48. ushort crc;
  49. int clen;
  50. int rmfiles;
  51. int    unixf;
  52. char *Creator, *Type;
  53.  
  54. usage() { fprintf(stderr,"Usage: sit file\n"); }
  55. extern char *optarg;
  56. extern int optind;
  57.  
  58. main(argc,argv) char **argv; {
  59.     int i,n;
  60.     int total, nfiles;
  61.     int c;
  62.  
  63.     while ((c=getopt(argc, argv, "ro:uC:T:")) != EOF)
  64.     switch (c) {
  65.         case 'r':
  66.             rmfiles++;    /* remove files when done */
  67.             break;
  68.         case 'o':        /* specify output file */
  69.             defoutfile = optarg;
  70.             break;
  71.         case 'u':        /* unix file -- change '\n' to '\r' */
  72.             unixf++;
  73.             break;
  74.         case 'C':        /* set Mac creator */
  75.             Creator = optarg;
  76.             break;
  77.         case 'T':        /* set Mac file type */
  78.             Type = optarg;
  79.             break;
  80.         case '?':
  81.             usage();
  82.             exit(1);
  83.     }
  84.  
  85.     if ((ofd=creat(defoutfile,0644))<0) {
  86.         perror(defoutfile);
  87.         exit(1);
  88.     }
  89.     /* empty header, will seek back and fill in later */
  90.     write(ofd,&sh,sizeof sh);
  91.  
  92.     for (i=optind; i<argc; i++) {
  93.         n = put_file(argv[i]);
  94.         if (n) {
  95.             total += n;
  96.             nfiles++;
  97.         }
  98.     }
  99.     lseek(ofd,0,0);
  100.  
  101.     total += sizeof(sh);
  102.     /* header header */
  103.     strncpy(sh.sig1,"SIT!",4);
  104.     cp2(nfiles,sh.numFiles);
  105.     cp4(total,sh.arcLen);
  106.     strncpy(sh.sig2,"rLau",4);
  107.     sh.version = 1;
  108.  
  109.     write(ofd,&sh,sizeof sh);
  110. }
  111.  
  112. put_file(name)
  113. char name[];
  114. {
  115.     struct stat st;
  116.     struct infohdr ih;
  117.     int i,n,fd;
  118.     long fpos1, fpos2;
  119.     char nbuf[256], *p;
  120.     int fork=0;
  121.     long tdiff;
  122.     struct tm *tp;
  123. #ifdef BSD
  124.     struct timeb tbuf;
  125. #else
  126.     long bs;
  127. #endif
  128.  
  129.     fpos1 = lseek(ofd,0,1); /* remember where we are */
  130.     /* write empty header, will seek back and fill in later */
  131.     bzero(&fh,sizeof fh);
  132.     write(ofd,&fh,sizeof fh);
  133.  
  134.     /* look for resource fork */
  135.     strcpy(nbuf,name);
  136.     strcat(nbuf,".rsrc");
  137.     if (stat(nbuf,&st)>=0 && st.st_size) {    /* resource fork exists */
  138.         dofork(nbuf);
  139.         cp4(st.st_size,fh.rLen);
  140.         cp4(clen,fh.cRLen);
  141.         cp2(crc,fh.rsrcCRC);
  142.         fh.compRMethod = lpzComp;
  143.         fork++;
  144.     }
  145.     if (rmfiles) unlink(nbuf);    /* ignore errors */
  146.  
  147.     /* look for data fork */
  148.     st.st_size = 0;
  149.     strcpy(nbuf,name);
  150.     if (stat(nbuf,&st)<0) {        /* first try plain name */
  151.         strcat(nbuf,".data");
  152.         stat(nbuf,&st);
  153.     }
  154.     if (st.st_size) {        /* data fork exists */
  155.         dofork(nbuf);
  156.         cp4(st.st_size,fh.dLen);
  157.         cp4(clen,fh.cDLen);
  158.         cp2(crc,fh.dataCRC);
  159.         fh.compDMethod = lpzComp;
  160.         fork++;
  161.     }
  162.     if (fork == 0) {
  163.         fprintf(stderr,"%s: no data or resource files\n",name);
  164.         return 0;
  165.     }
  166.     if (rmfiles) unlink(nbuf);    /* ignore errors */
  167.  
  168.     /* look for .info file */
  169.     strcpy(nbuf,name);
  170.     strcat(nbuf,".info");
  171.     if ((fd=open(nbuf,0))>=0 && read(fd,&ih,sizeof(ih))==sizeof(ih)) {
  172.         strncpy(fh.fName, ih.name,64);
  173.         strncpy(fh.fType, ih.type, 4);
  174.         strncpy(fh.fCreator, ih.creator, 4);
  175.         strncpy(fh.FndrFlags, ih.flag, 2);
  176.         strncpy(fh.cDate, ih.ctime, 4);
  177.         strncpy(fh.mDate, ih.mtime, 4);
  178.     }
  179.     else {    /* no info file so fake it */
  180.         strncpy(&fh.fName[1], name,63); fh.fName[0] = min(strlen(name),63);
  181.         /* default to LSC text file */
  182.         strncpy(fh.fType, Type ? Type : "TEXT", 4);
  183.         strncpy(fh.fCreator, Creator ? Creator : "KAHL", 4);
  184.         /* convert unix file time to mac time format */
  185. #ifdef BSD
  186.         ftime(&tbuf);
  187.         tp = localtime(&tbuf.time);
  188.         tdiff = TIMEDIFF - tbuf.timezone * 60;
  189.         if (tp->tm_isdst)
  190.             tdiff += 60 * 60;
  191. #else
  192.         /* I hope this is right! -andy */
  193.         time(&bs);
  194.         tp = localtime(&bs);
  195.         tdiff = TIMEDIFF - timezone;
  196.         if (tp->tm_isdst)
  197.             tdiff += 60 * 60;
  198. #endif
  199.         cp4(st.st_ctime + tdiff, fh.cDate);
  200.         cp4(st.st_mtime + tdiff, fh.mDate);
  201.     }
  202.     close(fd);
  203.     if (rmfiles) unlink(nbuf);    /* ignore errors */
  204.  
  205.     crc = updcrc(0,&fh,(sizeof fh)-2);
  206.     cp2(crc, fh.hdrCRC);
  207.  
  208.     fpos2 = lseek(ofd,0,1);        /* remember where we are */
  209.     lseek(ofd,fpos1,0);                /* seek back over file(s) and header */
  210.     write(ofd,&fh,sizeof fh);        /* write back header */
  211.     fpos2=lseek(ofd,fpos2,0);                /* seek forward file */
  212.  
  213.     return (fpos2 - fpos1);
  214. }
  215.     
  216. dofork(name)
  217. char name[];
  218. {
  219.     FILE *fs;
  220.     int n, fd, ufd;
  221.     char *p;
  222.  
  223.     if ((fd=open(name,0))<0) {
  224.         perror(name);
  225.         return 0;
  226.     }   
  227.     if (unixf)        /* build conversion file */
  228.         if ((ufd=creat("sit+temp",0644))<0) {
  229.             perror("sit+temp");
  230.             return 0;
  231.         }   
  232.     /* do crc of file: */
  233.     crc = 0;
  234.     while ((n=read(fd,buf,BUFSIZ))>0) {
  235.         if (unixf) {    /* convert '\n' to '\r' */
  236.             for (p=buf; p<&buf[n]; p++)
  237.                 if (*p == '\n') *p = '\r';
  238.             write(ufd,buf,n);
  239.         }
  240.         crc = updcrc(crc,buf,n);
  241.     }
  242.     close(fd);
  243.     /*
  244.      * open pipe to compress file
  245.      *   If a unix file ('\n' -> '\r' conversion) 'sit+temp' will be a new copy
  246.      *   with the conversion done.    Otherwise, 'sit+temp' is just a link to 
  247.      *   the input file.
  248.      */
  249.     if (unixf)
  250.         close(ufd);
  251.     else link(name,"sit+temp");
  252.     fs = popen("compress -c -n -b 14 sit+temp","r");
  253.     if (fs == NULL) {
  254.         perror(name);
  255.         return 0;
  256.     }
  257.     /* write out compressed file */
  258.     clen = 0;
  259.     while ((n=fread(buf,1,BUFSIZ,fs))>0) {
  260.         write(ofd,buf,n);
  261.         clen += n;
  262.     }
  263.     pclose(fs);
  264.     unlink("sit+temp");
  265. }
  266.  
  267. cp2(x,dest)
  268. unsigned short x;
  269. char dest[];
  270. {
  271.     dest[0] = x>>8;
  272.     dest[1] = x;
  273. }
  274.  
  275. cp4(x,dest)
  276. unsigned long x;
  277. char dest[];
  278. {
  279.     dest[0] = x>>24;
  280.     dest[1] = x>>16;
  281.     dest[2] = x>>8;
  282.     dest[3] = x;
  283. }
  284.