Annotation of researchv10dc/lbin/kermit/ckufio.c, revision 1.1.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.