$! ------------------ CUT HERE ----------------------- $! $! This archive created by VMS_SHARE Version 7.1-001 26-JUN-1989 $! On 28-JUL-1990 21:28:56.40 By user TIHOR (Warren Toomey - wtoomey@csadfa.oz.au@munnari.oz[@uunet]) $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $!+ THIS PACKAGE DISTRIBUTED IN 2 PARTS, TO KEEP EACH PART $! BELOW 30 BLOCKS $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. GETOPT.C;2 $! 2. INDEX.C;2 $! 3. MAKEFILE.;2 $! 4. README.;3 $! 5. UNSHAR.1;2 $! 6. UNSHAR.C;2 $! 7. UNSHAR.H;2 $! $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ if f$getsyi("version") .ges. "4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete/nolog 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete/nolog 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name"); buff:=CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(buff)) ;LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(buff));g:=0;LOOP EXITIF MARK(NONE)=END_OF(buff);x:= ERASE_CHARACTER(1);IF g = 0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x= "V" THEN APPEND_LINE;MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF; IF x="+" THEN g:=1;ERASE_LINE;ENDIF;ELSE IF x="-" THEN g:=0;ENDIF;ERASE_LINE; ENDIF;ENDLOOP;p:="`";POSITION(BEGINNING_OF(buff));LOOP r:=SEARCH(p,FORWARD); EXITIF r=0;POSITION(r);ERASE(r);COPY_TEXT(ASCII(INT(ERASE_CHARACTER(3)))); ENDLOOP;o:=GET_INFO(COMMAND_LINE,"output_file");WRITE_FILE(buff,o); ENDPROCEDURE;Unpacker;EXIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create/nolog 'f' X/* X**`009@(#)getopt.c`0092.2 (smail) 1/26/87 X*/ X`032 X/* X * Here's something you've all been waiting for: the AT&T public domain X * source for getopt(3). It is the code which was given out at the 1985 X * UNIFORUM conference in Dallas. I obtained it by electronic mail X * directly from AT&T. The people there assure me that it is indeed X * in the public domain. X * X * There is no manual page. That is because the one they gave out at X * UNIFORUM was slightly different from the current System V Release 2 X * manual page. The difference apparently involved a note about the X * famous rules 5 and 6, recommending using white space between an option X * and its first argument, and not grouping options that have arguments. X * Getopt itself is currently lenient about both of these things White X * space is allowed, but not mandatory, and the last option in a group can X * have an argument. That particular version of the man page evidently X * has no official existence, and my source at AT&T did not send a copy. X * The current SVR2 man page reflects the actual behavor of this getopt. X * However, I am not about to post a copy of anything licensed by AT&T. X */ X`032 X#ifdef BSD X#include X#else X#include X#endif X`032 X/*LINTLIBRARY*/ X#define NULL`0090 X#define EOF`009(-1) X#define ERR(s, c)`009if(opterr)`123\ X`009extern int write();\ X`009char errbuf`0912`093;\ X`009errbuf`0910`093 = c; errbuf`0911`093 = '\n';\ X`009(void) write(2, argv`0910`093, (unsigned)strlen(argv`0910`093));\ X`009(void) write(2, s, (unsigned)strlen(s));\ X`009(void) write(2, errbuf, 2);`125 X`032 Xextern char *index(); X`032 Xint`009opterr = 1; Xint`009optind = 1; Xint`009optopt; Xchar`009*optarg; X`032 Xint Xgetopt(argc, argv, opts) Xint`009argc; Xchar`009**argv, *opts; X`123 X`009static int sp = 1; X`009register int c; X`009register char *cp; X`032 X`009if(sp == 1) X`009`009if(optind >= argc `124`124 X`009`009 argv`091optind`093`0910`093 != '-' `124`124 argv`091optind`093`09 V11`093 == '\0') X`009`009`009return(EOF); X`009`009else if(strcmp(argv`091optind`093, "--") == NULL) `123 X`009`009`009optind++; X`009`009`009return(EOF); X`009`009`125 X`009optopt = c = argv`091optind`093`091sp`093; X`009if(c == ':' `124`124 (cp=index(opts, c)) == NULL) `123 X`009`009ERR(": illegal option -- ", c); X`009`009if(argv`091optind`093`091++sp`093 == '\0') `123 X`009`009`009optind++; X`009`009`009sp = 1; X`009`009`125 X`009`009return('?'); X`009`125 X`009if(*++cp == ':') `123 X`009`009if(argv`091optind`093`091sp+1`093 != '\0') X`009`009`009optarg = &argv`091optind++`093`091sp+1`093; X`009`009else if(++optind >= argc) `123 X`009`009`009ERR(": option requires an argument -- ", c); X`009`009`009sp = 1; X`009`009`009return('?'); X`009`009`125 else X`009`009`009optarg = argv`091optind++`093; X`009`009sp = 1; X`009`125 else `123 X`009`009if(argv`091optind`093`091++sp`093 == '\0') `123 X`009`009`009sp = 1; X`009`009`009optind++; X`009`009`125 X`009`009optarg = NULL; X`009`125 X`009return(c); X`125 $ CALL UNPACK GETOPT.C;2 1661603400 $ create/nolog 'f' Xchar *index(s, c) Xregister char *s, c; X`123 X do `123 X`009if (*s == c) X`009`009return(s); X `125 while (*s++ != 0); X return(0); X`125 $ CALL UNPACK INDEX.C;2 521485661 $ create/nolog 'f' X`032 Xunshar: cc -o unshar.c -lgetopt X`032 Xshar: README Makefile unshar.h unshar.c unshar.1 X`009shar README Makefile unshar.h unshar.c unshar.1 > unshar.shar $ CALL UNPACK MAKEFILE.;2 662188069 $ create/nolog 'f' XHere is a version of unshar that I have `096knocked up' in the past few week Vs. XIt isn't as flash as the standard unshar, but I've made it modular so it Xcan be enhanced easily. X`032 XHowever, it has some advantages: X`032 X`009- it does not call any other program, especially /bin/sh X`009- it can extract specific files from the shar X`009- can give a table of contents without extracting files X`009- takes several input files, or the standard input X`009- ignores leading `096junk' e.g news headers X`009- emulates sed, gres and cat to do the unsharing X`009- avoids the Minix `096cat /dev/null > file' problem :-) X`009- it works `096as is' under MS-DOS (needs getopt) X`032 XI've used it to unshar lots of different files; there are bound to be Xsome that it can't extract, but fixing the program should be easy. X`032 X`009Warren Toomey - wtoomey@csadfa.oz.au@munnari.oz`091@uunet`093 $ CALL UNPACK README.;3 2100125609 $ create/nolog 'f' X.T1 unshar 1L X.SH NAME Xunshar \- extract files from shell archive(s) X.SH SYNTAX Xunshar `091\-t`093 `091\-b`093 `091-v`093 `091-xfile`093 `091file(s)`093 X.SH OPTIONS XOptions are processed by X.B getopts(3). X.TP 8 X.B \-t XDo not extract files, just list the files in the archive(s). X.TP X.B \-b XExtract files from the archive(s) brutally, with no regard at all to things Xsuch as testing if the file exists, or chmoding the file etc. Currently Xthis is the only method supported, but other methods would be easy to add. X.TP X.B \-v XBe verbose. Used only for debugging purposes. X.TP X.B \-xfile XExtract the named file from the shell archive. If the \-x flag is used, Xonly those files specified will be extracted. X.SH DESCRIPTION X.I Unshar Xextracts files from one or more shell archives, and places them in the curre Vnt Xdirectory. It does no forking to achieve this, and is relatively fast. XIf no file name is given as an agrumemt, X.I unshar Xwill use standard input. XAt the moment X.I unshar Xis very simple-minded, and does its extraction rather brutally. The code Xhas been written to allow more intelligent unarchiving methods to be Xadded. X.SH SEE ALSO Xshar(1), sh(1). $ CALL UNPACK UNSHAR.1;2 1143356827 $ create/nolog 'f' X#include X#include "unshar.h" X`032 X/* X * Unshar - extract files from shell archive X * X * Written by Warren Toomey. Nov, 1989. X * You may freely copy or give away this source as X * long as this notice remains intact. X * X */ X`032 X/* Global variables */ X`032 Xint table;`009`009`009/* Generate a table, or extract */ Xint verbose;`009`009`009/* Unshar verbosely - debugging */ Xint numext;`009`009`009/* Number of files to extract */ Xchar *exfile`091100`093;`009`009/* Files to extract */ X`032 X`032 X#define getline(x,y)`009fgetline(stdin,x,y) X`032 Xint fgetline(zin,how,buf)`009/* Get a line from a file */ X FILE *zin; X int how;`009`009`009/* Ignore leading whitespace if */ X char *buf;`009`009`009/* how == NOWHITE */ X `123 X int ch=NULL; X`032 X *buf=NULL;`009`009`009/* Null the buffer */ X if (how==NOWHITE)`009`009/* If skip any whitespace */ X `123 X while (((ch=fgetc(zin))==' ') `124`124 (ch=='\t')); X if (ch==EOF) return(EOF);`009/* Returning EOF or NULL */ X if (ch=='\n') return(NULL); X *buf++ =ch;`009`009/* Put char in buffer */ X `125 X`032 X while ((ch=fgetc(zin))!='\n')`009/* Now get the line */ X `123 X if (ch==EOF) `123 *buf=NULL; return(EOF); `125 X *buf++ = ch; X `125 X`032 X *buf=NULL;`009`009`009/* Finally null-terminate the buffer */ X return(NULL);`009`009`009/* and return */ X `125 X`032 X`032 X`032 Xchar *getstring(buf)`009`009/* Get the next string from the buffer */ X char *buf;`009`009`009/* ignoring any quotes */ X `123 X char out`091BUFSIZE`093; X char *temp=out; X while ((*buf==' ') `124`124 (*buf=='\t')) buf++;`009/* Skip whitespace */ X`032 X switch(*buf)`009`009`009/* Now check first char */ X `123 X case '\'' : buf++; X`009`009while (*buf!='\'') *temp++ = *buf++; X`009`009*temp=NULL; X`009`009return(out); X case '\"' : buf++; X`009`009while (*buf!='\"') *temp++ = *buf++; X`009`009*temp=NULL; X`009`009return(out); X case NULL : return(NULL); X default : while ((*buf!=' ') && (*buf!='\t')) X`009`009 if (*buf!='\\') *temp++ = *buf++; X`009`009 else buf++; X`009`009*temp=NULL; X`009`009return(out); X `125 X `125 X`032 X`032 Xint firstword(buf)`009`009/* Return token value of first word */ X char *buf;`009`009`009/* in the buffer. Assume no leading */ X `123`009`009`009`009/* whitespace in the buffer */ X int i; X`032 X for (i=1;i' : strcpy(file,getstring(++temp)); /* Get the file name */ X`009 `009 break; X case '<' : if (*(++temp)=='<') ++temp;`009/* Skip 2nd < */ X`009`009 strcpy(word,getstring(temp));`009/* Get next word */ X`009`009 break; X default : temp++; X `125 X `125 X `125 X`032 X`032 X`032 Xvoid disembowel()`009`009/* Unshar brutally! */ X `123 X char buf`091BUFSIZE`093;`009`009/* Line buffer */ X char file`091BUFSIZE`093;`009`009/* File name */ X char word`091BUFSIZE`093;`009`009/* Word buffer */ X int ch,x; X`032 X if (verbose) printf("Entering disembowel\n"); X x='X';`009`009`009/* Leading X character */ X while(1) X `123 X ch=getline(NOWHITE,buf);`009/* Get a line from file */ X if (ch==EOF) X`009return; X`032 X switch(firstword(buf))`009/* Extract, depending on first word */ X `123 X case CAT: X case GRES: X case SED: if (verbose) printf("About to do getnames\n"); X`009`009 getnames(buf,file,word); X`009`009 if (table==0) X`009`009 `123 X`009`009 if ((numext==0) `124`124 (mustget(file))) X`009`009 `123 X`009`009 printf("unshar: Extracting %s\n",file); X`009`009 if (verbose) X`009`009`009printf(" stopping at %s\n",word); X`009`009 extract(YESX,file,word,x); X`009`009 `125 X`009`009 `125 X`009`009 else printf("%s\n",file); X`009`009 break; X default: break; X `125 X `125 X `125 X`032 X`032 X`032 Xusage() X `123 X fprintf(stderr,"Usage: unshar `091-t`093 `091-b`093 `091-v`093 `091-xfile` V093 `091file(s)`093\n"); X exit(0); X `125 X`032 X`032 Xmain(argc,argv) X int argc; X char *argv`091`093; X `123 X extern int optind; X extern char *optarg; X int i,c,first; X`032 X FILE *zin;`009`009`009/* Dummy file descriptor */ +-+-+-+-+-+-+-+- END OF PART 1 +-+-+-+-+-+-+-+-