home *** CD-ROM | disk | FTP | other *** search
- char *revision = "3.24";
- /*
- ** shar.c
-
- Defined functions:
- Rname(file)
- exit_incompat()
- gen_mkdir(path)
- gen_mkdir_script(path)
- setTOUCH()
- header(argc,argv)
- helpuser()
- main(argc,argv)
- mode_map(mode,mode_str)
- shar(file)
-
- */
- /*+:EDITS:*/
- /*:05-10-1990-20:39-wht@n4hgf-altos does not not like at-sign in filenames */
- /*:05-10-1990-13:38-wht@n4hgf-add -V Vanilla mode */
- /*:05-07-1990-00:06-wht@n4hgf-test all mallocs for Purity Of Essence */
- /*:05-07-1990-00:06-wht@n4hgf-add -S switch */
- /*:05-05-1990-01:37-relay.EU.net!rivm!a3-dont assume vax is running BSD */
- /*:04-18-1990-02:01-wht@n4hgf-3.20 rhg@cps.com did all the NICE work */
- /*:04-17-1990-14:30-rhg@cps.com-pretty up if-then-else-fi in shar file */
- /*:04-17-1990-12:13-rhg@cps.com-add Split and renamed old -l to -L */
- /*:04-17-1990-12:13-rhg@cps.com-add -c option to shar file execution */
- /*:04-17-1990-11:20-rhg@cps.com-simplify TOUCH logic in shar file */
- /*:04-17-1990-10:27-rhg@cps.com-create setTOUCH to avoid duplicate code */
- /*:04-17-1990-04:43-rhg@cps.com-add missing && to commands in shar file(s) */
- /*:04-17-1990-02:03-rhg@cps.com-add Compress */
- /*:04-16-1990-17:08-rhg@cps.com-add AvoidPipes as well as code to use pipes */
- /*:04-03-1990-20:09-wht@n4hgf-3.11 */
- /*:04-01-1990-13:20-pat@rwing-correct case on M option in getopt() call */
- /*:04-01-1990-13:50-pat@rwing-change defaults on -v, -w to be on */
- /*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */
- /*:03-28-1990-15:56-wht@n4hgf-add mode and length net.bandwidth chrome */
- /*:03-28-1990-14:23-wht@n4hgf-correct some runtime diagnostics */
- /*:11-14-1989-02:21-wht-SHAR_EOF was botched if last file char not newline */
- /*:11-02-1989-14:11-wht-add touch -am */
-
- /*
- Shar puts readable text files together in a package
- from which they are easy to extract.
- earlier attribution wht@n4hgf has: decvax!microsof!uw-beave!jim
- (James Gosling at CMU)
- */
- /*
- * I have made several mods to this program:
- *
- * 1) the -----Cut Here-----... now preceds the script.
- * 2) the cat has been changed to a sed which removes a prefix
- * character from the beginning of each line of the extracted
- * file, this prefix character is added to each line of the archived
- * files and is not the same as the first character of the
- * file delimeter.
- * 3) added several options:
- * -c - add the -----Cut Here-----... line.
- * -d'del' - change the file delimeter to del.
- * -s - cause the resulting script to print the wc of
- * the orignal file and the wc of the extracted
- * file.
- *
- * Michael A. Thompson
- * Dalhousie University
- * Halifax, N.S., Canada.
- */
-
- /*
- * I, too, have been hacking this code. This is the version on sixhub
- * bill davidsen (davidsen@sixhub.uucp)
- *
- * - added support for binary files
- * - automatic creation of limited size multiple file archives,
- * each of which may be unpacked separately, and with sequence
- * checking.
- * - support for mixed text and binary files
- * - preserve file permissions
- * - restore to filename rather than pathname
- *
- */
- /*
- * One good hack deserves another ... this version generates shell
- * code which attempts to create missing directories
- * handle deviants sun, vax, pyr (pyramid), SCO XENIX/UNIX automatically
- * for sequent, add -DBSD42
- * force Verbose on
- * if unsharing system's touch Sys V compatible (allows touch -m),
- * restore file dates
- * -n switch puts an alpha "name" in header
- * -a (if also -n) puts "Submitted-by:" & "Archive-name: <name>/part##
- * use getopt
- * as well as some other chrome-plated junque
- * ...!gatech!emory!tridom!wht (wht%n4hgf@gatech.edu) Warren Tucker
- *
- * 3.11 - Fri Apr 6 14:21:51 EDT 1990
- * With due deference to davidsen@sixhub, more changes..... copies
- * of this, like 3.10, were mailed to him:
- * From wht Fri Apr 6 15:14:30 1990 remote from n4hgf
- * Received: by n4hgf.UUCP (smail2.5-UNIX/386 5.3.2)
- * id AA01781; 6 Apr 90 15:14:30 EDT (Fri)
- * Date: Fri, 6 Apr 90 15:14:30 EDT
- * X-Mailer: Mail User's Shell (6.5 4/17/89)
- * From: wht@n4hgf (Warren Tucker)
- * To: davidsen@sixhub
- * Subject: shar 3.11
- * X-Bang-Reply-to: gatech!n4hgf!wht -or- emory!tridom!n4hgf!wht
- * Reply-to: wht%n4hgf@gatech.edu
- * Message-Id: <9004061514.AA01781@n4hgf.UUCP>
- *
- * 1. changes suggested by pat@rwing (Pat Myrto) and silvert@cs.dal.ca
- * (Bill Silvert)
- * 2. fixes to who_am_i code in who@where.c
- *
- * 3.20 - Wed Apr 18 01:58:32 EDT 1990
- * changes were made per edit notes by
- From: gatech!mailrus!uunet!cpsolv.CPS.COM!rhg (Richard H. Gumpertz)
- * ...!gatech!n4hgf!wht (wht%n4hgf@gatech.edu) Warren Tucker
- *
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <time.h>
- #include <sys/stat.h>
-
- /* assume system v unless otherwise fixed */
- #if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42) && !defined(SYS5)
- #define BSD42
- #endif
- #if defined(sun) /* this miscreant doesn't exactly fit BSD or SYSV */
- #undef BSD42
- #undef SYS5
- #endif
- #if !defined(BSD42) && !defined(sun) && !defined(SYS5)
- #define SYS5
- #endif
-
- #if defined(sun) || defined(BSD42)
- #define strchr index
- #define strrchr rindex
- #endif
-
- char *strchr();
- char *strrchr();
- #ifdef __STDC__ /* my concession to ANSI-pansiness */
- void *malloc();
- #else
- char *malloc();
- #endif
- FILE *fdopen();
- FILE *popen();
-
- #define DELIM "SHAR_EOF"/* put after each file */
- #define PREFIX1 'X' /* goes in front of each line */
- #define PREFIX2 'Y' /* goes in front of each line if Delim
- * starts with PREFIX1 */
- #define PREFIX (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1)
- #define WC "wc -c"
-
- int Archive_name = 0; /* option to generate "Archive-name:" headers */
- int Verbose = 1; /* option to provide append/extract feedback */
- int Wc_c = 1; /* option to provide wc checking */
- char *Delim = DELIM; /* pointer to delimiter string */
- int Cut = 0; /* option to provide cut mark */
- int Binary = 0; /* flag for binary files */
- int AvoidPipes = 0; /* use temp file instead of pipe to feed uudecode, etc.
- (better error detection at expense of disk space) */
- int Vanilla = 0; /* no Brown-Shirt mode */
- int Compress = 0; /* run input files through compress (requires Binary) */
- int Mixed = 0; /* mixed text and binary files */
- int eXists = 0; /* check if file exists */
- int InterOW = 0; /* interactive overwrite */
- int PosParam = 0; /* allow positional parameters */
- int FileStrip; /* strip directories from filenames */
- #ifdef DEBUG
- int de_bug = 0; /* switch for debugging on */
- #define DeBug(f,v) if (de_bug) printf(f, v)
- #else /* normal compile */
- #define DeBug(f,v) /* do nothing */
- #endif
-
- FILE *fpout = stdout;
- char *Rname(); /* file restore name */
- unsigned limit = 0;
- int Split = 0; /* Split files in the middle */
- long ftell();
- long TypePos; /* position for archive type message */
- long EndHeadPos; /* position for first file in the shar file */
- char outname[50]; /* base for output filename */
- char filename[50]; /* actual output filename */
- char *sharname = (char *)0;
- char *submitter = (char *)0;
- int filenum = 0; /* output file # */
- struct stat fst; /* check file type, access */
-
- main(argc,argv)
- char **argv;
- {
- int status = 0;
- int stdin_file_list = 0;
- char *oname;
- int c;
- extern int optind;
- extern char *optarg;
-
- while((c = getopt(argc,argv,"VSvwd:btCxXcfMpPas:n:l:L:o:h")) != -1)
- {
- switch(c)
- {
- case 'V':
- Vanilla = 1;
- break;
- case 'S':
- stdin_file_list = 1;
- break;
- case 'v':
- Verbose = 0;
- break;
- case 'w':
- Wc_c = 0;
- break;
- case 'd':
- Delim = optarg;
- break;
- case 'b': /* binary files */
- Binary = 1;
- Compress = 0;
- break;
- case 't': /* text mode */
- Binary = 0;
- Compress = 0;
- break;
- case 'C': /* Compress */
- Binary = 1;
- Compress = 1;
- break;
- case 'x': /* does the file exist */
- eXists = 1;
- if(InterOW || Split)
- exit_incompat();
- break;
- case 'X': /* does the file exist */
- InterOW = 1;
- if(eXists || Split)
- exit_incompat();
- eXists = 1;
- break;
- case 'c':
- Cut = 1;
- break;
- case 'f': /* filenames only */
- FileStrip = 1;
- break;
- case 'M': /* mixed text and binary */
- Mixed = 1;
- break;
- case 'p': /* allow positional parameters */
- PosParam = 1;
- break;
- case 'P': /* use temp files instead of pipes in the shar file */
- AvoidPipes = 1;
- break;
- case 'l': /* soft size limit in k */
- if((limit = atoi(optarg)) > 1)
- --limit;
- Split = 0;
- DeBug("Soft limit %dk\n",limit);
- break;
- case 'L': /* hard size limit in k */
- if(eXists)
- exit_incompat();
- if((limit = atoi(optarg)) > 1)
- --limit;
- Split = (limit != 0);
- AvoidPipes = 1;
- DeBug("Hard limit %dk\n",limit);
- break;
- case 'n': /* name of archive */
- sharname = optarg;
- break;
- case 's': /* submitter */
- submitter = optarg;
- break;
- case 'a': /* generate Archive-name: headers */
- Archive_name = 1;
- break;
- case 'o': /* specify output file */
- oname = optarg;
- strcpy(outname,oname);
- strcat(outname,".");
- filenum = 1;
- strcpy(filename,outname);
- strcat(filename,"01");
- fpout = fopen(filename,"w");
- if(!fpout)
- { /* creation error */
- perror("can't create output file");
- exit(1);
- }
- break;
- #ifdef DEBUG
- case '$': /* totally undocumented $ option, debug on */
- de_bug = 1;
- break;
- #endif
- default: /* invalid option */
- case 'h': /* help */
- helpuser();
- break;
- }
- }
-
- if(Vanilla)
- {
- fprintf(stderr,"Vanilla mode disabling years of progress :-)\n");
- if(Binary || Mixed || Compress || PosParam)
- fprintf(stderr,"WARNING: non-Text storage options overridden.\n");
- Wc_c = 0;
- Binary = 0;
- Compress = 0;
- InterOW = 0;
- Mixed = 0;
- PosParam = 0;
- AvoidPipes = 0;
- }
-
- if(stdin_file_list)
- {
- char stdin_buf[258];
- argc = 0;
- if(!(argv = (char **)malloc(1024 * sizeof(char *))))
- goto MEMORY_ERROR;
- stdin_buf[0] = 0;
- while(fgets(stdin_buf,sizeof(stdin_buf),stdin))
- {
- if(argc == 1024)
- {
- fprintf(stderr,"max files from stdin is 1024!\n");
- exit(1);
- }
- if(stdin_buf[0])
- stdin_buf[strlen(stdin_buf) - 1] = 0;
- if(!(argv[argc] = malloc(strlen(stdin_buf) + 1)))
- {
- MEMORY_ERROR: /* NOT likely, but free software must pure as snow! */
- fprintf(stderr,"out of memory handling stdin input at %d\n",
- argc);
- exit(1);
- }
- strcpy(argv[argc],stdin_buf);
- argc++;
- stdin_buf[0] = 0;
- }
- optind = 0;
- }
-
- if(optind >= argc)
- {
- fprintf(stderr,"shar: No input files\n");
- helpuser();
- exit(1);
- }
-
- if(Archive_name && !sharname)
- {
- fprintf(stderr,"shar: -n must accompany -a\n");
- helpuser();
- exit(1);
- }
-
- if(!submitter)
- {
- if(!(submitter = malloc(128)))
- {
- fprintf(stderr,"memory allocation failed\n"); /* NOT likely */
- exit(1);
- }
- who_where(submitter);
- }
-
- if(header(argc-optind,&argv[optind]))
- exit(2);
-
- if(InterOW)
- {
- Verbose = 1;
- fprintf(fpout,"wish=\n");
- if(Archive_name)
- {
- printf("PLEASE do not submit -X shars to the usenet or other\n");
- printf("public networks. They will cause problems.\n");
- }
- }
-
- EndHeadPos = ftell(fpout);
-
- while(optind < argc)
- { /* process positional parameters and files */
- if(PosParam)
- { /* allow -b and -t and -C inline */
- if(strcmp(argv[optind],"-b") == 0)
- { /* set binary */
- Binary = 1;
- Compress = 0;
- optind++;
- continue;
- }
- if(strcmp(argv[optind],"-t") == 0)
- { /* set mode text */
- Binary = 0;
- Compress = 0;
- optind++;
- continue;
- }
- if(strcmp(argv[optind],"-C") == 0)
- { /* set compress */
- Binary = 1;
- Compress = 1;
- optind++;
- continue;
- }
- }
- status += shar(argv[optind++]);
- }
-
- /* delete the sequence file, if any */
- if(Split && filenum > 1)
- {
- fputs("rm -f shar3_seq_.tmp\n",fpout);
- fputs("echo \"You have unpacked the last part\"\n",fpout);
- if(!Verbose)
- fprintf(stderr,"Created %d files\n",filenum);
- }
- fputs("exit 0\n",fpout);
- exit(status);
- }
-
- /*+-----------------------------------------------------------------------
- mode_map(mode,mode_str) build drwxrwxrwx string
- ------------------------------------------------------------------------*/
- char *
- mode_map(mode,mode_str)
- unsigned short mode;
- char *mode_str;
- {
- register unsigned ftype = mode & S_IFMT;
- register char *rtn;
- static char result[12];
-
- rtn = (mode_str == (char *)0) ? result : mode_str;
-
- /* drwxrwxrwx */
- /* 0123456789 */
- strcpy(rtn,"----------");
-
- #ifdef THIS_IS_NOT_NEEDED_FOR_SHAR
- switch(ftype)
- {
- case S_IFIFO: *rtn = 'p'; break; /* FIFO (named pipe) */
- case S_IFDIR: *rtn = 'd'; break; /* directory */
- case S_IFCHR: *rtn = 'c'; break; /* character special */
- case S_IFBLK: *rtn = 'b'; break; /* block special */
- case S_IFREG: *rtn = '-'; break; /* regular */
-
- #if defined(sun) | defined(BSD42)
- case S_IFLNK: *rtn = 'l'; break; /* symbolic link */
- case S_IFSOCK: *rtn = 's'; break; /* socket */
- #endif
-
- #if defined (SYS5)
- case S_IFNAM: /* name space entry */
- if(mode & S_INSEM) /* semaphore */
- {
- *rtn = 's';
- break;
- }
- if(mode & S_INSHD) /* shared memory */
- {
- *rtn = 'm';
- break;
- }
- #endif
-
- default: *rtn = '?'; break; /* ??? */
- }
- #endif /* THIS_IS_NOT_NEEDED_FOR_SHAR */
-
- if(mode & 000400) *(rtn + 1) = 'r';
- if(mode & 000200) *(rtn + 2) = 'w';
- if(mode & 000100) *(rtn + 3) = 'x';
- if(mode & 004000) *(rtn + 3) = 's';
- if(mode & 000040) *(rtn + 4) = 'r';
- if(mode & 000020) *(rtn + 5) = 'w';
- if(mode & 000010) *(rtn + 6) = 'x';
- if(mode & 002000) *(rtn + 6) = 's';
- if(mode & 000004) *(rtn + 7) = 'r';
- if(mode & 000002) *(rtn + 8) = 'w';
- if(mode & 000001) *(rtn + 9) = 'x';
- if(mode & 001000) *(rtn + 9) = 't';
-
- return(rtn);
-
- } /* end of mode_map */
-
- void
- setTOUCH()
- {
- if(Vanilla)
- return;
- fputs("if touch 2>&1 | fgrep '[-amc]' > /dev/null\n",fpout);
- fputs(" then TOUCH=touch\n",fpout);
- fputs(" else TOUCH=true\n",fpout);
- fputs("fi\n",fpout);
- } /* end of setTOUCH */
-
- header(argc,argv)
- char **argv;
- {
- int i;
- int status;
- FILE *fpsource; /* pipe temp */
- char s128[128];
- long now;
- struct tm *utc;
- struct tm *gmtime();
-
- /* see if any conflicting options */
- if(limit && !filenum)
- { /* can't rename what you don't have */
- fprintf(stderr,"Can't use -l or -L option without -o\n");
- helpuser();
- return(1);
- }
-
- for(i = 0; i < argc; i++)
- { /* skip positional parameters */
- if(PosParam &&
- (strcmp(argv[i],"-b") == 0 ||
- strcmp(argv[i],"-t") == 0 ||
- strcmp(argv[i],"-C") == 0))
- continue;
-
- /* see if access and correct type */
- if(access(argv[i],4))
- {
- fprintf(stderr,"shar: Can't access %s\n",argv[i]);
- return(1);
- }
-
- /* get file type */
- stat(argv[i],&fst);
- status = fst.st_mode & S_IFMT;
-
- /* at this point I check to see that this is a regular file */
- if(status != S_IFREG)
- { /* this is not a regular file */
- fprintf(stderr,"shar: %s is not a regular file\n",argv[i]);
- return(1);
- }
- }
-
- if(Archive_name)
- {
- fprintf(fpout,"Submitted-by: %s\n",submitter);
- fprintf(fpout,"Archive-name: %s%s%02d\n\n",
- sharname,(strchr(sharname,'/')) ? "" : "/part",
- (filenum) ? filenum : 1);
- }
-
- if(Cut)
- fputs("---- Cut Here and unpack ----\n",fpout);
- fputs("#!/bin/sh\n",fpout);
- if(sharname)
- fprintf(fpout,"# This is %s, a shell archive (shar %s)\n",
- sharname,revision);
- else
- fprintf(fpout,"# This is a shell archive (shar %s)\n",revision);
-
- time(&now);
- utc = gmtime(&now);
- fprintf(fpout,"# made %02d/%02d/%04d %02d:%02d UTC ",
- utc->tm_mon + 1,utc->tm_mday,utc->tm_year + 1900,
- utc->tm_hour,utc->tm_min);
-
- fputs("by ",fpout);
- fputs(submitter,fpout);
- fputs("\n",fpout);
-
- #if defined(SYS5)
- if(!(fpsource = popen("/bin/pwd","r")))
- return(-1);
- fgets(s128,sizeof(s128),fpsource);
- s128[strlen(s128) - 1] = 0;
- fclose(fpsource);
- #else
- #if defined(BSD42) || defined(sun)
- getwd(s128);
- #else
- #include "Need_conditional_compile_fix"
- #endif
- #endif
- fprintf(fpout,"# Source directory %s\n",s128);
-
- fprintf(fpout,"#\n# existing files %s be overwritten\n",
- (eXists) ? "will NOT"
- : ((InterOW) ? "MAY" : "WILL"));
- if(InterOW)
- fprintf(fpout,"# The unsharer will be INTERACTIVELY queried.\n");
-
- if(Vanilla)
- {
- fprintf(fpout,
- "# This format requires very little intelligence at unshar time.\n");
- fputs("# ",fpout);
- if(eXists)
- fputs("\"if test\", ",fpout);
- fputs("\"echo\" and \"sed\" will be needed.\n",fpout);
- }
-
- if(Split)
- { /* may be split, explain */
- fputs("#\n",fpout);
- TypePos = ftell(fpout);
- fprintf(fpout,"%-75s\n%-75s\n","#","#");
- }
-
- fputs("#\n# This shar contains:\n",fpout);
- fputs("# length mode name\n",fpout);
- fputs("# ------ ---------- ------------------------------------------\n",
- fpout);
- for(i = 0; i < argc; i++)
- { /* output names of files but not parameters */
- if(PosParam &&
- (strcmp(argv[i],"-b") == 0 ||
- strcmp(argv[i],"-t") == 0 ||
- strcmp(argv[i],"-C") == 0))
- continue;
- stat(argv[i],&fst);
- fst.st_mode &= ~(07000); /* turn off setuid, setgid and sticky bits */
- fprintf(fpout,"# %6ld %s %s\n",fst.st_size,
- mode_map(fst.st_mode,(char *)0),Rname(argv[i]));
- }
- fputs("#\n",fpout);
-
- setTOUCH();
-
- if(Split)
- { /* now check the sequence */
- fputs("if test -r shar3_seq_.tmp; then\n",fpout);
- fputs("\techo \"Must unpack archives in sequence!\"\n",fpout);
- fputs("\tnext=`cat shar3_seq_.tmp`; ",fpout);
- fputs("echo \"Please unpack part $next next\"\n\texit 1\nfi\n",fpout);
- }
- return(0);
- }
-
- #define MAX_MKDIR_ALREADY 128 /* ridiculously enough */
- char *mkdir_already[MAX_MKDIR_ALREADY];
- int mkdir_already_count = 0;
-
- void
- gen_mkdir(path)
- char *path;
- {
- register int ialready;
- char *cptr;
-
- /* if already generated code for this dir creation, dont do again */
- for(ialready = 0; ialready < mkdir_already_count; ialready++)
- {
- if(!strcmp(path,mkdir_already[ialready]))
- return;
- }
-
- /* haven't done this one */
- if(mkdir_already_count == MAX_MKDIR_ALREADY)
- {
- fprintf(stderr,"too many directories for mkdir generation\n");
- exit(255);
- }
- if(!(cptr = mkdir_already[mkdir_already_count++] = malloc(strlen(path)+1)))
- {
- fprintf(stderr,"out of memory for mkdir generation\n");
- exit(255);
- }
- strcpy(cptr,path);
-
- /* generate the text */
- fprintf(fpout,"if test ! -d '%s'; then\n",path);
- if(Verbose)
- fprintf(fpout," echo \"x - creating directory %s\"\n",path);
- fprintf(fpout," mkdir '%s'\n",path);
- fprintf(fpout,"fi\n");
-
- } /* end of gen_mkdir */
-
- void
- gen_mkdir_script(path)
- register char *path;
- {
- register char *cptr;
-
- for(cptr = strchr(path,'/'); cptr; cptr = strchr(cptr + 1,'/'))
- {
- /* avoid empty string if leading or double '/' */
- if(cptr == path || *(cptr - 1) == '/')
- continue;
- /* omit '.' */
- if((*(cptr - 1) == '.') && ((cptr == path + 1) || (*(cptr - 2) == '/')))
- continue;
- *cptr = 0; /* temporarily terminate string */
- gen_mkdir(path);
- *cptr = '/';
- }
- } /* end of gen_mkdir_script */
-
- shar(file)
- char *file;
- {
- char line[BUFSIZ];
- FILE *fpsource;
- long cursize,remaining,ftell();
- int split = 0; /* file split flag */
- char *filetype; /* text or binary */
- char *RstrName; /* name for restore */
- struct tm *lt;
- char *filename_base;
-
- /* get file size, dates, and mode for later */
- stat(file,&fst);
-
- /* if limit set, get the current output length */
- if(limit)
- {
- cursize = ftell(fpout);
- remaining = (limit * 1024L) - cursize;
- DeBug("In shar: remaining size %ld\n",remaining);
-
- if(!Split && cursize > EndHeadPos &&
- (Binary ? fst.st_size + fst.st_size/3 : fst.st_size) > remaining)
- { /* change to another file */
- DeBug("Newfile, remaining %ld, ",remaining);
- DeBug("limit still %d\n",limit);
-
- fprintf(fpout,
- "echo \"End of part %d, continue with part %d\"\n",
- filenum,filenum + 1);
- fprintf(fpout,"exit 0\n");
-
- fclose(fpout);
-
- /* form the next filename */
- sprintf(filename,"%s%02d",outname,++filenum);
- fpout = fopen(filename,"w");
-
- if(Archive_name)
- {
- fprintf(fpout,"Submitted-by: %s\n",submitter);
- fprintf(fpout,"Archive-name: %s%s%02d\n\n",
- sharname,(strchr(sharname,'/')) ? "." : "/part",
- (filenum) ? filenum : 1);
- }
-
- if(Cut)
- fputs("---- Cut Here and unpack ----\n",fpout);
- if(!(filename_base = strrchr(filename,'/')))
- filename_base = filename;
- else
- filename_base++;
-
- fprintf(fpout,"#!/bin/sh\n");
- fprintf(fpout,"# This is part %02d of %s\n",
- filenum,(sharname) ? sharname : "a multipart archive");
-
- setTOUCH();
-
- EndHeadPos = ftell(fpout);
- }
- }
-
- /* determine the name to use for restore */
- RstrName = Rname(file);
-
- fputs("# ============= ",fpout);
- fputs(RstrName,fpout);
- fputs(" ==============\n",fpout);
-
- gen_mkdir_script(RstrName);
-
- /* if mixed, determine the file type */
- if(Mixed)
- {
- int count;
- sprintf(line,"file %s | egrep -c \"text|shell\"",file);
- fpsource = popen(line,"r");
- fscanf(fpsource,"%d",&count);
- pclose(fpsource);
- Binary = (count != 1);
- }
-
- if(Binary)
- { /* fork a uuencode process */
- static int pid,pipex[2];
-
- pipe(pipex);
- fflush(fpout);
-
- if(pid = fork())
- { /* parent, create a file to read */
- if(pid < 0)
- {
- fprintf(stderr,"could not fork!\n");
- exit(1);
- }
- close(pipex[1]);
- fpsource = fdopen(pipex[0],"r");
- filetype = (Compress ? "Compressed" : "Binary");
- }
- else
- { /* start writing the pipe with encodes */
- FILE *outptr;
-
- if(Compress)
- {
- sprintf(line, "compress < %s", file);
- fpsource = popen(line, "r");
- }
- else
- fpsource = fopen(file, "rb");
- outptr = fdopen(pipex[1],"w");
- fprintf(outptr,"begin 600 %s\n",
- (Compress ? "shar3_cmp_.tmp" : RstrName));
- encode(fpsource,outptr);
- fprintf(outptr,"end\n");
- if(Compress)
- pclose(fpsource);
- else
- fclose(fpsource);
- exit(0);
- }
- }
- else
- {
- fpsource = fopen(file,"r");
- filetype = "Text";
- }
-
- if(fpsource)
- {
- /* protect existing files */
- if(eXists)
- {
- fprintf(fpout,"if test X\"$1\" != X\"-c\" -a -f '%s'; then\n",
- RstrName);
- if(InterOW)
- {
- fprintf(fpout,"\tcase $wish in\n");
- fprintf(fpout,"\tA*|a*) echo x - overwriting '%s';;\n",
- RstrName);
- fprintf(fpout,
- "\t*) echo \"? - overwrite '%s' -- [No], [Y]es, [A]ll, [Q]uit? \"\n",
- RstrName);
- fprintf(fpout,"\t\tread wish;;\n");
- fprintf(fpout,"\tesac\n");
- fprintf(fpout,"\tcase $wish in\n");
- fprintf(fpout,"\tQ*|q*) echo aborted; exit 86;;\n");
- fprintf(fpout,"\tA*|a*|Y*|y*) x=Y;;\n");
- fprintf(fpout,"\t*) x=N;;\n");
- fprintf(fpout,"\tesac\n");
- fprintf(fpout,"else\n");
- fprintf(fpout,"\tx=Y\n");
- fprintf(fpout,"fi\n");
- fprintf(fpout,"if test $x != Y; then\n");
- fprintf(fpout,"\techo x - skipping '%s'\n",RstrName);
- }
- else
- fprintf(fpout,"\techo \"File already exists: skipping '%s'\"\n",
- RstrName);
- fprintf(fpout,"else\n");
- }
-
- fprintf(stderr,"shar: saving %s (%s)\n",file,filetype);
- if(Verbose)
- { /* info on archive and unpack */
- fprintf(fpout,"echo \"x - extracting %s (%s)\"\n",
- RstrName,filetype);
- }
- if(Binary)
- { /* run sed through uudecode (via temp file if might get split) */
- fprintf(fpout, "sed 's/^%c//' << '%s' %s &&\n",
- PREFIX,Delim,
- (AvoidPipes ? "> shar3_tmp_.tmp" : "| uudecode"));
- }
- else
- { /* just run it into the file */
- fprintf(fpout,"sed 's/^%c//' << '%s' > %s &&\n",
- PREFIX,Delim,RstrName);
- }
- while(fgets(line,BUFSIZ,fpsource))
- { /* output a line and test the length */
- fprintf(fpout,"%c%s",PREFIX,line);
- if(Split && (remaining -= strlen(line) + 2) < 0)
- { /* change to another file */
- DeBug("Newfile, remaining %ld, ",remaining);
- DeBug("limit still %d\n",limit);
-
- if(line[strlen(line) - 1] != '\n')
- fputc('\n',fpout);
-
- fprintf(fpout,"%s\n",Delim);
- if(Verbose)
- { /* output some reassurance */
- fprintf(fpout,
- "echo \"End of %s part %d\"\n",
- (sharname) ? sharname : "",filenum);
- fprintf(fpout,
- "echo \"File %s is continued in part %d\"\n",
- RstrName,filenum + 1);
- }
- else
- fprintf(fpout,
- "echo \"End of part %d, continue with part %d\"\n",
- filenum,filenum + 1);
- fprintf(fpout,"echo \"%d\" > shar3_seq_.tmp\n",filenum + 1);
- fprintf(fpout,"exit 0\n");
-
- if(filenum == 1)
- { /* rewrite the info lines on the firstheader */
- fseek(fpout,TypePos,0);
- fprintf(fpout,"%-75s\n%-75s\n",
- "# This is part 1 of a multipart archive",
- "# do not concatenate these parts, unpack them in order with /bin/sh");
- }
- fclose(fpout);
-
- /* form the next filename */
- sprintf(filename,"%s%02d",outname,++filenum);
- fpout = fopen(filename,"w");
-
- if(Archive_name)
- {
- fprintf(fpout,"Submitted-by: %s\n",submitter);
- fprintf(fpout,"Archive-name: %s%s%02d\n\n",
- sharname,(strchr(sharname,'/')) ? "." : "/part",
- (filenum) ? filenum : 1);
- }
-
- if(Cut)
- fputs("---- Cut Here and unpack ----\n",fpout);
- if(!(filename_base = strrchr(filename,'/')))
- filename_base = filename;
- else
- filename_base++;
-
- fprintf(fpout,"#!/bin/sh\n");
- fprintf(fpout,
- "# this is %s (part %d of %s)\n",
- filename_base,
- filenum,
- (sharname) ? sharname : "a multipart archive");
- fputs("# do not concatenate these parts, ",fpout);
- fputs("unpack them in order with /bin/sh\n",fpout);
- fprintf(fpout,"# file %s continued\n#\n",RstrName);
-
- setTOUCH();
-
- fputs("if test ! -r shar3_seq_.tmp; then\n",fpout);
- fputs("\techo \"Please unpack part 1 first!\"\n",fpout);
- fputs("\texit 1\nfi\n",fpout);
- fputs("(read Scheck\n",fpout);
- fprintf(fpout,
- " if test \"$Scheck\" != %d; then\n",filenum);
- fputs("\techo \"Please unpack part $Scheck next!\"\n",
- fpout);
- fputs("\texit 1\n",fpout);
- fputs(" else\n\texit 0\n fi\n",fpout);
- fputs(") < shar3_seq_.tmp || exit 1\n",fpout);
-
- if(Verbose)
- { /* keep everybody informed */
- fprintf(stderr,"Starting file %s\n",filename);
- fprintf(fpout,
- "echo \"x - Continuing file %s\"\n",RstrName);
- }
- fprintf(fpout,
- "sed 's/^%c//' << '%s' >> %s &&\n",
- PREFIX,Delim,
- (Binary ? "shar3_tmp_.tmp" : RstrName));
- remaining = limit * 1024L;
- split = 1;
- }
- }
-
- (void) fclose(fpsource);
-
- if(line[strlen(line) - 1] != '\n')
- fputc('\n',fpout);
-
- fprintf(fpout,"%s\n",Delim);
- if(split && Verbose)
- fprintf(fpout,
- "echo \"File %s is complete\" &&\n",RstrName);
-
- /* if this file was uuencoded w/Split, decode it and drop the temp */
- if(Binary && AvoidPipes)
- {
- if(Verbose)
- fprintf(fpout,"echo \"uudecoding file %s\" &&\n",RstrName);
- fprintf(fpout,
- "uudecode < shar3_tmp_.tmp && rm -f shar3_tmp_.tmp &&\n");
- }
-
- /* if this file was compressed, uncompress it and drop the temp */
- if(Compress)
- {
- if(Verbose)
- fprintf(fpout,"echo \"uncompressing file %s\" &&\n",RstrName);
- fprintf(fpout,
- "compress -d < shar3_cmp_.tmp > %s && rm -f shar3_cmp_.tmp &&\n",
- RstrName);
- }
-
- if(!Vanilla)
- {
- /* set the dates as they were */
- lt = localtime(&fst.st_mtime);
- fprintf(fpout,"$TOUCH -am %02d%02d%02d%02d%02d %s &&\n",
- lt->tm_mon + 1,lt->tm_mday,lt->tm_hour,lt->tm_min,
- lt->tm_year,RstrName);
-
- /* set the permissions as they were */
- fprintf(fpout,"chmod %04o %s ||\n",
- fst.st_mode & 00777,RstrName);
-
- /* report an error if any of the above failed */
- fprintf(fpout,"echo \"restore of %s failed\"\n",RstrName);
-
- if(Wc_c)
- { /* validate the transferred file */
- FILE *pfp;
- char command[BUFSIZ];
-
- sprintf(command,"%s %s",WC,file);
- if((pfp = popen(command,"r")))
- {
- char wc[BUFSIZ];
-
- fscanf(pfp,"%s",wc);
- fprintf(fpout,"set `%s %s`;Wc_c=$1\n",
- WC,RstrName);
- fprintf(fpout,
- "if test \"$Wc_c\" != \"%s\"; then\n",wc);
- fprintf(fpout,
- "\techo original size %s, current size $Wc_c\nfi\n",
- wc);
- pclose(pfp);
- }
- }
- }
-
- /* if the exists option is in place close the if */
- if(eXists)
- fprintf(fpout,"fi\n");
-
- return(0);
- }
- else
- {
- fprintf(stderr,"shar: Can't open %s (%s): ",file,filetype);
- perror("");
- return(1);
- }
- }
-
- char *
- Rname(file)
- register char *file;
- {
- register char *RstrName;
-
- if(FileStrip)
- { /* use just the filename */
- RstrName = file+strlen(file);
- while(RstrName > file && *RstrName != '/')
- RstrName--;
- if(*RstrName == '/') RstrName++;
- }
- else
- RstrName = file;
- if(!strncmp(RstrName,"./",2))
- RstrName += 2;
- return(RstrName);
- }
-
- /*****************************************************************
- | exit_incompat - incompatible options
- ****************************************************************/
-
- exit_incompat()
- {
- fputs("You may only specify one of -L, -X or -x\n",stderr);
- exit(1);
- }
-
- char *helpinfo[] =
- {
- "-V produce \"vanilla\" shars demanding little of the unshar environment",
- "-v verbose messages OFF while executing",
- "-w don't check with 'wc -c' after unpack",
- "-n Name of archive (documentation)",
- "-a Generate Submitted-by: & Archive-name: headers",
- "-s override automatically determined submitter name",
- "-x don't overwrite existing files",
- "-X interactively overwrite existing files (NOT FOR NET SHARS)",
- "-b treat all files as binary, use uuencode",
- "-t treat all files as text (default)",
- "-C compress and uuencode all files",
- "-p allow positional parameter options. The options \"-b\" and \"-t\"",
- " and \"-C\" may be embedded, and files to the right of the",
- " option will be processed in the specified mode",
- "-M mixed mode. Determine if the files are text or",
- " binary and archive correctly.",
- "-P use temp files instead of pipes in the shar file",
- "-c start the shar with a cut line",
- "-f restore by filename only, rather than path",
- "-dXXX use XXX to delimit the files in the shar",
- "-oXXX (or -o XXX) output to file XXX.01 thru XXX.nn",
- "-lXX limit output file size to XXk bytes (but don't split files)",
- "-LXX limit output file size to XXk bytes (may split files)",
- "-S read files to wrap from stdin, ignoring argument line",
- "\nThe -S option reads filenames one per line from stdin; input",
- "format must be similar to 'find' output, except that if -p",
- "is specified, -b, -t or -C may be used (on lines by themselves)",
- "e.g., find . -type f -print | sort | shar -C -L50 -o /tmp/big",
- "\nThe 'o' option is required if the 'l' or 'L' option is used",
- "The 'n' option is required if the 'a' option is used",
- "The 'x' and 'L' options are incompatible",
- "\n-a generates sharname/part## headers. If the -a argument contains",
- "a '/', then /patch is not appended",
- "The automatic submitter name is trivial: essentially `whoami`@`uname`",
- (char *)0
- };
-
- helpuser()
- { /* output a command format message */
- register char **ptr;
- fprintf(stderr,
- "shar %s\nusage: shar [ options ] file [ file1 ... ] ]\n",revision);
- for(ptr = helpinfo; *ptr; ptr++)
- fprintf(stderr,"%s\n",*ptr);
-
- exit(1);
- }
- /* vi: set tabstop=4 shiftwidth=4: */
-