From:	ADVAX::"mcnc!CUNYVM.CUNY.EDU!MAILSERV%FRSIM51.BITNET" 24-SEP-1990 09:35:04.55
To:	ARISIA::EVERHART
CC:	
Subj:	MAEVA:[MAILSERV.PUB.VMSTAR]VMSTAR.SHARE_2;1

Received: by ADVAX.DECnet (utk-mail11 v1.5) ; Mon, 24 Sep 90 09:36:32 EDT
Received:  from mcnc by ge-dab.GE.COM (5.61/GE-DAB 1.12) with UUCP
	id AA09665 for everhart; Mon, 24 Sep 90 09:36:04 -0400
Received: from CUNYVM.CUNY.EDU by mcnc.mcnc.org (5.59/MCNC/6-11-90)
	id AA16359; Mon, 24 Sep 90 08:46:11 -0400
Message-Id: <9009241246.AA16359@mcnc.mcnc.org>
Received: from FRSIM51.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.2.2MX) with BSMTP id 2875; Mon, 24 Sep 90 08:44:51 EDT
Date: 24 SEP 90 14:40:12.57-WET
From: mcnc!CUNYVM.CUNY.EDU!MAILSERV%FRSIM51.BITNET
Subject: MAEVA:[MAILSERV.PUB.VMSTAR]VMSTAR.SHARE_2;1
To: ARISIA::EVERHART
 
-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
X/* Remove illegal characters from directory and file names; replace
X* hyphens and commas with underscores.Returns number of translations
X* that were made.
X*/
X
Xvms_cleanup(string)
Xchar string`5B`5D;
X`7B
Xint i,flag=0;
Xchar c;
X    for(i=0;c=string`5Bi`5D;i++)
X        `7B
X        switch (c)
X            `7B
X            case ',':           /* No commas in file names  */
X                string`5Bi`5D= '_';
X                flag++;         /* Record if any changes were made */
X                break;
X            default:
X                string`5Bi`5D = toupper(c); /* map to uppercase */
X                break;
X            `7D
X        `7D
X    return(flag);
X`7D
X
X/* vms2tar -- handles create function */
X
Xvms2tar(argc,argv)
Xint argc;
Xchar **argv;
X`7B
X    int argi, process, file_type, absolute;
X    char string`5BNAMSIZE`5D, *cp, *dp, *wp;
X
X    if (argc < 3 `7C`7C (foption && argc < 4)) usage();
X
X    bufferpointer = 0;
X    gid = getgid();
X    uid = getuid();
X    mode = 0644;
X
X/* Open the output file */
X
X    outfd = creat(tarfile,0600,"rfm=fix","mrs=512");
X    if (outfd < 0)
X    `7B
X        printf("tar: error opening output tarfile %s\n", tarfile);
X        exit(SS$_NORMAL);
X    `7D `20
X
X    for (argi = foption ? 3 : 2; argi < argc; ++argi)
X    `7B
X        strcpy(string, argv`5Bargi`5D);
X        absolute = 0;
X        cp = strchr(string, ':');   /* device name in argument ? */
X        if (cp != NULL)            /* yes, force absolute mode */
X            absolute = 1;
X        else
X        `7B
X            cp = strchr(string, '`5B');  /* test argument for absolute... */
X            if (cp != NULL)            /* ...or relative filespec */
X            `7B
X                ++cp;
X                if (*cp != '.' && *cp != '-')
X                    absolute = 1;
X            `7D
X        `7D
X        if(initsearch(string) <= 0)
X            printf("tar: no files matching %s\n",string);
X        else
X          while(search(newfile,NAMSIZE)!=0)
X          `7B
X            strcpy(linkname, newfile);
X            cleanup_dire(newfile);
X            file_type = scan_name(newfile,new_directory,outfile,absolute);
X            strcpy(pathname,new_directory);
X            strcat(pathname,outfile);
X            get_attributes(newfile);
X            process = 1;
X            if(wait)
X            `7B
X                *temp = '\0';
X                while (*temp != 'y' && *temp != 'n')
X                `7B
X                    printf("%s   (y/n) ? ", linkname);
X                    scanf("%s", temp);
X                    *temp = tolower(*temp);
X                `7D
X                process = (*temp == 'y');
X            `7D
X            if (process)
X            `7B
X                if(file_type == ISDIRE)
X                `7B
X                    bytecount =  0;
X                    mode = 0755;
X                    fill_header(pathname);
X                    write_header(outfd);
X                `7D
X                if(file_type == ISFILE)
X                `7B
X                    mode = 0644;
X                    if(addfile(newfile, pathname) < 0)
X                    `7B
X                        printf("tar:error copying %s\n",linkname);
X                        exit(SS$_NORMAL);
X                    `7D
X                `7D
X                if (bytecount == 0 && file_type == ISFILE)
X                    printf("*** skipped  %s\n", linkname);
X                if (verbose && (bytecount `7C`7C file_type == ISDIRE))
X                `7B
X                     strcpy(creation,ctime(&vmstime)); /* work on this */
X                     creation`5B24`5D=0;
X                     printf("%s %6d %s\n",creation + 4,bytecount,pathname);
X                `7D
X            `7D
X          `7D
X    `7D
X    write_trailer(outfd);
X    close(outfd);
X`7D
X
X/* addfile - copy the vms file to the output file */
X
Xint addfile(vmsname,unixname)
Xchar vmsname`5B`5D,unixname`5B`5D;
X`7B
Xint ind;
X    if(bytecount == 0)          /* we don't output null files  */
X        return(0);
X    if((ind=out_file(vmsname,bytecount,outfd)) < 0)
X        return(ind);
X    bufferpointer = bufferpointer%BLKSIZE;
X    return(1);
X`7D
X
X
X/* out_file - write out the file.
X* move nbytes of data from "fdin" to "fdout";
X* Always pad the output to a full DSIZE
X* If it a VMS text file, it may be various formats, so we will
X* write into a temporary file first, then copy to the output
X* so that we get the correct byte count.
X* We set the bytecount=0 if this is funny file.
X*/
X
Xint out_file(filename,nbytes,fdout)
Xchar filename`5B`5D;
Xint fdout, nbytes;
X`7B
Xint i, n, pos, fdin;
Xchar *bufp, *linep;
XFILE *filein;
X
X    if(vmsrfm == FIXED)
X    `7B
X        if((fdin=open(filename,0)) <=0)
X        `7B
X            printf("tar: error opening input file %s\n",filename);
X            return(-1);
X        `7D
X        fill_header(pathname);          /* We have all of the information */
X        write_header(outfd);            /* So write to the output */
X        while(nbytes > 0)
X        `7B
X            n = read(fdin,buffer,nbytes>DSIZE? DSIZE:nbytes);
X            if(n<0)
X            `7B
X                close(fdin);
X                printf("tar: error reading input file %s\n",filename);
X                return(-1);
X            `7D
X            nbytes -= n;
X            flushout(fdout);
X        `7D
X        close(fdin);
X        return(0);
X    `7D
X    else
X        if(vmsrat != 0)                 /* must be a text file  */
X        `7B                               /* compute "Unix" file size */
X            if((filein = fopen(filename,"r")) == NULL)
X            `7B
X                printf("tar: error opening input file %s\n",filename);
X                return(-1);
X            `7D
X            nbytes = 0;
X            while(fgets(dbuffer,DSIZE,filein) !=  NULL)
X                nbytes += strlen(dbuffer);
X            rewind(filein);                 /* Back to the beginning  */
X            bytecount = nbytes;             /* Use the real count  */
X            fill_header(pathname);          /* Compute the header */
X            write_header(outfd);            /* Write it  */
X            bufp = buffer;
X
X            while(fgets(dbuffer,DSIZE,filein) !=  NULL)
X            `7B                               /* Now copy to the output */
X                linep = dbuffer;
X                while (*linep != '\0')      /* read source file line by line
V */
X                `7B
X                    *bufp++ = *linep++;  /* copy in fixed size output buffer
V */
X                    if (bufp >= &buffer`5BDSIZE`5D)
X                    `7B
X                        bufp = buffer;
X                        flushout(fdout);         /* if buffer full, flush it
V */
X                    `7D
X                `7D
X            `7D
X            flushout(fdout);
X            return(0);
X        `7D
X                        /* Other formats e.g. .OBJ are not done  */
X        bytecount = 0;
X        return(0);
X`7D
X
X/* flushout - write a fixed size block in output tarfile */
X
Xflushout(fdout)
Xint fdout;
X`7B
X    if (write(fdout,buffer,DSIZE) != DSIZE)
X    `7B
X        printf("tar: error writing tarfile.\n");
X        exit(SS$_NORMAL);
X    `7D
X    bufferpointer += DSIZE;
X`7D
X
X/* write_header - copy the header to the output file  */
X
Xint write_header(fd)
Xint fd;
X`7B
Xint n;
X    if((n=write(fd,&header,DSIZE))!=DSIZE)
X    `7B
X        printf("tar: error writing header in tarfile.\n");
X        exit(SS$_NORMAL);
X    `7D
X    bufferpointer += DSIZE;
X    return(n);
X`7D
X
X/*  get_attributes - get the file attributes via stat()  */
X
Xint get_attributes(fname)
Xchar fname`5B`5D;
X`7B
X    if(stat(fname,&sblock))
X    `7B
X        printf("tar: can't get file status on %s\n",fname);
X        vmstime = 0;                    /* Prevent garbage printoout */
X        bytecount = 0;                  /* of inaccessible files  */
X        return(-1);
X    `7D
X
X/* now get the file attributes, we don't use them all */
X    bytecount = sblock.st_size;
X    vmsrat = sblock.st_fab_rat;
X    vmsmrs = sblock.st_fab_mrs;
X    vmsrfm = sblock.st_fab_rfm;
X    vmstime = sblock.st_mtime;
X`7D
X
X
X/* write_trailer - write the two blank blocks on the output file */
X/* pad the output to a full blocksize if needed. */
X
Xwrite_trailer(fdout)
Xint fdout;
X`7B
Xint i;
X    for (i=0; i < NAMSIZE; ++i)
X        header.title`5Bi`5D = '\0';
X    write_header(fdout);
X    write_header(fdout);
X    bufferpointer = bufferpointer%BLKSIZE;
X    while (bufferpointer < BLKSIZE)
X        write_header(fdout);
X    return(1);
X`7D
X
X/* scan_name - decode a file name */
X
X/* Decode a file name into the directory, and the name, and convert
X* to a valid UNIX pathname. Return  a value to indicate if this is
X* a directory name, or another file.
X* We return the extracted directory string in "dire", and the
X* filename (if it exists) in "fname". The full title is in "line"
X* at input.
X*/
X
Xint scan_name(line,dire,fname,absolute)
Xchar line`5B`5D,dire`5B`5D,fname`5B`5D;
Xint absolute;
X`7B
Xchar *cp1,*cp2;
Xint len,len2,i;
Xchar *strindex();
X
X/* The format will be VMS at input, so we have to scan for the
X* VMS device separator ':', and also the VMS directory separators
X* '`5B' and '`5D'.
X* If the name ends with '.dir;1' then it is actually a directory name.
X* The outputs dire and  fname will be a complete file spec, based on the def
Vault
X* directory.
X* It may be a rooted directory, in which case there will be a "`5D`5B" strin
Vg,
X* remove it.
X* Strip out colons from the right, in case there is a node name (should not
V be!)
X* If the filename ends in a trailing '.', suppress it , unless the "d" optio
Vn
X* is set.
X*/
X
X
X    strcpy(temp,strrchr(line,':')+1);           /* Start with the whole name
V */
X
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 = DSIZE;
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`5Bvbd`5D`5Bf tarfile`5D `5Bfile `5Bfile...`
V5D`5D\n");
X    exit(1);
X`7D
$ CALL UNPACK VMSTAR.C;36 2015640688
$ v=f$verify(v)
$ EXIT
