From:	CSBVAX::MRGATE!info-vax-RELAY@KL.SRI.COM@SMTP  9-JUL-1988 04:10
To:	ARISIA::EVERHART
Subj:	ARC_C.SHAR04_OF_19


Received: from CORNELLC.CCS.CORNELL.EDU by KL.SRI.COM with TCP; Fri, 24 Jun 88 18:53:04 PDT
Received: from UNCAEDU.BITnet by CORNELLC.CCS.CORNELL.EDU ; Fri, 24 Jun 88 21:53:20 EDT
Received: from Stasis.MRC.AdhocNet.CA by UcEdu.UNCA.AdhocNet.CA with DECNET ;
          Fri, 24 Jun 88 09:29:16 MDT
Date:    Fri, 24 Jun 88 09:23:38 MDT
From:     ewilts%Ins.MRC.AdhocNet.CA%Stasis.MRC.AdhocNet.CA%UNCAEDU.@CORNELLC.CCS.CORNELL.EDU
         BITnet (Ed Wilts)
Message-Id: <880624092341.024@Ins.MRC.AdhocNet.CA>
Subject: ARC_C.SHAR04_OF_19
To:       info-vax@kl.sri.com
X-ST-Vmsmail-To: INFOVAX

$Part04:
$ File_is="ARCDIR.C"
$ Check_Sum_is=611663484
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcdir.c,v 1.2 86/07/15 07:52:56 turner Exp $";
X
X/*
X * $Log:`009arcdir.c,v $
X * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
X * `009Bludgeoned into submission for VAX 11/780 BSD4.2
X *`009(ugly code, but fewer core dumps)
X *
X * Revision 1.2  86/07/15  07:52:56  turner
X *
X *
X * Revision 1.1  86/06/26  15:00:12  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCDIR
X*/
X#include <stdio.h>
X#include "arc.h"
X
X#if MSDOS
X#include <dir.h>
X#endif
X
X#ifndef VAXC
X#if BSD
X#include <sys/types.h>
X#include <sys/dir.h>
X#endif
X#else
X#include "dir.h"
X#endif
X
Xchar *pattern;`009`009`009      /* global so that fmatch can use them */
XINT filemode;
X
Vextern char *dir(filename,mode,NameList)               /* get files, one by one
X */
Xchar *filename;                        /* template, or NULL */
XINT mode;                              /* search mode bits */
Xchar *(*NameList[]);
X{
X/*        struct direct *(*namelist[]);`009*/
X        static struct direct *(**namelist), *np;
X#ifdef BSD
X`009INT alphasort();
X`009INT scandir();
X#endif BSD
X        INT fmatch();
X`009static INT Nnum = 0,ii;
X`009char *result;
X
X`009pattern = filename;
X`009filemode = mode;`009`009/* set up globals for fmatch */
X`009if(Nnum == 0) {                  /* first call */
X/* cmb */
X`009    namelist = (char **)malloc(sizeof(char **));
X            Nnum = scandir(".", namelist, fmatch, alphasort);
X            *NameList = (char **)malloc(Nnum*sizeof(char *));
X            for (ii=0; ii<Nnum; ii++) {
V/*                (*NameList)[ii] = (char *)malloc((*namelist)[ii]->d_namlen+1)
X;
X *               strcpy((*NameList)[ii],(*namelist)[ii]->d_name);
X */
X                (*NameList)[ii] = (char *)malloc((*namelist)[ii]->d_namlen+1);
X                strcpy((*NameList)[ii],(*namelist)[ii]->d_name);
X            }
X            ii = 0;
X`009}
X`009if(ii >= Nnum) { /* all out of files */
X`009`009if(Nnum) { /* there were some files found */
X`009`009    freedir(namelist);
X`009`009    }
X`009`009Nnum = 0;
X`009`009return(NULL);
X`009}
X`009else {
X`009`009return((*NameList)[ii++]);
X`009}
X}
X
X
X#define ASTERISK '*'`009`009/* The '*' metacharacter */
X#define QUESTION '?'`009`009/* The '?' metacharacter */
X#define LEFT_BRACKET '['`009/* The '[' metacharacter */
X#define RIGHT_BRACKET ']'`009/* The ']' metacharacter */
X
X#define IS_OCTAL(ch) (ch >= '0' && ch <= '7')
X
Xtypedef INT BOOLEAN;
X#define VOID short
X#define TRUE 1
X#define FALSE 0
X#define EOS '\000'
X
Xstatic BOOLEAN do_list ();
Xstatic char nextch ();
Xstatic VOID list_parse ();
X
X`012
X/*
X *  FUNCTION
X *
X *`009match   test string for wildcard match
X *
X *  SYNOPSIS
X *
X *`009BOOLEAN match (string, pattern)
X *`009register char *string;
X *`009register char *pattern;
X *
X *  DESCRIPTION
X *
X *`009Test string for match using pattern.  The pattern may
X *`009contain the normal shell metacharacters for pattern
X *`009matching.  The '*' character matches any string,
X *`009including the null string.  The '?' character matches
X *`009any single character.  A list of characters enclosed
X *`009in '[' and ']' matches any character in the list.
X *`009If the first character following the beginning '['
X *`009is a '!' then any character not in the list is matched.
X *
X */
X
X`012
X/*
X *  PSEUDO CODE
X *
X *`009Begin match
X *`009    Switch on type of pattern character
X *`009`009Case ASTERISK:
X *`009`009    Attempt to match asterisk
X *`009`009    Break
X *`009`009Case QUESTION MARK:
X *`009`009    Attempt to match question mark
X *`009`009    Break
X *`009`009Case EOS:
X *`009`009    Match is result of EOS on string test
X *`009`009    Break
X *`009`009Case default:
X *`009`009    If explicit match then
X *`009`009`009Match is result of submatch
X *`009`009    Else
X *`009`009`009Match is FALSE
X *`009`009    End if
X *`009`009    Break
X *`009    End switch
X *`009    Return result of match test
X *`009End match
X *
X */
X
Xstatic BOOLEAN match (string, pattern)
Xregister char *string;
Xregister char *pattern;
X{
X    register BOOLEAN ismatch;
X
X    ismatch = FALSE;
X    switch (*pattern) {
X`009case ASTERISK:
X`009    pattern++;
X`009    do {
X`009`009ismatch = match (string, pattern);
X`009    } while (!ismatch && *string++ != EOS);
X`009    break;
X`009case QUESTION:
X`009    if (*string != EOS) {
X`009`009ismatch = match (++string, ++pattern);
X`009    }
X`009    break;
X`009case EOS:
X`009    if (*string == EOS) {
X`009`009ismatch = TRUE;
X`009    }
X`009    break;
X`009case LEFT_BRACKET:
X`009    if (*string != EOS) {
X`009`009ismatch = do_list (string, pattern);
X`009    }
X`009    break;
X`009default:
X`009    if (tolower(*string) == tolower(*pattern))
X`009    {
X`009    `009string++;
X`009    `009pattern++;
X`009`009ismatch = match (string, pattern);
X`009    } else {
X`009`009ismatch = FALSE;
X`009    }
X`009    break;
X    }
X    return (ismatch);
X}
X
X`012
X/*
X *  FUNCTION
X *
X *`009do_list    process a list and following substring
X *
X *  SYNOPSIS
X *
X *`009static BOOLEAN do_list (string, pattern)
X *`009register char *string;
X *`009register char *pattern;
X *
X *  DESCRIPTION
X *
X *`009Called when a list is found in the pattern.  Returns
X *`009TRUE if the current character matches the list and
X *`009the remaining substring matches the remaining pattern.
X *
X *`009Returns FALSE if either the current character fails to
X *`009match the list or the list matches but the remaining
X *`009substring and subpattern's don't.
X *
X *  RESTRICTIONS
X *
X *`009The mechanism used to match characters in an inclusive
X *`009pair (I.E. [a-d]) may not be portable to machines
X *`009in which the native character set is not ASCII.
X *
X *`009The rules implemented here are:
X *
X *`009`009(1)`009The backslash character may be
X *`009`009`009used to quote any special character.
X *`009`009`009I.E.  "\]" and "\-" anywhere in list,
X *`009`009`009or "\!" at start of list.
X *
X *`009`009(2)`009The sequence \nnn becomes the character
X *`009`009`009given by nnn (in octal).
X *
X *`009`009(3)`009Any non-escaped ']' marks the end of list.
X *
X *`009`009(4)`009A list beginning with the special character
X *`009`009`009'!' matches any character NOT in list.
X *`009`009`009The '!' character is only special if it
X *`009`009`009is the first character in the list.
X *
X */
X
X`012
X/*
X *  PSEUDO CODE
X *
X *`009Begin do_list
X *`009    Default result is no match
X *`009    Skip over the opening left bracket
X *`009    If the next pattern character is a '!' then
X *`009`009List match gives FALSE
X *`009`009Skip over the '!' character
X *`009    Else
X *`009`009List match gives TRUE
X *`009    End if
X *`009    While not at closing bracket or EOS
X *`009`009Get lower and upper bounds
X *`009`009If character in bounds then
X *`009`009    Result is same as sense flag.
X *`009`009    Skip over rest of list
X *`009`009End if
X *`009    End while
X *`009    If match found then
X *`009`009If not at end of pattern then
X *`009`009    Call match with rest of pattern
X *`009`009End if
X *`009    End if
X *`009    Return match result
X *`009End do_list
X *
X */
X
Xstatic BOOLEAN do_list (string, pattern)
Xregister char *string;
Xchar *pattern;
X{
X    register BOOLEAN ismatch;
X    register BOOLEAN if_found;
X    register BOOLEAN if_not_found;
X    auto char lower;
X    auto char upper;
X
X    pattern++;
X    if (*pattern == '!') {
X`009if_found = FALSE;
X`009if_not_found = TRUE;
X`009pattern++;
X    } else {
X`009if_found = TRUE;
X`009if_not_found = FALSE;
X    }
X    ismatch = if_not_found;
X    while (*pattern != ']' && *pattern != EOS) {
X`009list_parse (&pattern, &lower, &upper);
X`009if (*string >= lower && *string <= upper) {
X`009    ismatch = if_found;
X`009    while (*pattern != ']' && *pattern != EOS) {pattern++;}
X`009}
X    }
X    if (*pattern++ != ']') {
X`009fprintf (stderr, "warning - character class error\n");
X    } else {
X`009if (ismatch) {
X`009    ismatch = match (++string, pattern);
X`009}
X    }
X    return (ismatch);
X}
X
X`012
X/*
X *  FUNCTION
X *
X *`009list_parse    parse part of list into lower and upper bounds
X *
X *  SYNOPSIS
X *
X *`009static VOID list_parse (patp, lowp, highp)
X *`009char **patp;
X *`009char *lowp;
X *`009char *highp;
X *
X *  DESCRIPTION
X *
X *`009Given pointer to a pattern pointer (patp), pointer to
X *`009a place to store lower bound (lowp), and pointer to a
X *`009place to store upper bound (highp), parses part of
X *`009the list, updating the pattern pointer in the process.
X *
X *`009For list characters which are not part of a range,
X *`009the lower and upper bounds are set to that character.
X *
X */
X
Xstatic VOID list_parse (patp, lowp, highp)
Xchar **patp;
Xchar *lowp;
Xchar *highp;
X{
X    *lowp = nextch (patp);
X    if (**patp == '-') {
X`009(*patp)++;
X`009*highp = nextch (patp);
X    } else {
X`009*highp = *lowp;
X    }
X}
X
X`012
X/*
X *  FUNCTION
X *
X *`009nextch    determine next character in a pattern
X *
X *  SYNOPSIS
X *
X *`009static char nextch (patp)
X *`009char **patp;
X *
X *  DESCRIPTION
X *
X *`009Given pointer to a pointer to a pattern, uses the pattern
X *`009pointer to determine the next character in the pattern,
X *`009subject to translation of backslash-char and backslash-octal
X *`009sequences.
X *
X *`009The character pointer is updated to point at the next pattern
X *`009character to be processed.
X *
X */
X
Xstatic char nextch (patp)
Xchar **patp;
X{
X    register char ch;
X    register char chsum;
X    register INT count;
X
X    ch = *(*patp)++;
X    if (ch == '\\') {
X`009ch = *(*patp)++;
X`009if (IS_OCTAL (ch)) {
X`009    chsum = 0;
X`009    for (count = 0; count < 3 && IS_OCTAL (ch); count++) {
X`009`009chsum *= 8;
X`009`009chsum += ch - '0';
X`009`009ch = *(*patp)++;
X`009    }
X`009    (*patp)--;
X`009    ch = chsum;
X`009}
X    }
X    return (ch);
X}
X
X/*
X *`009Filename match - here, *.* matches everything
X */
X
XBOOLEAN fmatch (direntry)
Xstruct direct *direntry;
X{
X    char *ptr,*string;
X
X    string = direntry->d_name;
X
X    if(!strcmp(pattern, "") || !strcmp(pattern, "*.*"))
X    `009return(1);
X    return(match(string, pattern));
X}
X
$ GoSub Convert_File
$ File_is="ARCDOS.C"
$ Check_Sum_is=1651676921
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcdos.c,v 1.2 86/07/15 07:53:02 turner Exp $";
X
X/*
X * $Log:`009arcdos.c,v $
X * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
X * `009Bludgeoned into submission for VAX 11/780 BSD4.2
X *`009(ugly code, but fewer core dumps)
X *
X * Revision 1.2  86/07/15  07:53:02  turner
X *
X *
X * Revision 1.1  86/06/26  15:00:15  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCDOS
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =1.43), created on $tag(
XTED_DATE DB =11/09/85) at $tag(
XTED_TIME DB =22:24:44))#
X$undefine(tag)#
X    $version
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:  Thom Henderson
X
X    Description:
X         This file contains certain DOS level routines that assist
X         in doing fancy things with an archive, primarily reading and
X         setting the date and time last modified.
X
X         These are, by nature, system dependant functions.  But they are
X         also, by nature, very expendable.
X
X    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if MSDOS
X#include "fileio2.h"                   /* needed for filehand */
X#endif
X#if BSD
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X
XINT getstamp(f,date,time)                  /* get a file's date/time stamp */
XFILE *f;                               /* file to get stamp from */
Xunsigned INT *date, *time;             /* storage for the stamp */
X{
X#if MSDOS
X    struct {INT ax,bx,cx,dx,si,di,ds,es;} reg;
X
X    reg.ax = 0x5700;                   /* get date/time */
X    reg.bx = filehand(f);              /* file handle */
X    if(sysint21(&reg,&reg)&1)          /* DOS call */
X         printf("Get timestamp fail (%d)\n",reg.ax);
X
X    *date = reg.dx;                    /* save date/time */
X    *time = reg.cx;
X#endif
X#if BSD
X    struct stat *buf;
X    int day,hr,min,sec,yr,imon;
X    static char mon[4],*mons[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
X`009`009`009`009`009"Aug","Sep","Oct","Nov","Dec"};
X
X    buf = (struct stat *)malloc(sizeof(struct stat));
X/*    fstat(f->_file,buf);  */
X    fstat(fileno(f),buf);
X/*
X * assume the UGLY ibm format for date and time
X */
X    sscanf(ctime(&(buf->st_mtime)),"%*4s%3s%d%d:%d:%d%d"
X`009,mon,&day,&hr,&min,&sec,&yr);
X    for(imon = 0; imon < 12 && strcmp(mon,mons[imon]); imon++);
X
X    *date = (unsigned INT)(((yr-1980)<<9)+((imon+1)<<5)+day);
X    *time = (unsigned INT)((hr<<11)+(min<<5)+sec/2);
X#endif
X}
X
XINT setstamp(f,date,time)                  /* set a file's date/time stamp */
XFILE *f;                               /* file to set stamp on */
Xunsigned INT date, time;               /* desired date, time */
X{
X#if MSDOS
X    struct {INT ax,bx,cx,dx,si,di,ds,es;} reg;
X
X    fflush(f);                         /* force any pending output */
X
X    reg.ax = 0x5701;                   /* set date/time */
X    reg.bx = filehand(f);              /* file handle */
X    reg.cx = time;                     /* desired time */
X    reg.dx = date;                     /* desired date */
X    if(sysint21(&reg,&reg)&1)          /* DOS call */
X         printf("Set timestamp fail (%d)\n",reg.ax);
X#endif
X}
X
Xstatic INT filehand(stream)            /* find handle on a file */
Xstruct bufstr *stream;                 /* file to grab onto */
X{
X#if MSDOS
X    return stream->bufhand;            /* return DOS 2.0 file handle */
X#endif
X}
X
XINT izadir(filename)`009`009`009/* Is filename a directory? */
Xchar *filename;
X{
X#if MSDOS
X    return 0;
X#else
Xstruct stat buf;
X
X    if (stat(filename,&buf)!=0) return 0;   /* Ignore if stat fails since we */
X    else return (buf.st_mode & S_IFDIR);    /* trap for bad file elsewhere.  */
X
X#endif
X}
X
$ GoSub Convert_File
$ Goto Part05
