From:	MERC::"uunet!FRSIM51.BITNET!MAILSERV"  5-JUL-1992 00:03:20.27
To:	galaxy::gleeve
CC:	
Subj:	MAEVA:[MAILSERV.PUB.VMSTAR]VMSTAR.SHARE_2;2

-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
X/* If relative path, get rid of default directory part of the name  */
X
X    if (absolute == 0)
X    `7B
X        strcpy(dire,"./");
X        for(cp1 = temp ,cp2 = curdir; *cp2 && (*cp1 == *cp2);
X            cp1++, cp2++);
X        if(*cp2 == 0)
X            *cp1 = 0;              /* Perfect match, no directory spec  */
X        else
X        `7B
X            switch(*cp1)
X            `7B
X            case '.':
X            case '`5B':               /* Legal beginnings or ends  */
X                break;
X            default:            /* We are above the default, use full name *
V/
X                cp1 = strchr(temp,'`5B');    /* Fixed this from 1.5  */
X                *dire = '\0';
X                break;
X            `7D
X            cp1++;                 /* Get past the starting . or `5B */
X        `7D
X        strcat(dire, cp1);
X    `7D
X    else
X        strcpy(dire, temp + 1);
X    cp1 = strrchr(dire, '`5D');       /* change trailing directory mark */
X    if (cp1 != NULL)
X    `7B
X        *cp1++ = '/';
X        *cp1 = '\0';                /* and terminate string (no file name) *
V/
X    `7D
X    strcpy(temp,strrchr(line,'`5D')+1); /* Now get the file name */
X    if((cp1=strindex(temp,".DIR;1"))!=0)
X    `7B
X        *cp1++ = '/';                          /* Terminate directory name *
V/
X        *cp1 = '\0';
X        strcat(dire,temp);
X        *fname = '\0';
X    `7D
X    else
X    `7B
X        strcpy(fname,temp);
X        *strchr(fname,';') = '\0';;           /* no version numbers */
X        lowercase(fname);                     /* map to lowercase */
X    `7D
X
X    /* Now rewrite the directory name  */
X
X   lowercase(dire);
X
X    for (cp1 = dire + 1; *cp1; ++cp1)         /* Change '.' to '/'  */
X        if(*cp1 == '.')
X            *cp1 = '/';
X    if((len=strlen(fname))==0)
X        return(ISDIRE);
X    else
X        if(fname`5B--len`5D == '.')
X           if (dot == 0)
X                fname`5Blen`5D = 0; /* No trailing dots  */
X        return(ISFILE);
X`7D
X/* initsearch - parse input file name */
X/* To start looking for file names to satisfy the requested input,
X* use the sys$parse routine to create a wild-card name block. When
X* it returns, we can then use the resultant FAB and NAM blocks on
X* successive calls to sys$search() until there are no more files
X* that match.
X*/
X
Xint initsearch(string)
Xchar string`5B`5D;
X`7B
Xint status;
Xchar *strindex();
X
X    if(strindex(string,"::")!=NULL)
X    `7B
X        printf("tar: DECnet file access is not supported.\n");
X        return(-1);
X    `7D
X    fblock = cc$rms_fab;
X    nblock = cc$rms_nam;
X    fblock.fab$l_dna = default_name;
X    fblock.fab$b_dns = strlen(default_name);
X    fblock.fab$l_fna = string;
X    fblock.fab$b_fns = strlen(string);
X    fblock.fab$l_nam = &nblock;
X    nblock.nam$l_esa = searchname;
X    nblock.nam$b_ess = sizeof(searchname);
X#ifdef debug
X    printf("searching on: %s\n",string);
X#endif
X    status = sys$parse(&fblock);
X    if(status != RMS$_NORMAL)
X    `7B
X        if(status == RMS$_DNF)
X            printf("tar: directory not found %s\n",searchname);
X        else
X            printf("tar: error in SYS$PARSE.\n");
X        return (-1);
X    `7D
X    searchname`5Bnblock.nam$b_esl`5D = 0;   /* Terminate the string  */
X
X    /* Now reset for searching, pointing to the parsed name block */
X
X    fblock = cc$rms_fab;
X    fblock.fab$l_nam = &nblock;
X    return(nblock.nam$b_esl); /* return the length of the string  */
X`7D
X
X/* search - get the next file name that matches the namblock */
X/* that was set up by the sys$search() function. */
X
Xint search(buff,maxlen)
Xchar buff`5B`5D;
Xint maxlen;
X`7B
Xint status;
X
X    nblock.nam$l_rsa = buff;
X    nblock.nam$b_rss = maxlen;
X    nblock.nam$b_rsl = 0;       /* For next time around  */
X    while ((status = sys$search(&fblock)) != RMS$_NMF)
X    `7B
X        buff`5Bnblock.nam$b_rsl`5D = 0;
X        if(status == RMS$_NORMAL)
X            return(nblock.nam$b_rsl);
X        else
X        `7B
X            if (status == RMS$_PRV)
X                printf("tar: no privilege to access %s\n",buff);
X            else if (status == RMS$_FNF)
X                printf("tar: file not found %s\n",buff);
X            else
X            `7B
X                printf("tar: error in SYS$SEARCH for %s\n", buff);
X                return (0);
X            `7D
X        `7D
X    `7D
X    return (0);
X`7D
X/* fill_header - fill the fields of the header */
X/* enter with the file name, if the file name is empty, */
X/* then this is a trailer, and we should fill it with zeroes. */
X
Xint fill_header(name)
Xchar name`5B`5D;
X`7B
Xint i,chksum;
Xint zero = 0, hdrsize = RECSIZE;
Xchar *ptr,tem`5B15`5D;
X
X/* Fill the header with zeroes */
X
X    LIB$MOVC5(&zero, &zero, &zero, &hdrsize, &header); `20
X    if(strlen(name)!=0)         /* only fill if there is a file */
X    `7B
X        sprintf(header.title,"%s",name);        /* write file name */
X        sprintf(header.protection,"%6o ",mode); /* all written with */
X        sprintf(header.uid,"%6o ",uid);         /* a trailing space */
X        sprintf(header.gid,"%6o ",gid);
X        sprintf(tem,"%11o ",bytecount);         /* except the count */
X        strncpy(header.count,tem,12);           /* and the time, which */
X        sprintf(tem,"%11o ",vmstime);           /* except the count */
X        strncpy(header.time,tem,12);            /* have no null */
X        strncpy(header.chksum,"        ",8);    /* all blanks for sum*/
X
X/* I know that the next two are already zero, but do them */
X
X        header.linkcount = 0;                   /* always zero */
X        sprintf(header.linkname,"%s","");       /* always blank */
X        for(chksum=0, ptr = &header;ptr < &header.linkcount;ptr++)
X                 chksum += *ptr;                /* make the checksum */
X        sprintf(header.chksum,"%6o",chksum);
X    `7D
X    return(0);
X`7D
X
X/* strindex - search for string2 in string1, return address pointer */
X
Xchar *strindex(string1,string2)
Xchar *string1,*string2;
X`7B
Xchar *c1, *c2, *cp;
X    for(c1 = string1; *c1 !=0; c1++)
X    `7B
X        cp = c1;        /* save the start address */
X        for(c2=string2; *c2 !=0 && *c1 == *c2; c1++,c2++);
X           if(*c2 == 0)
X                return(cp);
X    `7D
X    return(NULL);
X`7D
X
X/* lowercase - function to change a string to lower case */
X
Xint lowercase(string)
Xchar string`5B`5D;
X`7B
Xint i;
X        for(i=0;string`5Bi`5D=tolower(string`5Bi`5D);i++);
X        return (--i);           /* return string length */
X`7D
X
X/* cleanup_dire - routine to get rid of rooted directory problems */
X/* and any others that turn up */
X
Xint cleanup_dire(string)
Xchar string`5B`5D;
X`7B
Xchar *ptr;
X        if((ptr=strindex(string,"`5D`5B")) != NULL)
X        `7B       /* Just collapse around the string */
X          strcpy(ptr,ptr+2);
X          return(1);
X        `7D
X        if((ptr=strindex(string,"`5B000000.")) != NULL)
X        `7B         /* remove "000000." */
X            strcpy(ptr + 1, ptr + 8);
X            return(1);
X        `7D
X        return(0);
X`7D
X
X/* Syntax error exit */
X
Xusage()
X`7B
X    printf("usage: tar x`7Cc`7Ct`5Bvbdz`5D`5Bf tarfile`5D `5Bfile `5Bfile...
V`5D`5D\n");
X    exit(1);
X`7D
$ CALL UNPACK VMSTAR.C;71 1834579784
$ create 'f'
X1 VMSTAR
X
X VMSTAR  is  a  TAR  reader/writer  for  VMS.  It  can  read  archives
X ("tarfiles") created by the Un*x command "tar" (VMSTAR has a  similar
X syntax) and also create such archives so that they can be read  later
X by a Un*x system. Tarfiles can be VMS disk files or directly on tape.
X Default tarfile is  whatever  the  logical  name  "$TAPE"  points  to
X (either device or file name) unless specified by  the  "f"  modifier.
X
X Tapes read/written by VMSTAR must be mounted /FOREIGN/RECORD=512/BLOCK=1024
V0
X
X Usage:    $ VMSTAR `5Boptions`5D `5Bfilespec `5Bfilespec...`5D`5D
X2 Options
X Options are single letters grouped together (no space). There must be
X at  list one of "x" (extract), "t" (type) or "c" (create) to indicate
X what  kind  of  action  VMSTAR  should have. Other single letters are
X modifiers.  The group of options may optionally include a leading "-"
X (dash).
X3 x (extract)
X This option instructs VMSTAR that files are to be extracted from  the
X tar archive and copied as VMS  files.  One  or  more  Un*x-like  file
X specifications including VMS wildcard characters may  be  present  on
X the command line. Only files matching one of  the  patterns  will  be
X actually   extracted.   Default   is   to    extract    all    files.
X
X VMSTAR will attempt to re-create the directory hierarchy  present  in
X the tar archive. If files are named "./foo/bar..." in the tar archive
X (common case) the VMS directory tree  will  be  created  relative  to
X current default.  All  illegal  characters  in  file  names  will  be
X replaced by "_" (underscore).
X3 t (type)
X This option produces a listing of the contents of  the  tar  archive,
X including file name (Un*x style), size (in  bytes)  and  modification
X date.
X3 c (create)
X This  option  directs  VMSTAR to create a tar archive and to copy VMS
X files  as directed by file specification(s) into this archive in such
X a  way  it  can  be  further  extracted  on  an  Un*x  machine.  File
X specifications  (space separated, no commas) can include standard VMS
X wildcards in file and directory name.
X
X If a relative specification  is  given  (no  directory  or  directory
X beginning with "`5B." and no device name), the file name given  is  the
X tar  archive  will  be  relative  too  (not   beginning   with   "/")
X3 v (verbose)
X Adding this modifier to a "x" or "c"  option  will  cause  VMSTAR  to
X display file names and sizes stored when archiving VMS files and  VMS
X directory and file names created when  extracting  from  an  archive.
X3 w (wait)
X VMSTAR asks for a  confirmation  before  each  file  is  archived  or
X extracted when this modifier is specified.
X3 b (binary)
X This modifier is meaningful only when VMSTAR extracts  files  from  a
X tar archive. If it is specified, VMSTAR  will  create  VMS  files  in
X fixed format, record size = 512 bytes and no record  attributes.  Use
X the "b" modifier when you extract  compressed  files,  tar  archives,
X executable VMS images or any kind of files  other  than  ASCII  files
X with line-feed terminated lines.
X
X When  this  modifier  is  *NOT*  present,  VMS  files  are created as
X stream-LF    files    with    implied    (CR)    record   attributes.
X3 z (automatic mode)
X When this modifier is  present  in  a  extract  operation  (it's  not
X meaningful  for  any  other  operation),  VMSTAR  will   attempt   to
X automatically determine if the file present in  the  tar  archive  is
X text or binary, and extract it  accordingly  (see  'b'  option).  The
X choice is based on very  simple  rules  such  as  the  proportion  of
X characters in the range 0-31 except CR, LF, FF  and  TAB  ;  and  the
X proportion of the characters above 127 in  the  first  block  of  the
X file.
X3 d (dots)
X This modifier is only meaningful for the "c" (create) option. When it
X is specified, VMSTAR will keep the trailing dot in file names without
X extension in the archive.
X3 f tarfile
X This  modifier allows to specify the tarfile (either VMS file name of
X VMS  device  name) read or written by VMSTAR. Default is whatever the
X logical    name   $TAPE   points   to,   either   file   or   device.
X2 Filespec
X One or more file specifications may be present on the command line as
X last arguments. They must be separated by spaces, *NOT*  commas  like
X in most VMS commands. They may include VMS  wildcard  characters  "*"
X and "%". Case is never significant.
X
X Upon create, the file  specifications  must  be  valid  VMS  file  or
X directory names. If only a directory name  is  specified,  "*.*;"  is
X automatically appended. The resultant specifications are the names of
X the VMS file names that will be  archived  in  the  tarfile.  Use  of
X device names and absolute paths ("`5BFOO.BAR`5D") is strongly discouraged
X unless  absolute  archives  are  to  be  created  (see  "c"  option).
X
X Upon  extract,  the  file  specifications  must be Un*x file names or
X patterns  for Un*x file names using VMS wildcard characters. Files in
X the  tarfile  having names matching one of the specifications will be
X extracted.  If  no  specification  is given, all files are extracted.
X Matching  is  done using pure wildcarded strings matching algorithms,
X i.e. "/" is a normal character.
X2 Examples
X $ MOUNT/FOREIGN/RECORD=512/BLOCK=10240
X $ VMSTAR TVF MUA0:
X
X Will give a full listing of the tar tape loaded in MUA0:
X
X $ SET DEF `5BFOO_ROOT`5D
X $ TAR XVF MUA0:
X
X Will  extract  files  from the tar tape in `5BFOO_ROOT...`5D provided the
X files in the tar archive do not begin with "/".
X
X $ DEFINE $TAPE MUA0:
X $ TAR XV *SOURCES/*.C
X
X Will  only  extract  C source files in the subdirectory "sources" (or
X "Sources"  or  "SOURCES",  case is not significant) from the tar tape
X mounted in MUA0:
X
X $ TAR XVF EMACS.TAR
X
X Will  extract  files in tar archive file EMACS.TAR which may has been
X transmitted from a Un*x system by network.
X
X $ TAR XVBF EMACS.TAR ./EXECUTABLE/EMACS.EXE
X
X Will  only  extract  the  specified file and create it as a VMS fixed
X format,   record  size  =  512  bytes,  no  record  attributes  file.
X
X $ TAR CWVF MUA0: `5B.GNUCC...`5D
X
X Will archive the contents of the whole  "`5B.GNUCC...`5D"  subtree  in  a
X tape tar archive on MUA0:. VMSTAR will prompt user  before  archiving
X each file.
X
X $ DEFINE $TAPE TARFILE.TAR
X $ TAR CV *.DOC `5B.GNUCC...`5D
X
X Will create a tar archive file TARFILE.TAR and write all files with
X type ".DOC" and all the "`5B.GNUCC...`5D" subtree in it.
X2 Restrictions
X Because of diffrences in the Un*x and VMS filesystems, some files may
X fail to be correctly transferred to/from the  tarfile.  This  can  be
X caused by :
X
X - restrictions in VMS file naming scheme: extra dots  in  file  names
X will  be  mapped  to  underscores,  dummy  directory  names  will  be
X generated if archive contains more than 8 levels  of  subdirectories,
X links are extracted as empty files containing only  a  short  message
X "this file is only a link  to...",  all  file  names  are  mapped  to
X uppercase etc.
X
X - restrictions of the Un*x filesystem: tar will only get  the  latest
X version of a VMS file to enter it into the archive, no trace  of  the
X orginal file device name is kept in the archive.
X
X - VMS strong file typing: VMSTAR can only  safely  tranfer  back  and
X forth VMS "text" files (rfm=vfc or  stream_lf  with  rat=cr)  or  VMS
X fixed size record, 512 bytes/record, rat=none files (e.g. .EXE  image
X files). VMSTAR will skip other file types  (this  includes  .OBJ  and
X library files, they *can't* be archived).
X
X Other restrictions:
X
X RMS file attributes are lost in the archive process, text  files  are
X archived as <record><LF><record><LF>, fixed files are archived as is.
X
X VMSTAR will always restore files relative to your current RMS default
X if names in tarfile do not begin by `60/'. If  file  names  in  tarfile
X begin with a `60/' (bad practice), an attempt will be made  to  restore
X files to the absolute path. There is currently no way to  explicitely
X specify the target VMS directory where  files  should  be  extracted.
X
X No  attempt has been made to handle search list as RMS defaults (e.g.
X SYSTEM account). Be very careful about that.
$ CALL UNPACK VMSTAR.HLP;10 1518046826
$ create 'f'
X$! BUILD.COM - Compiles and link VMSTAR
X$
X$ CC VMSTAR
X$ LINK VMSTAR,SYS$INPUT/OPT
XSYS$SHARE:VAXCRTL.EXE/SHARE
X
$ CALL UNPACK BUILD.COM;1 1547639552
$ v=f$verify(v)
$ EXIT
