home *** CD-ROM | disk | FTP | other *** search
- /*
- * sit - Stuffit for UNIX
- * Puts unix data files into stuffit archive suitable for downloading
- * to a Mac. Automatically processes files output from xbin.
- *
- * Reverse engineered from unsit by Allan G. Weber, which was based on
- * macput, which was based on ...
- * Just like unsit this uses the host's version of compress to do the work.
- *
- * Examples:
- * 1) take collection of UNIX text files and make them LSC text files
- * when uncompressed on the mac:
- * sit -u -T TEXT -C KAHL file ...
- * 2) Process output from xbin:
- * xbin file1 (produces FileOne.{info,rsrc,data})
- * sit file1
- *
- * Tom Bereiter
- * ..!{rutgers,ames}!cs.utexas.edu!halley!rolex!twb
- */
- #define BSD
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include "sit.h"
- #ifdef BSD
- #include <sys/time.h>
- #include <sys/timeb.h>
- #else
- #include <time.h>
- extern long timezone;
- #endif
-
- #ifndef min
- #define min(a,b) ((a)<(b)?(a):(b))
- #endif
-
- /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
- #define TIMEDIFF 0x7c25b080
-
- struct sitHdr sh;
- struct fileHdr fh;
-
- char buf[BUFSIZ];
- char *defoutfile = "archive.sit";
- int ofd;
- ushort crc;
- int clen;
- int rmfiles;
- int unixf;
- char *Creator, *Type;
-
- usage() { fprintf(stderr,"Usage: sit file\n"); }
- extern char *optarg;
- extern int optind;
-
- main(argc,argv) char **argv; {
- int i,n;
- int total, nfiles;
- int c;
-
- while ((c=getopt(argc, argv, "ro:uC:T:")) != EOF)
- switch (c) {
- case 'r':
- rmfiles++; /* remove files when done */
- break;
- case 'o': /* specify output file */
- defoutfile = optarg;
- break;
- case 'u': /* unix file -- change '\n' to '\r' */
- unixf++;
- break;
- case 'C': /* set Mac creator */
- Creator = optarg;
- break;
- case 'T': /* set Mac file type */
- Type = optarg;
- break;
- case '?':
- usage();
- exit(1);
- }
-
- if ((ofd=creat(defoutfile,0644))<0) {
- perror(defoutfile);
- exit(1);
- }
- /* empty header, will seek back and fill in later */
- write(ofd,&sh,sizeof sh);
-
- for (i=optind; i<argc; i++) {
- n = put_file(argv[i]);
- if (n) {
- total += n;
- nfiles++;
- }
- }
- lseek(ofd,0,0);
-
- total += sizeof(sh);
- /* header header */
- strncpy(sh.sig1,"SIT!",4);
- cp2(nfiles,sh.numFiles);
- cp4(total,sh.arcLen);
- strncpy(sh.sig2,"rLau",4);
- sh.version = 1;
-
- write(ofd,&sh,sizeof sh);
- }
-
- put_file(name)
- char name[];
- {
- struct stat st;
- struct infohdr ih;
- int i,n,fd;
- long fpos1, fpos2;
- char nbuf[256], *p;
- int fork=0;
- long tdiff;
- struct tm *tp;
- #ifdef BSD
- struct timeb tbuf;
- #else
- long bs;
- #endif
-
- fpos1 = lseek(ofd,0,1); /* remember where we are */
- /* write empty header, will seek back and fill in later */
- bzero(&fh,sizeof fh);
- write(ofd,&fh,sizeof fh);
-
- /* look for resource fork */
- strcpy(nbuf,name);
- strcat(nbuf,".rsrc");
- if (stat(nbuf,&st)>=0 && st.st_size) { /* resource fork exists */
- dofork(nbuf);
- cp4(st.st_size,fh.rLen);
- cp4(clen,fh.cRLen);
- cp2(crc,fh.rsrcCRC);
- fh.compRMethod = lpzComp;
- fork++;
- }
- if (rmfiles) unlink(nbuf); /* ignore errors */
-
- /* look for data fork */
- st.st_size = 0;
- strcpy(nbuf,name);
- if (stat(nbuf,&st)<0) { /* first try plain name */
- strcat(nbuf,".data");
- stat(nbuf,&st);
- }
- if (st.st_size) { /* data fork exists */
- dofork(nbuf);
- cp4(st.st_size,fh.dLen);
- cp4(clen,fh.cDLen);
- cp2(crc,fh.dataCRC);
- fh.compDMethod = lpzComp;
- fork++;
- }
- if (fork == 0) {
- fprintf(stderr,"%s: no data or resource files\n",name);
- return 0;
- }
- if (rmfiles) unlink(nbuf); /* ignore errors */
-
- /* look for .info file */
- strcpy(nbuf,name);
- strcat(nbuf,".info");
- if ((fd=open(nbuf,0))>=0 && read(fd,&ih,sizeof(ih))==sizeof(ih)) {
- strncpy(fh.fName, ih.name,64);
- strncpy(fh.fType, ih.type, 4);
- strncpy(fh.fCreator, ih.creator, 4);
- strncpy(fh.FndrFlags, ih.flag, 2);
- strncpy(fh.cDate, ih.ctime, 4);
- strncpy(fh.mDate, ih.mtime, 4);
- }
- else { /* no info file so fake it */
- strncpy(&fh.fName[1], name,63); fh.fName[0] = min(strlen(name),63);
- /* default to LSC text file */
- strncpy(fh.fType, Type ? Type : "TEXT", 4);
- strncpy(fh.fCreator, Creator ? Creator : "KAHL", 4);
- /* convert unix file time to mac time format */
- #ifdef BSD
- ftime(&tbuf);
- tp = localtime(&tbuf.time);
- tdiff = TIMEDIFF - tbuf.timezone * 60;
- if (tp->tm_isdst)
- tdiff += 60 * 60;
- #else
- /* I hope this is right! -andy */
- time(&bs);
- tp = localtime(&bs);
- tdiff = TIMEDIFF - timezone;
- if (tp->tm_isdst)
- tdiff += 60 * 60;
- #endif
- cp4(st.st_ctime + tdiff, fh.cDate);
- cp4(st.st_mtime + tdiff, fh.mDate);
- }
- close(fd);
- if (rmfiles) unlink(nbuf); /* ignore errors */
-
- crc = updcrc(0,&fh,(sizeof fh)-2);
- cp2(crc, fh.hdrCRC);
-
- fpos2 = lseek(ofd,0,1); /* remember where we are */
- lseek(ofd,fpos1,0); /* seek back over file(s) and header */
- write(ofd,&fh,sizeof fh); /* write back header */
- fpos2=lseek(ofd,fpos2,0); /* seek forward file */
-
- return (fpos2 - fpos1);
- }
-
- dofork(name)
- char name[];
- {
- FILE *fs;
- int n, fd, ufd;
- char *p;
-
- if ((fd=open(name,0))<0) {
- perror(name);
- return 0;
- }
- if (unixf) /* build conversion file */
- if ((ufd=creat("sit+temp",0644))<0) {
- perror("sit+temp");
- return 0;
- }
- /* do crc of file: */
- crc = 0;
- while ((n=read(fd,buf,BUFSIZ))>0) {
- if (unixf) { /* convert '\n' to '\r' */
- for (p=buf; p<&buf[n]; p++)
- if (*p == '\n') *p = '\r';
- write(ufd,buf,n);
- }
- crc = updcrc(crc,buf,n);
- }
- close(fd);
- /*
- * open pipe to compress file
- * If a unix file ('\n' -> '\r' conversion) 'sit+temp' will be a new copy
- * with the conversion done. Otherwise, 'sit+temp' is just a link to
- * the input file.
- */
- if (unixf)
- close(ufd);
- else link(name,"sit+temp");
- fs = popen("compress -c -n -b 14 sit+temp","r");
- if (fs == NULL) {
- perror(name);
- return 0;
- }
- /* write out compressed file */
- clen = 0;
- while ((n=fread(buf,1,BUFSIZ,fs))>0) {
- write(ofd,buf,n);
- clen += n;
- }
- pclose(fs);
- unlink("sit+temp");
- }
-
- cp2(x,dest)
- unsigned short x;
- char dest[];
- {
- dest[0] = x>>8;
- dest[1] = x;
- }
-
- cp4(x,dest)
- unsigned long x;
- char dest[];
- {
- dest[0] = x>>24;
- dest[1] = x>>16;
- dest[2] = x>>8;
- dest[3] = x;
- }
-