wht@n4hgf.uucp (Warren Tucker) (04/07/90)
Submitted by: wht@n4hgf Archive-name: shar311/part01 #!/bin/sh # This is shar311, a shell archive (shar 3.11) # made 04/06/1990 19:13 UTC by wht@n4hgf # Source directory /u1/src/shar # # existing files WILL be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 5093 -rw-r--r-- README # 333 -rw-r--r-- Makefile # 24654 -rw-r--r-- shar.c # 8440 -rw-r--r-- unshar.c # 1169 -rw-r--r-- uushar.c # 2784 -rw-r--r-- who@where.c # touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$ if [ -s /tmp/s3_touch$$ ] then TOUCH=can else TOUCH=cannot fi rm -f /tmp/s3_touch$$ # ============= README ============== echo "x - extracting README (Text)" sed 's/^X//' << 'SHAR_EOF' > README && XSubmitted by: wht%n4hgf@gatech.edu XArchive-name: shar311/part01 X XHere is shar311, an updated version of shar 3.10, derived from 'shar2' X XI apologize as appropriate to davidsen@sixhub for his not receiving Xmy mail of Wed, 28 Mar 90 17:31:25 EST sending him an advance copy Xof shar310. The mail header for this transmission to him is: X X From wht Fri Apr 6 15:14:30 1990 remote from n4hgf X Received: by n4hgf.UUCP (smail2.5-UNIX/386 5.3.2) X id AA01781; 6 Apr 90 15:14:30 EDT (Fri) X Date: Fri, 6 Apr 90 15:14:30 EDT X X-Mailer: Mail User's Shell (6.5 4/17/89) X From: wht@n4hgf (Warren Tucker) X To: davidsen@sixhub X Subject: shar 3.11 X X-Bang-Reply-to: gatech!n4hgf!wht -or- emory!tridom!n4hgf!wht X Reply-to: wht%n4hgf@gatech.edu X Message-Id: <9004061514.AA01781@n4hgf.UUCP> X X C.gatechN26ac UUCP uux file X U wht n4hgf X # return status on failure X Z X # return address for status or input return X R wht X F D.n4hgf54ef6e7 X I D.n4hgf54ef6e7 X C rmail mailrus!uunet!crdgw1!sixhub!davidsen # XChanges from 3.10: X X1) A much simplified who_am_i() is used. The function in 3.10 X was derived from code where it was important to obtain the user X name of the login user despite su'ing, setuid, etc. This X is difficult to do in a portable fashion and not necessary X for the 'shar' application. This version of shar uses the X username assosciated with the 'real uid'; use -s to override X the automagically determined submitter name if necessary. X X2) The -X switch generates shell sequences in the generated shar X code necessary to interactively query the disposition of files X which would be overwritten if unshared. NOTE: _PLEASE_ DO NOT, X OH PLEASE, DO NOT use this option for shars submitted to public X networks. X X When -X shars are extracted, the first time a file which would be X overwritten is encountered, the user is given the option of X X overwrite 'name' -- [No], [Y]es, [A]ll, [Q]uit? X N means no for this file, continue extraction, skipping 'file' X Y means yes for this file, continue extraction, including 'file' X A means yes for this file, continue extraction, automatically X overwriting any additional files encountered X Q means quit extraction X X Credit for this idea is given to Bill Silvert <silvert@cs.dal.ca>, X Habitat Ecology Division, Bedford Inst. of Oceanography, Dartmouth, X Nova Scotia, Canada X X I repeat: NOTE _PLEASE_: DO NOT, OH PLEASE, DO NOT use this option X for shars submitted to public networks. The overhead for -X is high and X its use will SCREW UP a lot of automated unshar mechanisms in use X throughout the world when the script tries to read from standard X input (which may not be open). Specifically, the unshar program X in this distrivbution is not compatible with shars created by the X -X option. it will die horribly with complaints about shell syntax X errors. X X3) A bug in the sun version which caused a bogus read from standard X input when shar was run has been fixed. It was botched who_am_i() X that was doing it. X X4) bugs reported and fixed (thanks!) pat@rwing (Pat Myrto): X> One was the M option - it was defined as M in the usage X> message, and in the switch construct, but as m in the X> getopt() call. I also changed the defaults for wc checking X> and verbose extraction to be ON - the cmd line options X> turning these OFF (since usually these are desired to be X> on). In who@where, in the utsname structure, looking at X> sysname returns 'UNIX' - I think nodename is what you want X> to get the [system's] name. ... Also declared a X> function that gave a compiler warning (getpwuid()). X XThis version X1) generates shell code which attempts to create missing directories X2) handle deviants sun, vax, pyramid, sequent, and SCO XENIX/UNIX X automatically; for system V systems I did not catch, add -DSYS5 X to CFLAGS; for other BSD-like systems, add -DBSD42 X3) if unsharing system's touch is Sys V compatible (allows touch -m), X the unshar process restores file dates X4) An archive name may be specified for includion in the header X of the shar files( -n switch) X5) allows automatic generation of "Submitted-by: who@where" & X "Archive-name: <name>/part##" headers X6) uses getopt; no good system library should be without a copy X but it is readily available X7) other chrome-plated junque X X------------------------ usage ----------------------------------- X Xshar 3.11 Xusage: shar [ options ] file [ file1 ... ] ] X-v verbose messages OFF while executing X-w don't check with 'wc -c' after unpack X-n Name of archive (documentation) X-a Generate Submitted-by: & Archive-name: headers X-s override automatically determined submitter name X-x don't overwrite existing files X-X interactively overwrite existing files (NOT FOR NET SHARS) X-b treat all files as binary, use uuencode X-t treat all files as text (default) X-p allow positional parameter options. The options "-b" X and "-t" may be embedded, and files to the right of the X option will be processed in the specified mode X-M mixed mode. Determine if the files are text or X binary and archive correctly. X-D output date, user, and directory comments to the archive X-c start the shar with a cut line X-f restore by filename only, rather than path X-dXXX use XXX to delimit the files in the shar X-oXXX (or -o XXX) output to file XXX.01 thru XXX.nn X-lXX limit output file size to XXk bytes X XThe 'o' option is required if the 'l' option is used XThe 'n' option is required if the 'a' option is used XThe 'x' and 'l' options are incompatible X X-a generates sharname/part## headers. If you are producing patches Xyou'll need to edit -a headers (or please improve shar :-)) XThe automatic submitter name is trivial: essentially `whoami`@`uname` SHAR_EOF chmod 0644 README || echo "restore of README fails" if [ $TOUCH = can ] then touch -am 0406151290 README fi # ============= Makefile ============== echo "x - extracting Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > Makefile && X# CHK=0xDDF8 X# X# makefile for shar X# X#+:EDITS: X#:03-28-1990-14:54-wht@n4hgf-for 3.10, add who@where.c X XCFLAGS = -O X XSRC = shar.c uushar.c unshar.sh XOBJ = shar.o uushar.o who@where.o XDOC = shar.1 unshar.1 shar.readme X Xall: shar unshar X Xshar: $(OBJ) X cc $(CFLAGS) $(OBJ) -o shar X Xunshar : unshar.c X cc $(CFLAGS) unshar.c -o unshar; SHAR_EOF chmod 0644 Makefile || echo "restore of Makefile fails" if [ $TOUCH = can ] then touch -am 0328165590 Makefile fi # ============= shar.c ============== echo "x - extracting shar.c (Text)" sed 's/^X//' << 'SHAR_EOF' > shar.c && X/* CHK=0xE923 */ Xchar *revision = "3.11"; X/* X** shar.c X X Defined functions: X Rname(file) X exit_incompat() X gen_mkdir(path) X gen_mkdir_script(path) X header(argc,argv) X helpuser() X main(argc,argv) X mode_map(mode,mode_str) X shar(file) X X*/ X/*+:EDITS:*/ X/*:04-03-1990-20:09-wht@n4hgf-3.11 */ X/*:04-01-1990-13:20-pat@rwing-correct case on M option in getopt() call */ X/*:04-01-1990-13:50-pat@rwing-change defaults on -v, -w to be on */ X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */ X/*:03-28-1990-15:56-wht@n4hgf-add mode and length net.bandwidth chrome */ X/*:03-28-1990-14:23-wht@n4hgf-correct some runtime diagnostics */ X/*:11-14-1989-02:21-wht-SHAR_EOF was botched if last file char not newline */ X/*:11-02-1989-14:11-wht-add touch -am */ X X/* X Shar puts readable text files together in a package X from which they are easy to extract. X earlier attribution wht@n4hgf has: decvax!microsof!uw-beave!jim X (James Gosling at CMU) X*/ X/* X * I have made several mods to this program: X * X * 1) the -----Cut Here-----... now preceds the script. X * 2) the cat has been changed to a sed which removes a prefix X * character from the beginning of each line of the extracted X * file, this prefix character is added to each line of the archived X * files and is not the same as the first character of the X * file delimeter. X * 3) added several options: X * -c - add the -----Cut Here-----... line. X * -d'del' - change the file delimeter to del. X * -s - cause the resulting script to print the wc of X * the orignal file and the wc of the extracted X * file. X * X * Michael A. Thompson X * Dalhousie University X * Halifax, N.S., Canada. X */ X X/* X * I, too, have been hacking this code. This is the version on sixhub X * bill davidsen (davidsen@sixhub.uucp) X * X * - added support for binary files X * - automatic creation of limited size multiple file archives, X * each of which may be unpacked separately, and with sequence X * checking. X * - support for mixed text and binary files X * - preserve file permissions X * - restore to filename rather than pathname X * X */ X/* X * One good hack deserves another ... this version generates shell X * code which attempts to create missing directories X * handle deviants sun, vax, pyr (pyramid), SCO XENIX/UNIX automatically X * for sequent, add -DBSD42 X * force Verbose on X * if unsharing system's touch Sys V compatible (allows touch -m), X * restore file dates X * -n switch puts an alpha "name" in header X * -a (if also -n) puts "Submitted-by:" & "Archive-name: <name>/part## X * use getopt X * as well as some other chrome-plated junque X * ...!gatech!emory!tridom!wht (wht%n4hgf@gatech.edu) Warren Tucker X * X * 3.11 - Fri Apr 6 14:21:51 EDT 1990 X * With due deference to davidsen@sixhub, more changes..... copies X * of this, like 3.10, were mailed to him: X * From wht Fri Apr 6 15:14:30 1990 remote from n4hgf X * Received: by n4hgf.UUCP (smail2.5-UNIX/386 5.3.2) X * id AA01781; 6 Apr 90 15:14:30 EDT (Fri) X * Date: Fri, 6 Apr 90 15:14:30 EDT X * X-Mailer: Mail User's Shell (6.5 4/17/89) X * From: wht@n4hgf (Warren Tucker) X * To: davidsen@sixhub X * Subject: shar 3.11 X * X-Bang-Reply-to: gatech!n4hgf!wht -or- emory!tridom!n4hgf!wht X * Reply-to: wht%n4hgf@gatech.edu X * Message-Id: <9004061514.AA01781@n4hgf.UUCP> X * X * 1. changes suggested by pat@rwing (Pat Myrto) and silvert@cs.dal.ca X * (Bill Silvert) X * 2. fixes to who_am_i code in who@where.c X * ...!gatech!n4hgf!wht (wht%n4hgf@gatech.edu) Warren Tucker X * X */ X X#include <stdio.h> X#include <sys/types.h> X#include <time.h> X#include <sys/stat.h> X X/* assume system v unless otherwise fixed */ X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42) X#define BSD42 X#endif X#if defined(sun) /* this miscreant doesn't exactly fit BSD or SYSV */ X#undef BSD42 X#undef SYS5 X#endif X#if !defined(BSD42) && !defined(sun) X#define SYS5 X#endif X X#if defined(sun) || defined(BSD42) X#define strchr index X#define strrchr rindex X#endif X Xchar *strchr(); Xchar *strrchr(); X#ifdef __STDC__ /* my concession to ANSI-pansiness */ Xvoid *malloc(); X#else Xchar *malloc(); X#endif XFILE *fdopen(); XFILE *popen(); X X#define DELIM "SHAR_EOF"/* put after each file */ X#define PREFIX1 'X' /* goes in front of each line */ X#define PREFIX2 'Y' /* goes in front of each line if Delim X * starts with PREFIX1 */ X#define PREFIX (Delim[0] == PREFIX1 ? PREFIX2 : PREFIX1) X#define WC "wc -c" X Xint Archive_name = 0; /* option to generate "Archive-name:" headers */ Xint Verbose = 1; /* option to provide append/extract feedback */ Xint Wc_c = 1; /* option to provide wc checking */ Xchar *Delim = DELIM; /* pointer to delimiter string */ Xint Cut = 0; /* option to provide cut mark */ Xint Binary = 0; /* flag for binary files */ Xint Mixed = 0; /* mixed text and binary files */ Xint eXists = 0; /* check if file exists */ Xint InterOW = 0; /* interactive overwrite */ Xint PosParam = 0; /* allow positional parameters */ Xint FileStrip; /* strip directories from filenames */ X#ifdef DEBUG Xint de_bug = 0; /* switch for debugging on */ X#define DeBug(f,v) if (de_bug) printf(f, v) X#else /* normal compile */ X#define DeBug(f,v) /* do nothing */ X#endif X XFILE *fpout = stdout; Xchar *Rname(); /* file restore name */ Xunsigned limit = 0; Xlong ftell(); Xlong TypePos; /* position for archive type message */ Xchar outname[50]; /* base for output filename */ Xchar filename[50]; /* actual output filename */ Xchar *sharname = (char *)0; Xchar *submitter = (char *)0; Xint filenum = 0; /* output file # */ Xstruct stat fst; /* check file type, access */ X Xmain(argc,argv) Xchar **argv; X{ Xint status = 0; Xchar *oname; Xint c; Xextern int optind; Xextern char *optarg; X X while((c = getopt(argc,argv,"vwd:btxXcfmpas:n:l:o:h")) != -1) X { X switch(c) X { X case 'v': X Verbose = 0; X break; X case 'w': X Wc_c = 0; X break; X case 'd': X Delim = optarg; X break; X case 'b': /* binary files */ X Binary = 1; X break; X case 't': /* text mode */ X Binary = 0; X break; X case 'x': /* does the file exist */ X eXists = 1; X if(InterOW || limit) X exit_incompat(); X break; X case 'X': /* does the file exist */ X InterOW = 1; X if(limit || eXists) X exit_incompat(); X eXists = 1; X break; X case 'c': X Cut = 1; X break; X case 'f': /* filenames only */ X FileStrip = 1; X break; X case 'M': /* mixed text and binary */ X Mixed = 1; X break; X case 'p': /* allow positional parameters */ X PosParam = 1; X break; X case 'l': /* size limit in k */ X if(eXists) X exit_incompat(); X limit = atoi(optarg) - 1; X DeBug("Limit %dk\n",limit); X break; X case 'n': /* name of archive */ X sharname = optarg; X break; X case 's': /* submitter */ X submitter = optarg; X break; X case 'a': /* generate Archive-name: headers */ X Archive_name = 1; X break; X case 'o': /* specify output file */ X oname = optarg; X strcpy(outname,oname); X strcat(outname,"."); X filenum = 1; X strcpy(filename,outname); X strcat(filename,"01"); X fpout = fopen(filename,"w"); X if(!fpout) X { /* creation error */ X perror("can't create output file"); X exit(1); X } X break; X#ifdef DEBUG X case '$': /* totally undocumented $ option, debug on */ X de_bug = 1; X break; X#endif X default: /* invalid option */ X case 'h': /* help */ X helpuser(); X break; X } X } X X if(optind >= argc) X { X fprintf(stderr,"shar: No input files\n"); X helpuser(); X exit(1); X } X X if(Archive_name && !sharname) X { X fprintf(stderr,"shar: -n must accompany -a\n"); X helpuser(); X exit(1); X } X X if(!submitter) X { X submitter = malloc(128); X who_where(submitter); X } X X if(header(argc-optind,&argv[optind])) X exit(2); X X if(InterOW) X { X Verbose = 1; X fprintf(fpout,"wish=\n"); X if(Archive_name) X { X printf("PLEASE do not submit -X shars to the usenet or other\n"); X printf("public networks. They will cause problems.\n"); X } X } X X while(optind < argc) X { /* process positional parameters and files */ X if(PosParam) X { /* allow -b and -t inline */ X if(strcmp(argv[optind],"-b") == 0) X { /* set binary */ X Binary = 1; X optind++; X continue; X } X if(strcmp(argv[optind],"-t") == 0) X { /* set mode text */ X Binary = 0; X optind++; X continue; X } X } X status += shar(argv[optind++]); X } X X /* delete the sequence file, if any */ X if(limit && filenum > 1) X { X fputs("rm -f s3_seq_.tmp\n",fpout); X fputs("echo \"You have unpacked the last part\"\n",fpout); X if(!Verbose) X fprintf(stderr,"Created %d files\n",filenum); X } X fputs("exit 0\n",fpout); X exit(status); X} X X/*+----------------------------------------------------------------------- X mode_map(mode,mode_str) build drwxrwxrwx string X------------------------------------------------------------------------*/ Xchar * Xmode_map(mode,mode_str) Xunsigned short mode; Xchar *mode_str; X{ Xregister unsigned ftype = mode & S_IFMT; Xregister char *rtn; Xstatic char result[12]; X X rtn = (mode_str == (char *)0) ? result : mode_str; X X /* drwxrwxrwx */ X /* 0123456789 */ X strcpy(rtn,"----------"); X X#ifdef THIS_IS_NOT_NEEDED_FOR_SHAR X switch(ftype) X { X case S_IFIFO: *rtn = 'p'; break; /* FIFO (named pipe) */ X case S_IFDIR: *rtn = 'd'; break; /* directory */ X case S_IFCHR: *rtn = 'c'; break; /* character special */ X case S_IFBLK: *rtn = 'b'; break; /* block special */ X case S_IFREG: *rtn = '-'; break; /* regular */ X X#if defined(sun) | defined(BSD42) X case S_IFLNK: *rtn = 'l'; break; /* symbolic link */ X case S_IFSOCK: *rtn = 's'; break; /* socket */ X#endif X X#if defined (SYS5) X case S_IFNAM: /* name space entry */ X if(mode & S_INSEM) /* semaphore */ X { X *rtn = 's'; X break; X } X if(mode & S_INSHD) /* shared memory */ X { X *rtn = 'm'; X break; X } X#endif X X default: *rtn = '?'; break; /* ??? */ X } X#endif /* THIS_IS_NOT_NEEDED_FOR_SHAR */ X X if(mode & 000400) *(rtn + 1) = 'r'; X if(mode & 000200) *(rtn + 2) = 'w'; X if(mode & 000100) *(rtn + 3) = 'x'; X if(mode & 004000) *(rtn + 3) = 's'; X if(mode & 000040) *(rtn + 4) = 'r'; X if(mode & 000020) *(rtn + 5) = 'w'; X if(mode & 000010) *(rtn + 6) = 'x'; X if(mode & 002000) *(rtn + 6) = 's'; X if(mode & 000004) *(rtn + 7) = 'r'; X if(mode & 000002) *(rtn + 8) = 'w'; X if(mode & 000001) *(rtn + 9) = 'x'; X if(mode & 001000) *(rtn + 9) = 't'; X X return(rtn); X X} /* end of mode_map */ X Xheader(argc,argv) Xchar **argv; X{ Xint i; Xint status; XFILE *fpsource; /* pipe temp */ Xchar s128[128]; Xlong now; Xstruct tm *utc; Xstruct tm *gmtime(); X X /* see if any conflicting options */ X if(limit && !filenum) X { /* can't rename what you don't have */ X fprintf(stderr,"Can't use -l option without -o\n"); X helpuser(); X } X X for(i = 0; i < argc; i++) X { /* skip positional parameters */ X if(PosParam && (strcmp(argv[i],"-b") == 0 || X strcmp(argv[i],"-t") == 0)) X continue; X X /* see if access and correct type */ X if(access(argv[i],4)) X { X fprintf(stderr,"shar: Can't access %s\n",argv[i]); X return(1); X } X X /* get file type */ X stat(argv[i],&fst); X status = fst.st_mode & S_IFMT; X X /* at this point I check to see that this is a regular file */ X if(status != S_IFREG) X { /* this is not a regular file */ X fprintf(stderr,"shar: %s is not a regular file\n",argv[i]); X return(1); X } X } X X if(Archive_name) X { X fprintf(fpout,"Submitted by: %s\n",submitter); X fprintf(fpout,"Archive-name: %s/part%02d\n\n", X sharname,(filenum) ? filenum : 1); X } X X if(Cut) X fputs("---- Cut Here and unpack ----\n",fpout); X fputs("#!/bin/sh\n",fpout); X if(sharname) X fprintf(fpout,"# This is %s, a shell archive (shar %s)\n", X sharname,revision); X else X fprintf(fpout,"# This is a shell archive (shar %s)\n",revision); X X time(&now); X utc = gmtime(&now); X fprintf(fpout,"# made %02d/%02d/%04d %02d:%02d UTC ", X utc->tm_mon + 1,utc->tm_mday,utc->tm_year + 1900, X utc->tm_hour,utc->tm_min); X X fputs("by ",fpout); X fputs(submitter,fpout); X fputs("\n",fpout); X X#if defined(SYS5) X if(!(fpsource = popen("/bin/pwd","r"))) X return(-1); X fgets(s128,sizeof(s128),fpsource); X s128[strlen(s128) - 1] = 0; X fclose(fpsource); X#else X#if defined(BSD42) || defined(sun) X getwd(s128); X#else X#include "Need_conditional_compile_fix" X#endif X#endif X fprintf(fpout,"# Source directory %s\n",s128); X X fprintf(fpout,"#\n# existing files %s be overwritten\n", X (eXists) ? "will NOT" X : ((InterOW) ? "MAY" : "WILL")); X if(InterOW) X fprintf(fpout,"# The unsharer will be INTERACTIVELY queried.\n"); X X if(limit) X { /* may be split, explain */ X fputs("#\n",fpout); X TypePos = ftell(fpout); X fprintf(fpout,"%-75s\n%-75s\n","#","#"); X } X X fputs("#\n# This shar contains:\n",fpout); X fputs("# length mode name\n",fpout); X fputs("# ------ ---------- ------------------------------------------\n", X fpout); X for(i = 0; i < argc; i++) X { /* output names of files but not parameters */ X if(PosParam && (strcmp(argv[i],"-b") == 0 || X strcmp(argv[i],"-t") == 0)) X continue; X stat(argv[i],&fst); X fst.st_mode &= ~(07000); /* turn off setuid, setgid and sticky bits */ X fprintf(fpout,"# %6ld %s %s\n",fst.st_size, X mode_map(fst.st_mode,(char *)0),Rname(argv[i])); X } X fputs("#\n",fpout); X X fputs("touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$\n",fpout); X fputs("if [ -s /tmp/s3_touch$$ ]\n",fpout); X fputs("then\n",fpout); X fputs(" TOUCH=can\n",fpout); X fputs("else\n",fpout); X fputs(" TOUCH=cannot\n",fpout); X fputs("fi\n",fpout); X fputs("rm -f /tmp/s3_touch$$\n",fpout); X X if(limit) X { /* now check the sequence */ X fprintf(fpout,"%s%s%s%s", X "if test -r s3_seq_.tmp\n", X "then echo \"Must unpack archives in sequence!\"\n", X " next=`cat s3_seq_.tmp`; echo \"Please unpack part $next next\"\n", X " exit 1; fi\n"); X } X return(0); X} X X#define MAX_MKDIR_ALREADY 128 /* ridiculously enough */ Xchar *mkdir_already[MAX_MKDIR_ALREADY]; Xint mkdir_already_count = 0; X Xvoid Xgen_mkdir(path) Xchar *path; X{ Xregister int ialready; Xchar *cptr; X X/* if already generated code for this dir creation, dont do again */ X for(ialready = 0; ialready < mkdir_already_count; ialready++) X { X if(!strcmp(path,mkdir_already[ialready])) X return; X } X X/* haven't done this one */ X if(mkdir_already_count == MAX_MKDIR_ALREADY) X { X fprintf(stderr,"too many directories for mkdir generation\n"); X exit(255); X } X if(!(cptr = mkdir_already[mkdir_already_count++] = malloc(strlen(path)+1))) X { X fprintf(stderr,"out of memory for mkdir generation\n"); X exit(255); X } X strcpy(cptr,path); X X/* generate the text */ X fprintf(fpout,"if test ! -d '%s' ; then\n",path); X if(Verbose) X fprintf(fpout," echo \"x - creating directory %s\"\n",path); X fprintf(fpout," mkdir '%s'\n",path); X fprintf(fpout,"fi\n"); X X} /* end of gen_mkdir */ X Xvoid Xgen_mkdir_script(path) Xregister char *path; X{ Xregister char *cptr; X X for(cptr = strchr(path,'/'); cptr; cptr = strchr(cptr + 1,'/')) X { X /* avoid empty string if leading or double '/' */ X if(cptr == path || *(cptr - 1) == '/') X continue; X /* omit '.' */ X if((*(cptr - 1) == '.') && ((cptr == path + 1) || (*(cptr - 2) == '/'))) X continue; X *cptr = 0; /* temporarily terminate string */ X gen_mkdir(path); X *cptr = '/'; X } X} /* end of gen_mkdir_script */ X Xshar(file) Xchar *file; X{ Xchar line[BUFSIZ]; XFILE *fpsource; Xlong cursize,remaining,ftell(); Xint split = 0; /* file split flag */ Xchar *filetype; /* text or binary */ Xchar *RstrName; /* name for restore */ Xstruct tm *lt; Xchar *filename_base; X X /* if limit set, get the current output length */ X if(limit) X { X cursize = ftell(fpout); X remaining = (limit * 1024L) - cursize; X DeBug("In shar: remaining size %ld\n",remaining); X } X X /* determine the name to use for restore */ X RstrName = Rname(file); X X fputs("# ============= ",fpout); X fputs(RstrName,fpout); X fputs(" ==============\n",fpout); X X gen_mkdir_script(RstrName); X X /* if mixed, determine the file type */ X if(Mixed) X { X int count; X sprintf(line,"file %s | egrep -c \"text|shell\"",file); X fpsource = popen(line,"r"); X fscanf(fpsource,"%d",&count); X pclose(fpsource); X Binary = (count != 1); X } X X if(Binary) X { /* fork a uuencode process */ X static int pid,pipex[2]; X X pipe(pipex); X fflush(fpout); X X if(pid = fork()) X { /* parent, create a file to read */ X close(pipex[1]); X fpsource = fdopen(pipex[0],"r"); X } X else X { /* start writing the pipe with encodes */ X FILE *outptr; X X fpsource = fopen(file,"rb"); X outptr = fdopen(pipex[1],"w"); X fprintf(outptr,"begin 600 %s\n",RstrName); X encode(fpsource,outptr); X fprintf(outptr,"end\n"); X exit(0); X } X filetype = "Binary"; X } X else X { X fpsource = fopen(file,"r"); X filetype = "Text"; X } X X if(fpsource) X { X /* protect existing files */ X if(eXists) X { X if(InterOW) X { X fprintf(fpout,"if test -f '%s'\n",RstrName); X fprintf(fpout,"then\n"); X fprintf(fpout,"\tcase $wish in\n"); X fprintf(fpout,"\tA*|a*) echo x - overwriting '%s';;\n",RstrName); X fprintf(fpout, X "\t*) echo \"? - overwrite '%s' -- [No], [Y]es, [A]ll, [Q]uit? \"\n", X RstrName); X fprintf(fpout,"\t\tread wish;;\n"); X fprintf(fpout,"\tesac\n"); X fprintf(fpout,"\tcase $wish in\n"); X fprintf(fpout,"\tQ*|q*) echo aborted; exit 86;;\n"); X fprintf(fpout,"\tA*|a*|Y*|y*) x=Y;;\n"); X fprintf(fpout,"\t*) x=N;;\n"); X fprintf(fpout,"\tesac\n"); X fprintf(fpout,"else\n"); X fprintf(fpout,"\tx=Y\n"); X fprintf(fpout,"fi\n"); X fprintf(fpout,"if test $x != Y\n"); X fprintf(fpout,"then\n"); X fprintf(fpout,"\techo x - skipping '%s'\n",RstrName); X fprintf(fpout,"else\n"); X } X else X { X fprintf(fpout, X "if test -f '%s'; then echo \"File %s exists\"; else\n", X RstrName,RstrName); X } X } X X fprintf(stderr,"shar: saving %s (%s)\n",file,filetype); X if(Verbose) X { /* info on archive and unpack */ X fprintf(fpout,"echo \"x - extracting %s (%s)\"\n", X RstrName,filetype); X } X if(Binary) X { /* run sed through uudecode via temp file */ X fprintf(fpout,"sed 's/^%c//' << '%s' > s3_temp_.tmp &&\n", X PREFIX,Delim); X } X else X { /* just run it into the file */ X fprintf(fpout,"sed 's/^%c//' << '%s' > %s &&\n", X PREFIX,Delim,RstrName); X } X while(fgets(line,BUFSIZ,fpsource)) X { /* output a line and test the length */ X fprintf(fpout,"%c%s",PREFIX,line); X if(limit && (remaining -= strlen(line) + 2) < 0) X { /* change to another file */ X DeBug("Newfile, remaining %ld, ",remaining); X DeBug("limit still %d\n",limit); X X if(line[strlen(line) - 1] != '\n') X fputc('\n',fpout); X X fprintf(fpout,"%s\n",Delim); X if(Verbose) X { /* output some reassurance */ X fprintf(fpout, X "echo \"End of %s part %d\"\n", X (sharname) ? sharname : "",filenum); X fprintf(fpout, X "echo \"File %s is continued in part %d\"\n", X RstrName,filenum + 1); X } X else X fprintf(fpout, X "echo \"End of part %d, continue with part %d\"\n", X filenum,filenum + 1); X fprintf(fpout,"echo \"%d\" > s3_seq_.tmp\n",filenum + 1); X fprintf(fpout,"exit 0\n"); X X if(filenum == 1) X { /* rewrite the info lines on the firstheader */ X fseek(fpout,TypePos,0); X fprintf(fpout,"%-75s\n%-75s\n", X "# This is part 1 of a multipart archive", X "# do not concatenate these parts, unpack them in order with /bin/sh"); X } X fclose(fpout); X X /* form the next filename */ X sprintf(filename,"%s%02d",outname,++filenum); X fpout = fopen(filename,"w"); X X if(Archive_name) X { X fprintf(fpout,"Submitted by: %s\n",submitter); X fprintf(fpout,"Archive-name: %s/part%2d\n\n", X sharname,(filenum) ? filenum : 1); X } X X if(Cut) X fputs("---- Cut Here and unpack ----\n",fpout); X if(!(filename_base = strrchr(filename,'/'))) X filename_base = filename; X else X filename_base++; X X fprintf(fpout,"#!/bin/sh\n"); X fprintf(fpout, X "# this is %s (part %d of %s)\n", X filename_base, X filenum, X (sharname) ? sharname : "a multipart archive"); X fputs("# do not concatenate these parts, ",fpout); X fputs("unpack them in order with /bin/sh\n",fpout); X fprintf(fpout,"# file %s continued\n#\n",RstrName); X X fputs("touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$\n",fpout); X fputs("if [ -s /tmp/s3_touch$$ ]\n",fpout); X fputs("then\n",fpout); X fputs(" TOUCH=can\n",fpout); X fputs("else\n",fpout); X fputs(" TOUCH=cannot\n",fpout); X fputs("fi\n",fpout); X fputs("rm -f /tmp/s3_touch$$\n",fpout); X X fprintf(fpout,"CurArch=%d\n",filenum); X fprintf(fpout,"%s%s%s%s%s%s%s%s%s", X "if test ! -r s3_seq_.tmp\n", X "then echo \"Please unpack part 1 first!\"\n", X " exit 1; fi\n", X "( read Scheck\n", X " if test \"$Scheck\" != $CurArch\n", X " then echo \"Please unpack part $Scheck next!\"\n", X " exit 1;\n", X " else exit 0; fi\n", X ") < s3_seq_.tmp || exit 1\n"); X X if(Verbose) X { /* keep everybody informed */ X fprintf(stderr,"Starting file %s\n",filename); X fprintf(fpout, X "echo \"x - Continuing file %s\"\n",RstrName); X } X fprintf(fpout, X "sed 's/^%c//' << '%s' >> %s\n", X PREFIX,Delim,(Binary ? "s3_temp_.tmp" : RstrName)); X remaining = limit * 1024L; X split = 1; X } X } X X (void) fclose(fpsource); X X if(line[strlen(line) - 1] != '\n') X fputc('\n',fpout); X X fprintf(fpout,"%s\n",Delim); X if(split && Verbose) X fprintf(fpout, X "echo \"File %s is complete\"\n",RstrName); X X /* if this file was uuencoded, decode it and drop the temp */ X if(Binary) X { X if(Verbose) X fprintf(fpout,"echo \"uudecoding file %s\"\n",RstrName); X fprintf(fpout, X "uudecode < s3_temp_.tmp && rm -f s3_temp_.tmp &&\n"); X } X X /* set the permissions as they were */ X stat(file,&fst); X fprintf(fpout,"chmod %04o %s || echo \"restore of %s fails\"\n", X fst.st_mode & 00777,RstrName,RstrName); X lt = localtime(&fst.st_mtime); X fputs("if [ $TOUCH = can ]\nthen\n",fpout); X fprintf(fpout," touch -am %02d%02d%02d%02d%02d %s\n", X lt->tm_mon + 1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_year, X RstrName); X fputs("fi\n",fpout); X X if(Wc_c) X { /* validate the transferred file */ X FILE *pfp; X char command[BUFSIZ]; X X sprintf(command,"%s %s",WC,file); X if((pfp = popen(command,"r"))) X { X char wc[BUFSIZ]; X X fscanf(pfp,"%s",wc); X fprintf(fpout,"set `%s %s`;Wc_c=$1\n", X WC,RstrName); X fprintf(fpout, X "if test \"$Wc_c\" != \"%s\"\n",wc); X fprintf(fpout, X "then echo original size %s, current size $Wc_c;fi\n",wc); X pclose(pfp); X } X } X X /* if the exists option is in place close the if */ X if(eXists) X fprintf(fpout,"fi\n"); X X return(0); X } X else X { X fprintf(stderr,"shar: Can't open %s (%s): ",file,filetype); X perror(""); X return(1); X } X} X Xchar * XRname(file) Xregister char *file; X{ X register char *RstrName; X X if(FileStrip) X { /* use just the filename */ X RstrName = file+strlen(file); X while(RstrName > file && *RstrName != '/') X RstrName--; X if(*RstrName == '/') RstrName++; X } X else X RstrName = file; X if(!strncmp(RstrName,"./",2)) X RstrName += 2; X return(RstrName); X} X X/***************************************************************** X | exit_incompat - incompatible options X ****************************************************************/ X Xexit_incompat() X{ X fputs("You may only specify one of -l, -X or -x\n",stderr); X exit(1); X} X Xhelpuser() X{ /* output a command format message */ X register char **ptr; X static char *helpinfo[] = X { X "-v verbose messages OFF while executing", X "-w don't check with 'wc -c' after unpack", X "-n Name of archive (documentation)", X "-a Generate Submitted-by: & Archive-name: headers", X "-s override automatically determined submitter name", X "-x don't overwrite existing files", X "-X interactively overwrite existing files (NOT FOR NET SHARS)", X "-b treat all files as binary, use uuencode", X "-t treat all files as text (default)", X "-p allow positional parameter options. The options \"-b\"", X " and \"-t\" may be embedded, and files to the right of the", X " option will be processed in the specified mode", X "-M mixed mode. Determine if the files are text or", X " binary and archive correctly.", X "-D output date, user, and directory comments to the archive", X "-c start the shar with a cut line", X "-f restore by filename only, rather than path", X "-dXXX use XXX to delimit the files in the shar", X "-oXXX (or -o XXX) output to file XXX.01 thru XXX.nn", X "-lXX limit output file size to XXk bytes", X "\nThe 'o' option is required if the 'l' option is used", X "The 'n' option is required if the 'a' option is used", X "The 'x' and 'l' options are incompatible", X "\n-a generates sharname/part## headers. If you are producing patches", X "you'll need to edit -a headers (or please improve shar :-))", X "The automatic submitter name is trivial: essentially `whoami`@`uname`", X (char *)0 X }; X fprintf(stderr, X "shar %s\nusage: shar [ options ] file [ file1 ... ] ]\n",revision); X for(ptr = helpinfo; *ptr; ptr++) X fprintf(stderr,"%s\n",*ptr); X X exit(1); X} X/* vi: set tabstop=4 shiftwidth=4: */ SHAR_EOF chmod 0644 shar.c || echo "restore of shar.c fails" if [ $TOUCH = can ] then touch -am 0406143490 shar.c fi # ============= unshar.c ============== echo "x - extracting unshar.c (Text)" sed 's/^X//' << 'SHAR_EOF' > unshar.c && X/* CHK=0x4D8D */ X/**************************************************************** X * unshar.c: Unpackage one or more shell archive files X * X * Usage: unshar [ -d directory ] [ file ] ... X * X * Description: unshar is a filter which removes the front part X * of a file and passes the rest to the 'sh' command. X * It understands phrases like "cut here", and also X * knows about shell comment characters and the Unix X * commands "echo", "cat", and "sed". X * X * HISTORY X * 1-Feb-85 Guido van Rossum (guido@mcvax) at CWI, Amsterdam X * Added missing 'quit' routine; X * added -d flag to change to directory first; X * added filter mode (read stdin when no arguments); X * added 'getopt' to get flags (makes it self-contained). X * 29-Jan-85 Michael Mauldin (mlm) at Carnegie-Mellon University X * Created. X ****************************************************************/ X X#include <stdio.h> X#define EOL '\n' X X#if defined(pyr) || defined(sun) || defined(BSD42) || \ X defined(vax) || defined(sequent) X#define strchr index X#endif X Xchar *strchr(); X Xextern char *optarg; Xextern int optind; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int i,ch; X FILE *in; X X setbuf(stdout,NULL); X setbuf(stderr,NULL); X X /* Process options */ X X while((ch = getopt(argc,argv,"d:")) != EOF) X { X switch(ch) X { X case 'd': X if(chdir(optarg) == -1) X { X fprintf(stderr,"unshar: cannot chdir to '%s'\n",optarg); X exit(2); X } X break; X default: X quit(2,"Usage: unshar [-d directory] [file] ...\n"); X } X } X X if(optind < argc) X { X for(i= optind; i < argc; ++i) X { X if(!(in = fopen(argv[i],"r"))) X { X fprintf(stderr,"unshar: file '%s' not found\n",argv[i]); X exit(1); X } X process(argv[i],in); X fclose(in); X } X } X else X process("standard input",stdin); X X exit(0); X} X X Xprocess(name,in) Xchar *name; XFILE *in; X{ X char ch; X FILE *shpr,*popen(); X X if(position(name,in)) X { X printf("%s:\n",name); X if(!(shpr = popen("sh","w"))) X quit(1,"unshar: cannot open 'sh' process\n"); X X while((ch = fgetc(in)) != EOF) X fputc(ch,shpr); X X pclose(shpr); X } X} X X/**************************************************************** X * position: position 'fil' at the start of the shell command X * portion of a shell archive file. X ****************************************************************/ X Xposition(fn,fil) Xchar *fn; XFILE *fil; X{ X char buf[BUFSIZ]; X long pos,ftell(); X X /* Results from star matcher */ X static char res1[BUFSIZ],res2[BUFSIZ],res3[BUFSIZ],res4[BUFSIZ]; X static char *result[] = X { X res1,res2,res3,res4 }; X X rewind(fil); X X while(1) X { /* Record position of the start of this line */ X pos = ftell(fil); X X /* Read next line, fail if no more */ X if(!fgets(buf,BUFSIZ,fil)) X { X fprintf(stderr,"unshar: found no shell commands in %s\n",fn); X return(0); X } X X /* Bail out if we see C preprocessor commands or C comments */ X if(stlmatch(buf,"#include") || stlmatch(buf,"# include") || X stlmatch(buf,"#define") || stlmatch(buf,"# define") || X stlmatch(buf,"#ifdef") || stlmatch(buf,"# ifdef") || X stlmatch(buf,"#ifndef") || stlmatch(buf,"# ifndef") || X stlmatch(buf,"/*")) X { X fprintf(stderr, X "unshar: %s looks like raw C code, not a shell archive\n",fn); X return(0); X } X X /* Does this line start with a shell command or comment */ X if(stlmatch(buf,"#") || stlmatch(buf,":") || X stlmatch(buf,"echo ") || stlmatch(buf,"sed ") || X stlmatch(buf,"cat ")) X { X fseek(fil,pos,0); X return(1); X } X X /* Does this line say "Cut here" */ X if(smatch(buf,"*CUT*HERE*",result) || X smatch(buf,"*cut*here*",result) || X smatch(buf,"*TEAR*HERE*",result) || X smatch(buf,"*tear*here*",result) || X smatch(buf,"*CUT*CUT*",result) || X smatch(buf,"*cut*cut*",result)) X { X /* Read next line after "cut here", skipping blank lines */ X while(1) X { X pos = ftell(fil); X X if(!fgets(buf,BUFSIZ,fil)) X { X fprintf(stderr, X "unshar: found no shell commands after 'cut' in %s\n",fn); X return(0); X } X X if(*buf != '\n') break; X } X X /* Win if line starts with a comment character of lower case letter */ X if(*buf == '#' || *buf == ':' || (('a' <= *buf) && ('z' >= *buf))) X { X fseek(fil,pos,0); X return(1); X } X X /* Cut here message lied to us */ X fprintf(stderr,"unshar: %s is probably not a shell archive,\n",fn); X fprintf(stderr," the 'cut' line was followed by: %s",buf); X return(0); X } X } X} X X/***************************************************************** X * stlmatch -- match leftmost part of string X * X * Usage: i = stlmatch (big,small) X * int i; X * char *small, *big; X * X * Returns 1 iff initial characters of big match small exactly; X * else 0. X * X * HISTORY X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University X * Ripped out of CMU lib for Rog-O-Matic portability X * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University X * Rewritten for VAX from Ken Greer's routine. X * X * Originally from klg (Ken Greer) on IUS/SUS UNIX X *****************************************************************/ X Xint stlmatch(big,small) Xchar *small,*big; X{ X register char *s,*b; X s = small; X b = big; X do X { X if(*s == '\0') X return(1); X } while(*s++ == *b++); X return(0); X} X X/***************************************************************** X * smatch: Given a data string and a pattern containing one or X * more embedded stars (*) (which match any number of characters) X * return true if the match succeeds, and set res[i] to the X * characters matched by the 'i'th *. X *****************************************************************/ X Xsmatch(dat,pat,res) Xregister char *dat,*pat,**res; X{ X register char *star = 0,*starend,*resp; X int nres = 0; X X while(1) X { X if(*pat == '*') X { X star = ++pat; /* Pattern after * */ X starend = dat; /* Data after * match */ X resp = res[nres++]; /* Result string */ X *resp = '\0'; /* Initially null */ X } X else if(*dat == *pat) /* Characters match */ X { X if(*pat == '\0') /* Pattern matches */ X return(1); X pat++; /* Try next position */ X dat++; X } X else X { X if(*dat == '\0') /* Pattern fails - no more */ X return(0); /* data */ X if(star == 0) /* Pattern fails - no * to */ X return(0); /* adjust */ X pat = star; /* Restart pattern after * */ X *resp++ = *starend; /* Copy character to result */ X *resp = '\0'; /* null terminate */ X dat = ++starend; /* Rescan after copied char */ X } X } X} X X/***************************************************************** X * Addendum: quit subroutine (print a message and exit) X *****************************************************************/ X Xquit(status,message) Xint status; Xchar *message; X{ X fprintf(stderr,message); X exit(status); X} X X/***************************************************************** X * Public Domain getopt routine X *****************************************************************/ X X/* X * get option letter from argument vector X */ Xint opterr = 1; /* useless, never set or used */ Xint optind = 1; /* index into parent argv vector */ Xint optopt; /* character checked for validity */ Xchar *optarg; /* argument associated with option */ X X#define BADCH (int)'?' X#define EMSG "" X#define tell(s) fputs(*nargv,stderr);fputs(s,stderr); \ X fputc(optopt,stderr);fputc('\n',stderr);return(BADCH); X Xgetopt(nargc,nargv,ostr) Xint nargc; Xchar **nargv,*ostr; X{ X static char *place = EMSG; /* option letter processing */ X register char *oli; /* option letter list index */ X char *strchr(); X X if(!*place) X { /* update scanning pointer */ X if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) X return(EOF); X if(*place == '-') X { /* found "--" */ X ++optind; X return(EOF); X } X } /* option letter okay? */ X if((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) X { X if(!*place) ++optind; X tell(": illegal option -- "); X } X if(*++oli != ':') X { /* don't need argument */ X optarg = (char *)0; X if(!*place) ++optind; X } X else X { /* need an argument */ X if(*place) optarg = place; /* no white space */ X else if(nargc <= ++optind) X { /* no arg */ X place = EMSG; X tell(": option requires an argument -- "); X } X else optarg = nargv[optind]; /* white space */ X place = EMSG; X ++optind; X } X return(optopt); /* dump back option letter */ X} X/* vi: set tabstop=4 shiftwidth=4: */ SHAR_EOF chmod 0644 unshar.c || echo "restore of unshar.c fails" if [ $TOUCH = can ] then touch -am 0403210990 unshar.c fi # ============= uushar.c ============== echo "x - extracting uushar.c (Text)" sed 's/^X//' << 'SHAR_EOF' > uushar.c && X/* CHK=0x46B4 */ X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X X/* ENC is the basic 1 character encoding function to make a char printing */ X#define ENC(c) ((((c) & 077) + ' ') | ((c & 077) == 0 ? 0100 : 0)) X Xencode (in, out) X FILE *in; X FILE *out; X{ X char buf[80]; X int i, n; X X for (;;) X { X /* 1 (up to) 45 character line */ X n = fr (in, buf, 45); X putc (ENC (n), out); X X for (i = 0; i < n; i += 3) X outdec (&buf[i], out); X X putc ('\n', out); X if (n <= 0) X break; X } X} X X/* X * output one group of 3 bytes, pointed at by p, on file f. X */ Xoutdec (p, f) X char *p; X FILE *f; X{ X int c1, c2, c3, c4; X X c1 = *p >> 2; X c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; X c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03; X c4 = p[2] & 077; X putc (ENC (c1), f); X putc (ENC (c2), f); X putc (ENC (c3), f); X putc (ENC (c4), f); X} X X/* fr: like read but stdio */ Xint X fr (fp, buf, cnt) X FILE *fp; X char *buf; X int cnt; X{ X int c, i; X X for (i = 0; i < cnt; i++) X { X c = getc (fp); X if (c == EOF) X return (i); X buf[i] = c; X } X return (cnt); X} X/* vi: set tabstop=4 shiftwidth=4: */ SHAR_EOF chmod 0644 uushar.c || echo "restore of uushar.c fails" if [ $TOUCH = can ] then touch -am 0330002690 uushar.c fi # ============= who@where.c ============== echo "x - extracting who@where.c (Text)" sed 's/^X//' << 'SHAR_EOF' > who@where.c && X/* CHK=0xBAD4 */ X/*+------------------------------------------------------------------------- X who@where.c - find out who i am & where i am X ...!gatech!kd4nc!n4hgf!wht (wht%n4hgf@gatech.edu) X--------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:04-03-1990-19:55-wht@n4hgf-get rid of complicated who_am_i */ X/*:04-01-1990-13:30-pat@rwing-use utsname.nodename instead of sysname */ X/*:04-02-1990-12:12-wht@n4hgf-sigh... some pwd.h dont declare functions */ X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */ X/*:03-28-1990-15:24-wht@n4hgf-creation */ X X#include <stdio.h> X#include <sys/types.h> X#include <pwd.h> X X/* assume system v unless otherwise fixed */ X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42) X#define BSD42 X#endif X#if defined(sun) /* this miscreant doesn't exactly fit BSD or SYSV */ X#undef BSD42 X#undef SYS5 X#endif X#if !defined(BSD42) && !defined(sun) X#define SYS5 X#endif X X#if defined(sun) || defined(BSD42) X#define strchr index X#define strrchr rindex X#endif X X#if !defined(SYS5) || defined(sun) X#include <sys/time.h> Xextern int errno; X#else X#include <sys/utsname.h> X#include <time.h> X#endif /* system dependencies */ X X/*+------------------------------------------------------------------------- X who_am_i() - get user name X--------------------------------------------------------------------------*/ Xchar * Xwho_am_i() X{ X struct passwd *getpwuid(); X struct passwd *passwd; X passwd = getpwuid(getuid()); X (void)endpwent(); X if(passwd == (struct passwd *)0) X return("???"); X return(passwd->pw_name); X X} /* end of who_am_i */ X X/*+------------------------------------------------------------------------- X where_am_i() - do uname, gethostname, or read file (/etc/systemid) X--------------------------------------------------------------------------*/ Xchar * Xwhere_am_i() X{ X#if defined(M_SYS5) /* SCO UNIX or XENIX */ XFILE *fpsid = fopen("/etc/systemid","r"); Xstatic char s20[20]; X if(!fpsid) X return("???"); X fgets(s20,sizeof(s20),fpsid); X fclose(fpsid); X s20[strlen(s20) - 1] = 0; X return(s20); X#else /* M_SYS5 */ X#if defined(SYS5) Xstatic struct utsname where_i_am; X uname(&where_i_am); X return(where_i_am.nodename); X#else /* SYS5 */ Xstatic char where_i_am[64]; X gethostname(where_i_am,sizeof(where_i_am)); X return(where_i_am); X#endif /* SYS5 */ X#endif /* M_SYS5 */ X} /* end of where_am_i */ X X/*+------------------------------------------------------------------------- X who_where(buf) X--------------------------------------------------------------------------*/ Xchar * Xwho_where(buf) Xchar *buf; X{ Xstatic char ww[64]; X X if(!buf) X buf = ww; X strcpy(buf,who_am_i()); X strcat(buf,"@"); X strcat(buf,where_am_i()); X} /* end of who_where */ X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of who@where.c */ SHAR_EOF chmod 0644 who@where.c || echo "restore of who@where.c fails" if [ $TOUCH = can ] then touch -am 0406145790 who@where.c fi exit 0 ------------------------------------------------------------------- Warren Tucker, TuckerWare gatech!n4hgf!wht or wht%n4hgf@gatech.edu Sforzando (It., sfohr-tsahn'-doh). A direction to perform the tone or chord with special stress, or marked and sudden emphasis.