Annotation of researchv10dc/lbin/kermit/ckufio.c, revision 1.1

1.1     ! root        1: char *ckzv = "Unix file support, 4E(037) 27 Jan 88";
        !             2: 
        !             3: /* C K U F I O  --  Kermit file system support for Unix systems */
        !             4: 
        !             5: /* 4E, conditionals added for Apollo Aegis. */
        !             6: 
        !             7: /*
        !             8:  Author: Frank da Cruz (SY.FDC@CU20B),
        !             9:  Columbia University Center for Computing Activities, January 1985.
        !            10:  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
        !            11:  Permission is granted to any individual or institution to use, copy, or
        !            12:  redistribute this software so long as it is not sold for profit, provided this
        !            13:  copyright notice is retained. 
        !            14: */
        !            15: /* Includes */
        !            16: 
        !            17: #include <sys/types.h>                 /* Data types */
        !            18: #include "ckcker.h"                    /* Kermit definitions */
        !            19: #include "ckcdeb.h"                    /* Typedefs, debug formats, etc */
        !            20: #include <ctype.h>                     /* Character types */
        !            21: #include <stdio.h>                     /* Standard i/o */
        !            22: #include <sys/dir.h>                   /* Directory structure */
        !            23: #include <pwd.h>                       /* Password file for shell name */
        !            24: 
        !            25: #ifdef CIE
        !            26: #include <stat.h>                      /* File status */
        !            27: #else
        !            28: #include <sys/stat.h>
        !            29: #endif
        !            30: 
        !            31: 
        !            32: /* Berkeley Unix Version 4.x */
        !            33: /* 4.1bsd support added by Charles E Brooks, EDN-VAX */
        !            34: 
        !            35: #ifdef BSD4
        !            36: #ifdef MAXNAMLEN
        !            37: #define BSD42
        !            38: char *ckzsys = " 4.2 BSD";
        !            39: #else
        !            40: #ifdef FT18
        !            41: #define BSD41
        !            42: char *ckzsys = " Fortune For:Pro 1.8";
        !            43: #else
        !            44: #define BSD41
        !            45: char *ckzsys = " 4.1 BSD";
        !            46: #endif
        !            47: #endif
        !            48: #endif
        !            49: 
        !            50: /* 2.9bsd support contributed by Bradley Smith, UCLA */
        !            51: #ifdef BSD29
        !            52: char *ckzsys = " 2.9 BSD";
        !            53: #endif
        !            54: 
        !            55: /* Version 7 Unix  */
        !            56: #ifdef V7
        !            57: char *ckzsys = " Version 7 Unix";
        !            58: #endif
        !            59: 
        !            60: /* Version 9 Unix  */
        !            61: #ifdef V9
        !            62: char *ckzsys = " Version 9 Unix";
        !            63: #endif
        !            64: 
        !            65: /* DEC Professional-300 series with Venturcom Venix v1 */
        !            66: #ifdef PROVX1
        !            67: char *ckzsys = " DEC Pro-3xx/Venix v1";
        !            68: #endif
        !            69: 
        !            70: /* NCR Tower support contributed by John Bray, Auburn, AL. */
        !            71: /* Tower OS is like Sys III but with BSD features -- mostly follows BSD. */
        !            72: #ifdef TOWER1
        !            73: char *ckzsys = " NCR Tower 1632, OS 1.02";
        !            74: #endif
        !            75: 
        !            76: /* Sys III/V, Xenix, PC/IX,... support by Herm Fischer, Litton Data Systems */
        !            77: #ifdef UXIII
        !            78: #ifdef XENIX
        !            79: char *ckzsys = " Xenix/286";
        !            80: #else
        !            81: #ifdef PCIX
        !            82: char *ckzsys = " PC/IX";
        !            83: #else
        !            84: #ifdef ISIII
        !            85: char *ckzsys = " Interactive Systems Corp, System III";
        !            86: #else
        !            87: #ifdef ZILOG
        !            88: char *ckzsys = " Zilog S8000 Zeus 3.21+";
        !            89: #else
        !            90: char *ckzsys = " AT&T System III/System V";
        !            91: #endif
        !            92: #endif
        !            93: #endif
        !            94: #endif
        !            95: #endif
        !            96: 
        !            97: /* Definitions of some Unix system commands */
        !            98: 
        !            99: char *DELCMD = "rm -f ";               /* For file deletion */
        !           100: char *PWDCMD = "pwd ";                 /* For saying where I am */
        !           101: 
        !           102: #ifdef FT18
        !           103: char *DIRCMD = "ls -l | more ";                /* For directory listing */
        !           104: char *TYPCMD = "more ";                        /* For typing a file */
        !           105: #else
        !           106: char *TYPCMD = "cat ";                 /* For typing a file */
        !           107: char *DIRCMD = "ls -l ";               /* For directory listing */
        !           108: #endif
        !           109: 
        !           110: #ifdef FT18
        !           111: #undef BSD4
        !           112: #endif
        !           113: 
        !           114: #ifdef BSD4
        !           115: char *SPACMD = "pwd ; quota ; df .";   /* Space/quota of current directory */
        !           116: #else
        !           117: #ifdef FT18
        !           118: char #SPACMD = "pwd ; du ; df .";
        !           119: #else
        !           120: char *SPACMD = "df ";
        !           121: #endif
        !           122: #endif
        !           123: 
        !           124: char *SPACM2 = "df ";                  /* For space in specified directory */
        !           125: 
        !           126: #ifdef FT18
        !           127: #define BSD4
        !           128: #endif
        !           129: 
        !           130: #ifdef BSD4
        !           131: char *WHOCMD = "finger ";              /* For seeing who's logged in */
        !           132: #else
        !           133: char *WHOCMD = "who ";                 /* For seeing who's logged in */
        !           134: #endif
        !           135: 
        !           136: /*
        !           137:   Functions (n is one of the predefined file numbers from ckermi.h):
        !           138: 
        !           139:    zopeni(n,name)   -- Opens an existing file for input.
        !           140:    zopeno(n,name)   -- Opens a new file for output.
        !           141:    zclose(n)        -- Closes a file.
        !           142:    zchin(n,&c)      -- Gets the next character from an input file.
        !           143:    zsout(n,s)       -- Write a null-terminated string to output file, buffered.
        !           144:    zsoutl(n,s)      -- Like zsout, but appends a line terminator.
        !           145:    zsoutx(n,s,x)    -- Write x characters to output file, unbuffered.
        !           146:    zchout(n,c)      -- Add a character to an output file, unbuffered.
        !           147:    zchki(name)      -- Check if named file exists and is readable, return size.
        !           148:    zchko(name)      -- Check if named file can be created.
        !           149:    znewn(name,s)    -- Make a new unique file name based on the given name.
        !           150:    zdelet(name)     -- Delete the named file.
        !           151:    zxpand(string)   -- Expands the given wildcard string into a list of files.
        !           152:    znext(string)    -- Returns the next file from the list in "string".
        !           153:    zxcmd(cmd)       -- Execute the command in a lower fork.
        !           154:    zclosf()         -- Close input file associated with zxcmd()'s lower fork.
        !           155:    zrtol(n1,n2)     -- Convert remote filename into local form.
        !           156:    zltor(n1,n2)     -- Convert local filename into remote form.
        !           157:    zchdir(dirnam)   -- Change working directory.
        !           158:    zhome()          -- Return pointer to home directory name string.
        !           159:    zkself()         -- Kill self, log out own job.
        !           160:  */
        !           161: 
        !           162: #ifdef FT18
        !           163: #define PROVX1
        !           164: #endif
        !           165: 
        !           166: /* Which systems include <sys/file.h>... */
        !           167: #ifndef PROVX1
        !           168: #ifndef aegis
        !           169: #ifndef CIE
        !           170: #ifndef XENIX
        !           171: /* Watch out, some versions of Xenix might need to do this include, */
        !           172: /* but reportedly SCO Xenix 2.2 on an 80x86 system does not. */
        !           173: #include <sys/file.h>                  /* File access */
        !           174: #endif
        !           175: #endif
        !           176: #endif
        !           177: #endif
        !           178: 
        !           179: #ifdef FT18
        !           180: #undef PROVX1
        !           181: #endif
        !           182: 
        !           183: /* Some systems define these symbols in include files, others don't... */
        !           184: #ifndef R_OK
        !           185: #define R_OK 4                         /* For access */
        !           186: #endif
        !           187: 
        !           188: #ifndef W_OK
        !           189: #define W_OK 2
        !           190: #endif
        !           191: 
        !           192: #ifdef PROVX1
        !           193: #define MAXNAMLEN DIRSIZ               /* Max file name length */
        !           194: #endif
        !           195: 
        !           196: #ifdef UXIII
        !           197: #include <fcntl.h>
        !           198: #define MAXNAMLEN DIRSIZ
        !           199: #endif
        !           200: 
        !           201: #ifndef O_RDONLY
        !           202: #define O_RDONLY 000
        !           203: #endif
        !           204: 
        !           205: #ifndef MAXNAMLEN
        !           206: #define MAXNAMLEN 14                   /* If still not defined... */
        !           207: #endif
        !           208: 
        !           209: #ifdef PROVX1
        !           210: #define MAXWLD 50                      /* Maximum wildcard filenames */
        !           211: #else
        !           212: #ifdef BSD29
        !           213: #define MAXWLD 50                      /* Maximum wildcard filenames */
        !           214: #else
        !           215: #define MAXWLD 500
        !           216: #endif
        !           217: #endif
        !           218: 
        !           219: /* Declarations */
        !           220: 
        !           221: FILE *fp[ZNFILS] = {                   /* File pointers */
        !           222:     NULL, NULL, NULL, NULL, NULL, NULL, NULL };
        !           223: 
        !           224: static int pid;                                /* pid of child fork */
        !           225: static int fcount;                     /* Number of files in wild group */
        !           226: static char nambuf[MAXNAMLEN+2];       /* Buffer for a filename */
        !           227: char *malloc(), *getenv(), *strcpy();  /* System functions */
        !           228: extern errno;                          /* System error code */
        !           229: 
        !           230: static char *mtchs[MAXWLD],            /* Matches found for filename */
        !           231:      **mtchptr;                                /* Pointer to current match */
        !           232: 
        !           233: /*  Z K S E L F  --  Kill Self: log out own job, if possible.  */
        !           234: 
        !           235: /* Note, should get current pid, but if your system doesn't have */
        !           236: /* getppid(), then just kill(0,9)...  */
        !           237: 
        !           238: zkself() {                             /* For "bye", but no guarantee! */
        !           239: #ifdef PROVX1
        !           240:     return(kill(0,9));
        !           241: #else
        !           242: #ifdef V7
        !           243:     return(kill(0,9));
        !           244: #else
        !           245: #ifdef V9
        !           246:     return(kill(0,9));
        !           247: #else
        !           248: #ifdef TOWER1
        !           249:     return(kill(0,9));
        !           250: #else
        !           251: #ifdef FT18
        !           252:     return(kill(0,9));
        !           253: #else
        !           254: #ifdef aegis
        !           255:     return(kill(0,9));
        !           256: #else
        !           257:     return(kill(getppid(),1));
        !           258: #endif
        !           259: #endif
        !           260: #endif
        !           261: #endif
        !           262: #endif
        !           263: #endif
        !           264: }
        !           265: 
        !           266: /*  Z O P E N I  --  Open an existing file for input. */
        !           267: 
        !           268: zopeni(n,name) int n; char *name; {
        !           269:     debug(F111," zopeni",name,n);
        !           270:     debug(F101,"  fp","",(int) fp[n]);
        !           271:     if (chkfn(n) != 0) return(0);
        !           272:     if (n == ZSYSFN) {                 /* Input from a system function? */
        !           273:         debug(F110," invoking zxcmd",name,0);
        !           274:        return(zxcmd(name));            /* Try to fork the command */
        !           275:     }
        !           276:     if (n == ZSTDIO) {                 /* Standard input? */
        !           277:        if (isatty(0)) {
        !           278:            ermsg("Terminal input not allowed");
        !           279:            debug(F110,"zopeni: attempts input from unredirected stdin","",0);
        !           280:            return(0);
        !           281:        }
        !           282:        fp[ZIFILE] = stdin;
        !           283:        return(1);
        !           284:     }
        !           285:     fp[n] = fopen(name,"r");           /* Real file. */
        !           286:     debug(F111," zopeni", name, (int) fp[n]);
        !           287:     if (fp[n] == NULL) perror("zopeni");
        !           288:     return((fp[n] != NULL) ? 1 : 0);
        !           289: }
        !           290: 
        !           291: /*  Z O P E N O  --  Open a new file for output.  */
        !           292: 
        !           293: zopeno(n,name) int n; char *name; {
        !           294:     debug(F111," zopeno",name,n);
        !           295:     if (chkfn(n) != 0) return(0);
        !           296:     if ((n == ZCTERM) || (n == ZSTDIO)) {   /* Terminal or standard output */
        !           297:        fp[ZOFILE] = stdout;
        !           298:        debug(F101," fp[]=stdout", "", (int) fp[n]);
        !           299:        return(1);
        !           300:     }
        !           301:     fp[n] = fopen(name,"w");           /* A real file, try to open */
        !           302:     if (fp[n] == NULL) {
        !           303:         perror("zopeno can't open");
        !           304:     } else {
        !           305:        chown(name, getuid(), getgid());     /* In case set[gu]id */
        !           306:         if (n == ZDFILE) setbuf(fp[n],NULL); /* Debugging file unbuffered */
        !           307:     }
        !           308:     debug(F101, " fp[n]", "", (int) fp[n]);
        !           309:     return((fp[n] != NULL) ? 1 : 0);
        !           310: }
        !           311: 
        !           312: /*  Z C L O S E  --  Close the given file.  */
        !           313: 
        !           314: /*  Returns 0 if arg out of range, 1 if successful, -1 if close failed.  */
        !           315: 
        !           316: zclose(n) int n; {
        !           317:     int x;
        !           318:     if (chkfn(n) < 1) return(0);       /* Check range of n */
        !           319:     if ((n == ZIFILE) && fp[ZSYSFN]) { /* If system function */
        !           320:        x = zclosf();                   /* do it specially */
        !           321:     } else {
        !           322:        if ((fp[n] != stdout) && (fp[n] != stdin)) x = fclose(fp[n]);
        !           323:        fp[n] = NULL;
        !           324:     }
        !           325:     return((x == EOF) ? -1 : 1);
        !           326: }
        !           327: 
        !           328: /*  Z C H I N  --  Get a character from the input file.  */
        !           329: 
        !           330: /*  Returns -1 if EOF, 0 otherwise with character returned in argument  */
        !           331: 
        !           332: zchin(n,c) int n; char *c; {
        !           333:     int a;
        !           334:     if (chkfn(n) < 1) return(-1);
        !           335:     a = getc(fp[n]);
        !           336:     if (a == EOF) return(-1);
        !           337:     *c = a & 0377;
        !           338:     return(0);
        !           339: }
        !           340: 
        !           341: /*  Z S O U T  --  Write a string to the given file, buffered.  */
        !           342: 
        !           343: zsout(n,s) int n; char *s; {
        !           344:     if (chkfn(n) < 1) return(-1);
        !           345:     fputs(s,fp[n]);
        !           346:     return(0);
        !           347: }
        !           348: 
        !           349: /*  Z S O U T L  --  Write string to file, with line terminator, buffered  */
        !           350: 
        !           351: zsoutl(n,s) int n; char *s; {
        !           352:     if (chkfn(n) < 1) return(-1);
        !           353:     fputs(s,fp[n]);
        !           354:     fputs("\n",fp[n]);
        !           355:     return(0);
        !           356: }
        !           357: 
        !           358: /*  Z S O U T X  --  Write x characters to file, unbuffered.  */
        !           359: 
        !           360: zsoutx(n,s,x) int n, x; char *s; {
        !           361:     if (chkfn(n) < 1) return(-1);
        !           362: /*  return(write(fp[n]->_file,s,x));  */
        !           363:     return(write(fileno(fp[n]),s,x));
        !           364: }
        !           365: 
        !           366: 
        !           367: /*  Z C H O U T  --  Add a character to the given file.  */
        !           368: 
        !           369: /*  Should return 0 or greater on success, -1 on failure (e.g. disk full)  */
        !           370: 
        !           371: zchout(n,c) int n; char c; {
        !           372:     if (chkfn(n) < 1) return(-1);
        !           373:     if (n == ZSFILE)
        !           374:        return(write(fileno(fp[n]),&c,1)); /* Use unbuffered for session log */
        !           375:     else {                             /* Buffered for everything else */
        !           376:        if (putc(c,fp[n]) == EOF)       /* If true, maybe there was an error */
        !           377:            return(ferror(fp[n])?-1:0); /* Check to make sure */
        !           378:        else                            /* Otherwise... */
        !           379:            return(0);                  /* There was no error. */
        !           380:     }
        !           381: }
        !           382: 
        !           383: /*  C H K F N  --  Internal function to verify file number is ok  */
        !           384: 
        !           385: /*
        !           386:  Returns:
        !           387:   -1: File number n is out of range
        !           388:    0: n is in range, but file is not open
        !           389:    1: n in range and file is open
        !           390: */
        !           391: chkfn(n) int n; {
        !           392:     switch (n) {
        !           393:        case ZCTERM:
        !           394:        case ZSTDIO:
        !           395:        case ZIFILE:
        !           396:        case ZOFILE:
        !           397:        case ZDFILE:
        !           398:        case ZTFILE:
        !           399:        case ZPFILE:
        !           400:        case ZSFILE:
        !           401:        case ZSYSFN: break;
        !           402:        default:
        !           403:            debug(F101,"chkfn: file number out of range","",n);
        !           404:            fprintf(stderr,"?File number out of range - %d\n",n);
        !           405:            return(-1);
        !           406:     }
        !           407:     return( (fp[n] == NULL) ? 0 : 1 );
        !           408: }
        !           409: 
        !           410: /*  Z C H K I  --  Check if input file exists and is readable  */
        !           411: 
        !           412: /*
        !           413:   Returns:
        !           414:    >= 0 if the file can be read (returns the size).
        !           415:      -1 if file doesn't exist or can't be accessed,
        !           416:      -2 if file exists but is not readable (e.g. a directory file).
        !           417:      -3 if file exists but protected against read access.
        !           418: */
        !           419: /*
        !           420:  For Berkeley Unix, a file must be of type "regular" to be readable.
        !           421:  Directory files, special files, and symbolic links are not readable.
        !           422: */
        !           423: long
        !           424: zchki(name) char *name; {
        !           425:     struct stat buf;
        !           426:     int x; long y; 
        !           427: 
        !           428:     x = stat(name,&buf);
        !           429:     if (x < 0) {
        !           430:        debug(F111,"zchki stat fails",name,errno);
        !           431:        return(-1);
        !           432:     }
        !           433:     x = buf.st_mode & S_IFMT;          /* Isolate file format field */
        !           434:     if ((x != 0) && (x != S_IFREG)) {
        !           435:        debug(F111,"zchki skipping:",name,x);
        !           436:        return(-2);
        !           437:     }
        !           438:     debug(F111,"zchki stat ok:",name,x);
        !           439: 
        !           440:     if ((x = access(name,R_OK)) < 0) {         /* Is the file accessible? */
        !           441:        debug(F111," access failed:",name,x); /* No */
        !           442:        return(-3);                     
        !           443:     } else {
        !           444:        y = buf.st_size;
        !           445:        debug(F111," access ok:",name,(int) y); /* Yes */
        !           446:        return( (y > -1) ? y : 0 );
        !           447:     }
        !           448: }
        !           449: 
        !           450: /*  Z C H K O  --  Check if output file can be created  */
        !           451: 
        !           452: /*
        !           453:  Returns -1 if write permission for the file would be denied, 0 otherwise.
        !           454: */
        !           455: zchko(name) char *name; {
        !           456:     int i, x;
        !           457:     char s[50], *sp;   
        !           458: 
        !           459:     sp = s;                            /* Make a copy, get length */
        !           460:     x = 0;
        !           461:     while ((*sp++ = *name++) != '\0')
        !           462:        x++;
        !           463:     if (x == 0) return(-1);            /* If no filename, fail. */
        !           464: 
        !           465:     debug(F101," length","",x);
        !           466:     for (i = x; i > 0; i--)            /* Strip filename. */
        !           467:        if (s[i-1] == '/') break;
        !           468:     
        !           469:     debug(F101," i","",i);
        !           470:     if (i == 0)                                /* If no path, use current directory */
        !           471:        strcpy(s,"./");                 
        !           472:     else                               /* Otherwise, use given one. */
        !           473:         s[i] = '\0';
        !           474: 
        !           475:     x = access(s,W_OK);                        /* Check access of path. */
        !           476:     if (x < 0) {
        !           477:        debug(F111,"zchko access failed:",s,errno);
        !           478:        return(-1);
        !           479:     } else {
        !           480:        debug(F111,"zchko access ok:",s,x);
        !           481:        return(0);
        !           482:     }
        !           483: }
        !           484: 
        !           485: /*  Z D E L E T  --  Delete the named file.  */
        !           486: 
        !           487: zdelet(name) char *name; {
        !           488:     unlink(name);
        !           489: }
        !           490: 
        !           491: 
        !           492: /*  Z R T O L  --  Convert remote filename into local form  */
        !           493: 
        !           494: /*  For UNIX, this means changing uppercase letters to lowercase.  */
        !           495: 
        !           496: zrtol(name,name2) char *name, *name2; {
        !           497:     for ( ; *name != '\0'; name++) {
        !           498:        *name2++ = isupper(*name) ? tolower(*name) : *name;
        !           499:     }
        !           500:     *name2 = '\0';
        !           501:     debug(F110,"zrtol:",name2,0);
        !           502: }
        !           503: 
        !           504: 
        !           505: /*  Z L T O R  --  Local TO Remote */
        !           506: 
        !           507: /*  Convert filename from local format to common (remote) form.  */
        !           508: 
        !           509: zltor(name,name2) char *name, *name2; {
        !           510:     char work[100], *cp, *pp;
        !           511:     int dc = 0;
        !           512: #ifdef aegis
        !           513:     char *getenv(), *index(), *namechars;
        !           514:     int tilde = 0, bslash = 0;
        !           515: 
        !           516:     if ((namechars = getenv("NAMECHARS")) != NULL) {
        !           517:        if (index(namechars, '~' ) != NULL) tilde  = '~';
        !           518:        if (index(namechars, '\\') != NULL) bslash = '\\';
        !           519:     } else {
        !           520:         tilde = '~';
        !           521:         bslash = '\\';
        !           522:     }
        !           523: #endif
        !           524: 
        !           525:     debug(F110,"zltor",name,0);
        !           526:     pp = work;
        !           527: #ifdef aegis
        !           528:     cp = name;
        !           529:     if (tilde && *cp == tilde)
        !           530:        ++cp;
        !           531:     for (; *cp != '\0'; cp++) {        /* strip path name */
        !           532:        if (*cp == '/' || *cp == bslash) {
        !           533: #else
        !           534:     for (cp = name; *cp != '\0'; cp++) {       /* strip path name */
        !           535:        if (*cp == '/') {
        !           536: #endif
        !           537:            dc = 0;
        !           538:            pp = work;
        !           539:        }
        !           540:        else if (islower(*cp)) *pp++ = toupper(*cp); /* Uppercase letters */
        !           541:        else if (*cp == '~') *pp++ = 'X';       /* Change tilde to 'X' */
        !           542:        else if (*cp == '#') *pp++ = 'X';       /* Change number sign to 'X' */
        !           543:        else if ((*cp == '.') && (++dc > 1)) *pp++ = 'X'; /* & extra dots */
        !           544:        else *pp++ = *cp;
        !           545:     }
        !           546:     *pp = '\0';                                /* Tie it off. */
        !           547:     cp = name2;                                /* If nothing before dot, */
        !           548:     if (*work == '.') *cp++ = 'X';     /* insert 'X' */
        !           549:     strcpy(cp,work);
        !           550:     debug(F110," name2",name2,0);
        !           551: }    
        !           552: 
        !           553: 
        !           554: /*  Z C H D I R  --  Change directory  */
        !           555: 
        !           556: zchdir(dirnam) char *dirnam; {
        !           557:     char *hd;
        !           558:     if (*dirnam == '\0') hd = getenv("HOME");
        !           559:     else hd = dirnam;
        !           560:     return((chdir(hd) == 0) ? 1 : 0);
        !           561: }
        !           562: 
        !           563: 
        !           564: /*  Z H O M E  --  Return pointer to user's home directory  */
        !           565: 
        !           566: char *
        !           567: zhome() {
        !           568:     return(getenv("HOME"));
        !           569: }
        !           570: 
        !           571: /*  Z G T D I R  --  Return pointer to user's current directory  */
        !           572: 
        !           573: char *
        !           574: zgtdir() {
        !           575: 
        !           576: #ifdef MAXPATHLEN
        !           577: #define CWDBL MAXPATHLEN
        !           578: #else
        !           579: #define CWDBL 100
        !           580: #endif
        !           581: 
        !           582: #ifdef UXIII
        !           583:     char cwdbuf[CWDBL+1];
        !           584:     char *buf;
        !           585:     char *getcwd();
        !           586:     buf = cwdbuf;
        !           587:     return(getcwd(buf,CWDBL));
        !           588: #else
        !           589: #ifdef BSD4
        !           590:     char cwdbuf[CWDBL+1];
        !           591:     char *buf;
        !           592:     char *getwd();
        !           593:     buf = cwdbuf;
        !           594:     return(getwd(buf));
        !           595: #else
        !           596:     return("(directory unknown)");
        !           597: #endif
        !           598: #endif
        !           599: }
        !           600: 
        !           601: /*  Z X C M D -- Run a system command so its output can be read like a file */
        !           602: 
        !           603: zxcmd(comand) char *comand; {
        !           604:     int pipes[2];
        !           605:     if (pipe(pipes) != 0) {
        !           606:        debug(F100,"zxcmd pipe failure","",0);
        !           607:        return(0);                      /* can't make pipe, fail */
        !           608:     }
        !           609: #ifdef aegis
        !           610:     if ((pid = vfork()) == 0) {                /* child */
        !           611: #else
        !           612:     if ((pid = fork()) == 0) {         /* child */
        !           613: #endif
        !           614: 
        !           615: 
        !           616: /*#if BSD4*/           /* Code from Dave Tweten@AMES-NAS */
        !           617:                        /* readapted to use getpwuid to find login shell */
        !           618:                        /*   -- H. Fischer */
        !           619:        char *shpath, *shname, *shptr;  /* to find desired shell */
        !           620: #ifndef aegis
        !           621:        struct passwd *p;
        !           622:        extern struct passwd * getpwuid();
        !           623:        extern int getuid();
        !           624:        char *defShel = "/bin/sh";      /* default shell */
        !           625: #endif
        !           626: 
        !           627:        close(pipes[0]);                /* close input side of pipe */
        !           628:        close(0);                       /* close stdin */
        !           629:        if (open("/dev/null",0) < 0) return(0); /* replace input by null */
        !           630: 
        !           631: #ifndef UXIII
        !           632:        dup2(pipes[1],1);               /* replace stdout & stderr */
        !           633:        dup2(pipes[1],2);               /* by the pipe */
        !           634: #else
        !           635:        close(1);                       /* simulate dup2 */
        !           636:        if (dup(pipes[1]) != 1 )
        !           637:            conol("trouble duping stdout in routine zxcmd\n");
        !           638:        close(2);                       /* simulate dup2 */
        !           639:        if (dup(pipes[1]) != 2 )
        !           640:            conol("trouble duping stderr in routine zxcmd\n");
        !           641: #endif
        !           642: 
        !           643:        close(pipes[1]);                /* get rid of this copy of the pipe */
        !           644: 
        !           645: #ifdef aegis
        !           646:        if ((shpath = getenv("SERVERSHELL")) == NULL) shpath = "/bin/sh";
        !           647: #else
        !           648: 
        !           649: /****  shptr = shname = shpath = getenv("SHELL");  /* What shell? */
        !           650:        p = getpwuid( getuid() );       /* get login data */
        !           651:        if ( p == (struct passwd *) NULL || !*(p->pw_shell) ) shpath = defShel;
        !           652:          else shpath = p->pw_shell;
        !           653: #endif
        !           654:        shptr = shname = shpath;
        !           655:        while (*shptr != '\0') if (*shptr++ == '/') shname = shptr;
        !           656:        debug(F100,"zxcmd...","",0);
        !           657:        debug(F110,shpath,shname,0);
        !           658: 
        !           659: /* Remove the following uid calls if they cause trouble... */
        !           660: #ifdef BSD4
        !           661:        setegid(getgid());              /* Override 4.3BSD csh */
        !           662:        seteuid(getuid());              /*  security checks */
        !           663: #endif /* bsd4 */
        !           664: 
        !           665:        execl(shpath,shname,"-c",comand,(char *)NULL); /* Execute the cmd */
        !           666:        exit(0);                        /* just punt if it failed. */
        !           667:     } else if (pid == -1) {
        !           668:        debug(F100,"zxcmd fork failure","",0);
        !           669:        return(0);
        !           670:     }
        !           671:     close(pipes[1]);                   /* don't need the output side */
        !           672:     fp[ZIFILE] = fdopen(pipes[0],"r"); /* open a stream for it */
        !           673:     fp[ZSYSFN] = fp[ZIFILE];           /* Remember. */
        !           674:     return(1);
        !           675: }
        !           676: 
        !           677: /*  Z C L O S F  - wait for the child fork to terminate and close the pipe. */
        !           678: 
        !           679: zclosf() {
        !           680:     int wstat;
        !           681:     if (kill(pid,9) == 0) {
        !           682:        debug(F101,"zclosf pid =","",pid);
        !           683:         while ((wstat = wait((int *)0)) != pid && wstat != -1) ;
        !           684:         pid = 0;
        !           685:     }
        !           686:     fclose(fp[ZIFILE]);
        !           687:     fp[ZIFILE] = fp[ZSYSFN] = NULL;
        !           688:     return(1);
        !           689: }
        !           690: 
        !           691: /*  Z X P A N D  --  Expand a wildcard string into an array of strings  */
        !           692: /*
        !           693:   Returns the number of files that match fn1, with data structures set up
        !           694:   so that first file (if any) will be returned by the next znext() call.
        !           695: */
        !           696: zxpand(fn) char *fn; {
        !           697:     fcount = fgen(fn,mtchs,MAXWLD);    /* Look up the file. */
        !           698:     if (fcount > 0) {
        !           699:        mtchptr = mtchs;                /* Save pointer for next. */
        !           700:     }
        !           701:     debug(F111,"zxpand",mtchs[0],fcount);
        !           702:     return(fcount);
        !           703: }
        !           704: 
        !           705: 
        !           706: /*  Z N E X T  --  Get name of next file from list created by zxpand(). */
        !           707: /*
        !           708:  Returns >0 if there's another file, with its name copied into the arg string,
        !           709:  or 0 if no more files in list.
        !           710: */
        !           711: znext(fn) char *fn; {
        !           712:     if (fcount-- > 0) strcpy(fn,*mtchptr++);
        !           713:     else *fn = '\0';
        !           714:     debug(F111,"znext",fn,fcount+1);
        !           715:     return(fcount+1);
        !           716: }
        !           717: 
        !           718: 
        !           719: /*  Z N E W N  --  Make a new name for the given file  */
        !           720: 
        !           721: znewn(fn,s) char *fn, **s; {
        !           722: #ifdef BSD4
        !           723:     static char buf[256];
        !           724: #else
        !           725:     static char buf[100];
        !           726: #endif
        !           727:     char *bp, *xp;
        !           728:     int len = 0, n = 0, d = 0, t, i, power = 1;
        !           729: #ifdef MAXNAMLEN
        !           730:     int max = MAXNAMLEN;
        !           731: #else
        !           732:     int max = 14;
        !           733: #endif
        !           734:     bp = buf;
        !           735:     while (*fn) {                      /* Copy name into buf */
        !           736:        *bp++ = *fn++;
        !           737:        len++;
        !           738:     }
        !           739:     if (len > max-2) {                         /* Don't let it get too long */
        !           740:        bp = buf + max-2;
        !           741:        len = max - 2;
        !           742:     }
        !           743:        
        !           744:     for (i = 1; i < 4; i++) {          /* Try up to 999 times */
        !           745:        power *= 10;
        !           746:        *bp++ = '*';                    /* Put a star on the end */
        !           747:        *bp-- = '\0';
        !           748:        
        !           749:        n = zxpand(buf);                /* Expand the resulting wild name */
        !           750:     
        !           751:        while (n-- > 0) {               /* Find any existing name~d files */
        !           752:            xp = *mtchptr++;
        !           753:            xp += len;
        !           754:            if (*xp == '~') {
        !           755:                t = atoi(xp+1);
        !           756:                if (t > d) d = t;       /* Get maximum d */
        !           757:            }
        !           758:        }
        !           759:        if (d < power-1) {
        !           760:            sprintf(bp,"~%d",d+1);      /* Make name~(d+1) */
        !           761:            *s = buf;
        !           762:            return;
        !           763:        }
        !           764:        bp--; len--;
        !           765:     }
        !           766: /* If we ever get here, we'll overwrite the xxx~100 file... */
        !           767: }
        !           768: 
        !           769: /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */
        !           770: 
        !           771: /*
        !           772:  * The path structure is used to represent the name to match.
        !           773:  * Each slash-separated segment of the name is kept in one
        !           774:  * such structure, and they are linked together, to make
        !           775:  * traversing the name easier.
        !           776:  */
        !           777: 
        !           778: struct path {
        !           779:               char npart[MAXNAMLEN];   /* name part of path segment */
        !           780:               struct path *fwd;                /* forward ptr */
        !           781:             };
        !           782: 
        !           783: #ifdef PROVX1
        !           784: #define SSPACE 500
        !           785: #else
        !           786: #ifdef BSD29
        !           787: #define SSPACE 500
        !           788: #else
        !           789: #ifdef aegis
        !           790: #define SSPACE 10000                   /* size of string-generating buffer */
        !           791: static char bslash;                    /* backslash character if active */
        !           792: #else
        !           793: #define SSPACE 2000                    /* size of string-generating buffer */
        !           794: #endif
        !           795: #endif
        !           796: #endif
        !           797: static char sspace[SSPACE];             /* buffer to generate names in */
        !           798: static char *freeptr,**resptr;                 /* copies of caller's arguments */
        !           799: static int remlen;                      /* remaining length in caller's array*/
        !           800: static int numfnd;                      /* number of matches found */
        !           801: 
        !           802: /*
        !           803:  * splitpath:
        !           804:  *  takes a string and splits the slash-separated portions into
        !           805:  *  a list of path structures.  Returns the head of the list.  The
        !           806:  *  structures are allocated by malloc, so they must be freed.
        !           807:  *  Splitpath is used internally by the filename generator.
        !           808:  *
        !           809:  * Input: A string.
        !           810:  * Returns: A linked list of the slash-separated segments of the input.
        !           811:  */
        !           812: 
        !           813: struct path *
        !           814: splitpath(p)
        !           815: char *p;
        !           816: {
        !           817:  struct path *head,*cur,*prv;
        !           818:  int i;
        !           819:  head = prv = NULL;
        !           820:  if (*p == '/') p++;            /* skip leading slash */
        !           821:  while (*p != '\0')
        !           822:  {
        !           823:    cur = (struct path *) malloc(sizeof (struct path));
        !           824:    debug(F101,"splitpath malloc","",cur);
        !           825:    if (cur == NULL) fatal("malloc fails in splitpath()");
        !           826:    cur -> fwd = NULL;
        !           827:    if (head == NULL) head = cur;
        !           828:    else prv -> fwd = cur;       /* link into chain */
        !           829:    prv = cur;
        !           830: #ifdef aegis
        !           831:    /* treat backslash as "../" */
        !           832:    if (bslash && *p == bslash) {
        !           833:      strcpy(cur->npart, "..");
        !           834:      ++p;
        !           835:    } else {
        !           836:      for (i=0; i < MAXNAMLEN && *p && *p != '/' && *p != bslash; i++)
        !           837:        cur -> npart[i] = *p++;
        !           838:      cur -> npart[i] = '\0';      /* end this segment */
        !           839:      if (i >= MAXNAMLEN) while (*p && *p != '/' && *p != bslash) p++;
        !           840:    }
        !           841:    if (*p == '/') p++;
        !           842: #else
        !           843:    for (i=0; i < MAXNAMLEN && *p != '/' && *p != '\0'; i++)
        !           844:      cur -> npart[i] = *p++;
        !           845:    cur -> npart[i] = '\0';      /* end this segment */
        !           846:    if (i >= MAXNAMLEN) while (*p != '/' && *p != '\0') p++;
        !           847:    if (*p == '/') p++;
        !           848: #endif
        !           849:  }
        !           850:  return(head);
        !           851: }
        !           852: 
        !           853: /*
        !           854:  * fgen:
        !           855:  *  This is the actual name generator.  It is passed a string,
        !           856:  *  possibly containing wildcards, and an array of character pointers.
        !           857:  *  It finds all the matching filenames and stores them into the array.
        !           858:  *  The returned strings are allocated from a static buffer local to
        !           859:  *  this module (so the caller doesn't have to worry about deallocating
        !           860:  *  them); this means that successive calls to fgen will wipe out
        !           861:  *  the results of previous calls.  This isn't a problem here
        !           862:  *  because we process one wildcard string at a time.
        !           863:  *
        !           864:  * Input: a wildcard string, an array to write names to, the
        !           865:  *        length of the array.
        !           866:  * Returns: the number of matches.  The array is filled with filenames
        !           867:  *          that matched the pattern.  If there wasn't enough room in the
        !           868:  *         array, -1 is returned.
        !           869:  * By: Jeff Damens, CUCCA, 1984.
        !           870:  */
        !           871: 
        !           872: fgen(pat,resarry,len)
        !           873: char *pat,*resarry[];
        !           874: int len;
        !           875: {
        !           876:  struct path *head;
        !           877:  char scratch[100],*sptr;
        !           878: #ifdef aegis
        !           879:  char *getenv(), *index(), *namechars;
        !           880:  int tilde = 0, bquote = 0;
        !           881: 
        !           882:  if ((namechars = getenv("NAMECHARS")) != NULL) {
        !           883:   if (index(namechars, '~' ) != NULL) tilde  = '~';
        !           884:   if (index(namechars, '\\') != NULL) bslash = '\\';
        !           885:   if (index(namechars, '`' ) != NULL) bquote = '`';
        !           886:  }
        !           887:  else { tilde = '~'; bslash = '\\'; bquote = '`'; }
        !           888: 
        !           889:  sptr = scratch;
        !           890:  /* copy "`node_data", etc. anchors */
        !           891:  if (bquote && *pat == bquote)
        !           892:   while (*pat && *pat != '/' && *pat != bslash)
        !           893:    *sptr++ = *pat++;
        !           894:  else if (tilde && *pat == tilde)
        !           895:   *sptr++ = *pat++;
        !           896:  while (*pat == '/')
        !           897:   *sptr++ = *pat++;
        !           898:  if (sptr == scratch)
        !           899:  {
        !           900:   strcpy(scratch,"./");
        !           901:   sptr = scratch+2;
        !           902:  }                                     /* init buffer correctly */
        !           903:  head = splitpath(pat);
        !           904: #else
        !           905:  head = splitpath(pat);
        !           906:  if (*pat == '/')
        !           907:  {
        !           908:   scratch[0] = '/';
        !           909:   sptr = scratch+1;
        !           910:  }
        !           911:  else
        !           912:  {
        !           913:   strcpy(scratch,"./");
        !           914:   sptr = scratch+2;
        !           915:  }                                     /* init buffer correctly */
        !           916: #endif
        !           917:  numfnd = 0;                            /* none found yet */
        !           918:  freeptr = sspace;                     /* this is where matches are copied */
        !           919:  resptr = resarry;                     /* static copies of these so*/
        !           920:  remlen = len;                         /* recursive calls can alter them */
        !           921:  traverse(head,scratch,sptr);          /* go walk the directory tree */
        !           922:  for (; head != NULL; head = head -> fwd)
        !           923:    free(head);                         /* return the path segments */
        !           924:  return(numfnd);                       /* and return the number of matches */
        !           925: }
        !           926: 
        !           927: /* traverse:
        !           928:  *  Walks the directory tree looking for matches to its arguments.
        !           929:  *  The algorithm is, briefly:
        !           930:  *   If the current pattern segment contains no wildcards, that
        !           931:  *   segment is added to what we already have.  If the name so far
        !           932:  *   exists, we call ourselves recursively with the next segment
        !           933:  *   in the pattern string; otherwise, we just return.
        !           934:  *
        !           935:  *   If the current pattern segment contains wildcards, we open the name
        !           936:  *   we've accumulated so far (assuming it is really a directory), then read
        !           937:  *   each filename in it, and, if it matches the wildcard pattern segment, add
        !           938:  *   that filename to what we have so far and call ourselves recursively on the
        !           939:  *   next segment.
        !           940:  *
        !           941:  *   Finally, when no more pattern segments remain, we add what's accumulated
        !           942:  *   so far to the result array and increment the number of matches.
        !           943:  *
        !           944:  * Input: a pattern path list (as generated by splitpath), a string
        !           945:  *       pointer that points to what we've traversed so far (this
        !           946:  *       can be initialized to "/" to start the search at the root
        !           947:  *       directory, or to "./" to start the search at the current
        !           948:  *       directory), and a string pointer to the end of the string
        !           949:  *       in the previous argument.
        !           950:  * Returns: nothing.
        !           951:  */
        !           952: traverse(pl,sofar,endcur)
        !           953: struct path *pl;
        !           954: char *sofar,*endcur;
        !           955: {
        !           956: #ifdef BSD42
        !           957:  DIR *fd, *opendir();
        !           958:  struct direct *dirbuf;
        !           959: #else
        !           960: #ifdef BSD29
        !           961:  DIR *fd, *opendir();
        !           962:  struct direct *dirbuf;
        !           963: #else
        !           964:  int fd;
        !           965:  struct direct dir_entry;
        !           966:  struct direct *dirbuf = &dir_entry;
        !           967: #endif
        !           968: #endif
        !           969:  struct stat statbuf;
        !           970:  if (pl == NULL)
        !           971:  {
        !           972:   *--endcur = '\0';                    /* end string, overwrite trailing / */
        !           973:   addresult(sofar);
        !           974:   return;
        !           975:  }
        !           976:  if (!iswild(pl -> npart))
        !           977:  {
        !           978:   strcpy(endcur,pl -> npart);
        !           979:   endcur += strlen(pl -> npart);
        !           980:   *endcur = '\0';                      /* end current string */
        !           981:   if (stat(sofar,&statbuf) == 0)       /* if current piece exists */
        !           982:   {
        !           983:       *endcur++ = '/';                  /* add slash to end */
        !           984:       *endcur = '\0';                  /* and end the string */
        !           985:       traverse(pl -> fwd,sofar,endcur);
        !           986:   }
        !           987:   return;
        !           988:  }
        !           989: /* cont'd... */
        !           990: 
        !           991: /*...traverse, cont'd */
        !           992: 
        !           993: /* segment contains wildcards, have to search directory */
        !           994:  *endcur = '\0';                               /* end current string */
        !           995:  if (stat(sofar,&statbuf) == -1) return;       /* doesn't exist, forget it */
        !           996:  if ((statbuf.st_mode & S_IFDIR) == 0) return;  /* not a directory, skip */
        !           997: #ifdef BSD42                   /* ==BSD4 */
        !           998:  if ((fd = opendir(sofar)) == NULL) return;    /* can't open, forget it */
        !           999:  while (dirbuf = readdir(fd))
        !          1000: #else
        !          1001: #ifdef BSD29                   /* ==BSD29 */
        !          1002:  if ((fd = opendir(sofar)) == NULL) return;    /* can't open, forget it */
        !          1003:  while (dirbuf = readdir(fd))
        !          1004: #else
        !          1005: 
        !          1006:  if ((fd = open(sofar,O_RDONLY)) < 0) return;          /* can't open, forget it */
        !          1007:  while ( read(fd,dirbuf,sizeof dir_entry) )
        !          1008: #endif
        !          1009: #endif
        !          1010: {
        !          1011:   strncpy(nambuf,dirbuf->d_name,MAXNAMLEN); /* Get a null terminated copy!!! */
        !          1012:   nambuf[MAXNAMLEN] = '\0';
        !          1013:   if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) {
        !          1014:     char *eos;
        !          1015:     strcpy(endcur,nambuf);
        !          1016:     eos = endcur + strlen(nambuf);
        !          1017:     *eos = '/';                    /* end this segment */
        !          1018:     traverse(pl -> fwd,sofar,eos+1);
        !          1019:   }
        !          1020: }
        !          1021: #ifdef BSD42                   /* ==BSD4 */
        !          1022:  closedir(fd);
        !          1023: #else
        !          1024: #ifdef BSD29
        !          1025:  closedir(fd);
        !          1026: #else
        !          1027:  close(fd);
        !          1028: #endif
        !          1029: #endif
        !          1030: }
        !          1031: 
        !          1032: /*
        !          1033:  * addresult:
        !          1034:  *  Adds a result string to the result array.  Increments the number
        !          1035:  *  of matches found, copies the found string into our string
        !          1036:  *  buffer, and puts a pointer to the buffer into the caller's result
        !          1037:  *  array.  Our free buffer pointer is updated.  If there is no
        !          1038:  *  more room in the caller's array, the number of matches is set to -1.
        !          1039:  * Input: a result string.
        !          1040:  * Returns: nothing.
        !          1041:  */
        !          1042: 
        !          1043: addresult(str)
        !          1044: char *str;
        !          1045: {
        !          1046:  int l;
        !          1047:  if (strncmp(str,"./",2) == 0) str += 2;
        !          1048:  if (--remlen < 0) {
        !          1049:   numfnd = -1;
        !          1050:   return;
        !          1051:  }
        !          1052:  l = strlen(str) + 1;                  /* size this will take up */
        !          1053:  if ((freeptr + l) > &sspace[SSPACE-1]) {
        !          1054:     numfnd = -1;                       /* do not record if not enough space */
        !          1055:     return;
        !          1056:   }
        !          1057:  strcpy(freeptr,str);
        !          1058:  *resptr++ = freeptr;
        !          1059:  freeptr += l;
        !          1060:  numfnd++;
        !          1061: }
        !          1062: 
        !          1063: iswild(str)
        !          1064: char *str;
        !          1065: {
        !          1066:  char c;
        !          1067:  while ((c = *str++) != '\0')
        !          1068:    if (c == '*' || c == '?') return(1);
        !          1069:  return(0);
        !          1070: }
        !          1071: 
        !          1072: /*
        !          1073:  * match:
        !          1074:  *  pattern matcher.  Takes a string and a pattern possibly containing
        !          1075:  *  the wildcard characters '*' and '?'.  Returns true if the pattern
        !          1076:  *  matches the string, false otherwise.
        !          1077:  * by: Jeff Damens, CUCCA
        !          1078:  *
        !          1079:  * Input: a string and a wildcard pattern.
        !          1080:  * Returns: 1 if match, 0 if no match.
        !          1081:  */
        !          1082: 
        !          1083: match(pattern,string) char *pattern,*string; {
        !          1084:     char *psave,*ssave;                        /* back up pointers for failure */
        !          1085:     psave = ssave = NULL;
        !          1086:     while (1) {
        !          1087:        for (; *pattern == *string; pattern++,string++)  /* skip first */
        !          1088:            if (*string == '\0') return(1);     /* end of strings, succeed */
        !          1089:        if (*string != '\0' && *pattern == '?') {
        !          1090:            pattern++;                  /* '?', let it match */
        !          1091:            string++;
        !          1092:        } else if (*pattern == '*') {   /* '*' ... */
        !          1093:            psave = ++pattern;          /* remember where we saw it */
        !          1094:            ssave = string;             /* let it match 0 chars */
        !          1095:        } else if (ssave != NULL && *ssave != '\0') {   /* if not at end  */
        !          1096:                                        /* ...have seen a star */
        !          1097:            string = ++ssave;           /* skip 1 char from string */
        !          1098:            pattern = psave;            /* and back up pattern */
        !          1099:        } else return(0);               /* otherwise just fail */
        !          1100:     }
        !          1101: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.