Annotation of researchv10no/cmd/odist/opkg/inspkg.c, revision 1.1.1.1

1.1       root        1: #include "asd.h"
                      2: #include <libv.h>
                      3: #include <string.h>
                      4: #include <sys/types.h>
                      5: #include <sys/wait.h>
                      6: #include <unistd.h>
                      7: #include <utime.h>
                      8: 
                      9: #define CHUNK 64
                     10: 
                     11: /* type codes for installation subroutine */
                     12: #define BACKUP 0
                     13: #define INSTALL 1
                     14: 
                     15: static void readtemp(int, FILE *);
                     16: 
                     17: /*
                     18:  *     The following declarations and functions manipulate
                     19:  *     a list of directory names.  This list is used to decide
                     20:  *     which files should be backed up and which have already been.
                     21:  */
                     22: 
                     23: struct list {
                     24:        char *name;
                     25:        struct list *next;
                     26: };
                     27: 
                     28: static struct list *dirs;
                     29: 
                     30: /* is the name given a subdirectory of the name on the list? */
                     31: static int
                     32: subsumed (char *name)
                     33: {
                     34:        register struct list *item;
                     35:        register char *p, *q;
                     36: 
                     37:        for (item = dirs; item; item = item->next) {
                     38:                p = item->name;
                     39:                q = name;
                     40:                while (*p && *p == *q)
                     41:                        p++, q++;
                     42:                if (*p == '\0' && (*q == '/' || *q == '\0'))
                     43:                        return 1;
                     44:        }
                     45: 
                     46:        return 0;
                     47: }
                     48: 
                     49: /* add the name given to the list */
                     50: static void
                     51: addlist (char *name)
                     52: {
                     53:        register struct list *l;
                     54: 
                     55:        l = new (struct list);
                     56:        l->next = dirs;
                     57:        l->name = copy (name);
                     58:        dirs = l;
                     59: }
                     60: 
                     61: /* clear the entire list */
                     62: static void
                     63: clearlist(void)
                     64: {
                     65:        register struct list *l;
                     66: 
                     67:        while (l = dirs) {
                     68:                dirs = l->next;
                     69:                free (l->name);
                     70:                free ((char *) l);
                     71:        }
                     72: }
                     73: 
                     74: static char tfname[L_tmpnam];
                     75: static void delete(int);
                     76: 
                     77: /* process a single archive in a concatenation */
                     78: static int
                     79: doarch (FILE *file)
                     80: {
                     81:        register FILE *tf;
                     82:        Sig_typ sigsav;
                     83:        register long size;
                     84:        register int c;
                     85:        char armag[SARMAG];
                     86: 
                     87:        /* Make sure the file is an archive */
                     88:        if (fread (armag, sizeof (*armag), SARMAG, file) != SARMAG) {
                     89:                fprintf (stderr, "inspkg: unexpected EOF\n");
                     90:                exit (1);
                     91:        }
                     92:        if (strncmp (armag, ARMAG, SARMAG) != 0) {
                     93:                fprintf (stderr, "inspkg: input not a package\n");
                     94:                exit (1);
                     95:        }
                     96: 
                     97:        /* establish a temporary file */
                     98:        (void) tmpnam (tfname);
                     99:        tf = fopen (tfname, "w");
                    100:        sigsav = signal (SIGINT, SIG_IGN);
                    101:        if (sigsav != SIG_IGN)
                    102:                signal (SIGINT, delete);
                    103:        chmod (tfname, 0600);
                    104: 
                    105:        /* copy the installation instructions to the temp file */
                    106:        size = read_header (instr, file);
                    107:        while (--size >= 0) {
                    108:                c = getc (file);
                    109:                if (c == EOF) {
                    110:                        fprintf (stderr, "inspkg: premature EOF\n");
                    111:                        exit (1);
                    112:                }
                    113:                if (putc (c, tf) == EOF) {
                    114:                        perror ("inspkg: Instructions");
                    115:                        exit (1);
                    116:                }
                    117:        }
                    118:        if (fclose (tf) == EOF) {
                    119:                perror ("inspkg: Instructions fclose");
                    120:                exit (1);
                    121:        }
                    122: 
                    123:        next_header (file);
                    124: 
                    125:        /* create the optional backup package */
                    126:        if (bflag) {
                    127:                pkgstart();
                    128:                readtemp (BACKUP, file);
                    129:                pkgend();
                    130:                clearlist();
                    131:        }
                    132: 
                    133:        /* do the actual work */
                    134:        readtemp (INSTALL, file);
                    135: 
                    136:        /* delete the temporary file */
                    137:        nchk (unlink (tfname));
                    138:        signal (SIGINT, sigsav);
                    139: 
                    140:        return 0;
                    141: }
                    142: 
                    143: /*
                    144:  *     install the given file
                    145:  */
                    146: static int
                    147: process (FILE *file, char *fname)
                    148: {
                    149:        register int c, rc = 0;
                    150: 
                    151:        if (vflag)
                    152:                fprintf (stderr, "%s:\n", fname);
                    153: 
                    154:        while ((c = getc (file)) != EOF) {
                    155:                ungetc (c, file);
                    156:                rc += doarch (file);
                    157:        }
                    158: 
                    159:        return rc;
                    160: }
                    161: 
                    162: int
                    163: main (int argc, char **argv)
                    164: {
                    165:        static char errbuf[BUFSIZ];
                    166: 
                    167:        setbuf (stderr, errbuf);
                    168:        umask (0);
                    169:        return getargs (argc, argv, "nvbD:", process);
                    170: }
                    171: 
                    172: /*
                    173:  *     Make a pass through the temp file.
                    174:  */
                    175: static void
                    176: readtemp (int code, FILE *file)
                    177: {
                    178:        register FILE *tf;
                    179:        register int c;
                    180: 
                    181:        /* we're done writing the temp file, time to read it */
                    182:        tf = fopen (tfname, "r");
                    183:        schk ((char *) tf);
                    184: 
                    185:        /*
                    186:         *      The main loop -- one iteration per line
                    187:         *      We are careful in use and reuse of storage here;
                    188:         *      if you change this code make sure you understand
                    189:         *      the times at which getfield and transname
                    190:         *      recycle storage or strange things will happen.
                    191:         */
                    192:        while ((c = getc (tf)) != EOF) {
                    193:                char *param, *path, *path2;
                    194:                register FILE *outfd;
                    195:                int uid, gid, mode, dmajor, dminor, dev;
                    196:                register long size;
                    197:                char component[MAXCOMP+1];
                    198: 
                    199:                switch (c) {
                    200: 
                    201: #if 0
                    202:                /* special files */
                    203:                case 'b':
                    204:                case 'c':
                    205:                        /* read the parameters */
                    206:                        param = getfield (tf);
                    207:                        mode = cvlong (param, strlen (param), 8) |
                    208:                            (c == 'c'? S_IFCHR: S_IFBLK);
                    209:                        param = getfield (tf);
                    210:                        dmajor = cvlong (param, strlen (param), 10);
                    211:                        param = getfield (tf);
                    212:                        dminor = cvlong (param, strlen (param), 10);
                    213:                        dev = makedev (dmajor, dminor);
                    214:                        uid = uidnum (getfield (tf));
                    215:                        gid = gidnum (getfield (tf));
                    216:                        path = transname (getfield (tf));
                    217:                        geteol (tf);
                    218: 
                    219:                        switch (code) {
                    220: 
                    221:                        case BACKUP:
                    222:                                if (!subsumed (path)) {
                    223:                                        pkgfile (path);
                    224:                                        addlist (path);
                    225:                                }
                    226:                                break;
                    227: 
                    228:                        case INSTALL:
                    229:                                if (vflag) {
                    230:                                        fprintf (stderr, "special file ");
                    231:                                        putpath (stderr, path);
                    232:                                        fprintf (stderr, "\n");
                    233:                                }
                    234: 
                    235:                                if (!nflag) {
                    236:                                        rmall (path);
                    237:                                        if (mknod (path, mode, dev) >= 0)
                    238:                                                chown (path, uid, gid);
                    239:                                        else
                    240:                                                perror (path);
                    241:                                }
                    242:                                break;
                    243:                        }
                    244:                        break;
                    245: #endif
                    246: 
                    247:                /* directory */
                    248:                case 'd':
                    249:                        /* read the parameters */
                    250:                        param = getfield (tf);
                    251:                        mode = cvlong (param, strlen (param), 8);
                    252:                        uid = uidnum (getfield (tf));
                    253:                        gid = gidnum (getfield (tf));
                    254:                        path = transname (getfield (tf));
                    255:                        geteol (tf);
                    256: 
                    257:                        switch (code) {
                    258: 
                    259:                        case BACKUP:
                    260:                                if (!subsumed (path)) {
                    261:                                        pkgfile (path);
                    262:                                        addlist (path);
                    263:                                }
                    264:                                break;
                    265: 
                    266:                        case INSTALL:
                    267:                                /* make the directory */
                    268:                                if (vflag) {
                    269:                                        fprintf (stderr, "directory ");
                    270:                                        putpath (stderr, path);
                    271:                                        putc ('\n', stderr);
                    272:                                }
                    273:                                if (!nflag) {
                    274:                                        rmall (path);
                    275:                                        mkd (path);
                    276:                                        chmod (path, mode);
                    277:                                        chown (path, uid, gid);
                    278:                                        chmod (path, mode);
                    279:                                }
                    280:                                break;
                    281:                        }
                    282: 
                    283:                        break;
                    284: 
                    285:                /* file */
                    286:                case 'f':
                    287:                        /* read parameters */
                    288:                        param = getfield (tf);
                    289:                        if (strlen (param) > MAXCOMP) {
                    290:                                fprintf (stderr,
                    291:                                    "inspkg: impossibly long component name\n");
                    292:                                delete(0);
                    293:                                exit (1);
                    294:                        }
                    295:                        strcpy (component, param);
                    296:                        uid = uidnum (getfield (tf));
                    297:                        gid = gidnum (getfield (tf));
                    298:                        path = transname (getfield (tf));
                    299:                        geteol (tf);
                    300: 
                    301:                        switch (code) {
                    302: 
                    303:                        case BACKUP:
                    304:                                if (!subsumed (path))
                    305:                                        pkgfile (path);
                    306:                                break;
                    307: 
                    308:                        case INSTALL:
                    309:                                /* read the corresponding archive header */
                    310:                                size = read_header (component, file);
                    311: 
                    312:                                if (vflag) {
                    313:                                        fprintf (stderr, "file ");
                    314:                                        putpath (stderr, path);
                    315:                                        putc ('\n', stderr);
                    316:                                }
                    317: 
                    318:                                /* create and open the file */
                    319:                                if (!nflag) {
                    320:                                        rmall (path);
                    321:                                        umask (077);
                    322:                                        outfd = fopen (path, "w");
                    323:                                        umask (0);
                    324:                                        if (outfd == NULL) {
                    325:                                                fprintf (stderr,
                    326:                                                    "inspkg: cannot create ");
                    327:                                                putpath (stderr, path);
                    328:                                                putc ('\n', stderr);
                    329:                                        }
                    330:                                }
                    331:                                if (nflag || outfd == NULL) {
                    332:                                        outfd = fopen ("/dev/null", "w");
                    333:                                        schk ((char *) outfd);
                    334:                                }
                    335: 
                    336:                                /* copy the file, advance input */
                    337:                                while (--size >= 0)
                    338:                                        putc (getc (file), outfd);
                    339:                                next_header (file);
                    340: 
                    341:                                /* check successful completion, close output */
                    342:                                fflush (outfd);
                    343:                                if (feof (file) || ferror (file) ||
                    344:                                    ferror (outfd)) {
                    345:                                        fprintf (stderr, "inspkg: can't write ");
                    346:                                        putpath (stderr, path);
                    347:                                        putc ('\n', stderr);
                    348:                                }
                    349:                                if (fclose (outfd) == EOF) {
                    350:                                        fprintf (stderr, "inspkg: can't close ");
                    351:                                        putpath (stderr, path);
                    352:                                        fprintf (stderr, ": ");
                    353:                                        perror ("");
                    354:                                }
                    355:                                
                    356:                                /*
                    357:                                 *      Update output modification times
                    358:                                 *      and change mode and owner.
                    359:                                 *      This is done here to cater to systems
                    360:                                 *      that allow people to give files away.
                    361:                                 *      The chmod is done twice because
                    362:                                 *      systems that let you give files away
                    363:                                 *      won't let you change the mode after
                    364:                                 *      you've done so, and some other systems
                    365:                                 *      turn off the setuid bit as a side
                    366:                                 *      effect of chown, so the second chmod
                    367:                                 *      will restore that bit.
                    368:                                 */
                    369:                                if (!nflag) {
                    370:                                        struct utimbuf utb;
                    371:                                        utb.actime = utb.modtime = hdr.date;
                    372:                                        utime (path, &utb);
                    373:                                        chmod (path, hdr.mode & 07777);
                    374:                                        chown (path, uid, gid);
                    375:                                        chmod (path, hdr.mode & 07777);
                    376:                                }
                    377: 
                    378:                                break;
                    379:                        }
                    380:                        break;
                    381: 
                    382:                /* symbolic link */
                    383:                case 's':
                    384:                        /* read parameters */
                    385:                        path = copy (transname (getfield (tf)));
                    386:                        path2 = transname (getfield (tf));
                    387:                        geteol (tf);
                    388: 
                    389:                        switch (code) {
                    390:                        case BACKUP:
                    391:                                if (!subsumed (path2))
                    392:                                        pkgfile (path2);
                    393:                                break;
                    394: 
                    395:                        case INSTALL:
                    396:                                /* log it if requested */
                    397:                                if (vflag) {
                    398:                                        fprintf (stderr, "symlink ");
                    399:                                        putpath (stderr, path2);
                    400:                                        fprintf (stderr, " to ");
                    401:                                        putpath (stderr, path);
                    402:                                        putc ('\n', stderr);
                    403:                                }
                    404: #ifdef S_ISLNK
                    405: 
                    406:                                /* make the link */
                    407:                                if (!nflag) {
                    408:                                        rmall (path2);
                    409:                                        if (symlink (path, path2) < 0)
                    410:                                                perror (path2);
                    411:                                }
                    412: #else
                    413:                                fprintf(stderr, "This system does not support symbolic links\n");
                    414: #endif
                    415: 
                    416:                                break;
                    417:                        }
                    418:                        free (path);
                    419:                        break;
                    420:                
                    421:                /* link */
                    422:                case 'l':
                    423:                        /* read parameters */
                    424:                        path = copy (transname (getfield (tf)));
                    425:                        path2 = transname (getfield (tf));
                    426:                        geteol (tf);
                    427: 
                    428:                        switch (code) {
                    429: 
                    430:                        case BACKUP:
                    431:                                if (!subsumed (path2))
                    432:                                        pkgfile (path2);
                    433:                                break;
                    434: 
                    435:                        case INSTALL:
                    436:                                /* log it if requested */
                    437:                                if (vflag) {
                    438:                                        fprintf (stderr, "link ");
                    439:                                        putpath (stderr, path);
                    440:                                        fprintf (stderr, " to ");
                    441:                                        putpath (stderr, path2);
                    442:                                        putc ('\n', stderr);
                    443:                                }
                    444: 
                    445:                                /* make the link */
                    446:                                if (!nflag) {
                    447:                                        struct stat sb, sb2;
                    448: 
                    449:                                        /* are we about to link x to x? */
                    450:                                        if (stat (path, &sb) < 0
                    451:                                            || stat (path2, &sb2) < 0
                    452:                                            || sb.st_dev != sb2.st_dev
                    453:                                            || sb.st_ino != sb2.st_ino) {
                    454:                                                rmall (path2);
                    455:                                                if (link (path, path2) < 0)
                    456:                                                        perror (path2);
                    457:                                        }
                    458:                                }
                    459: 
                    460:                                break;
                    461:                        }
                    462:                        free (path);
                    463:                        break;
                    464:                
                    465:                /* remove */
                    466:                case 'r':
                    467:                        /* get parameters */
                    468:                        path = transname (getfield (tf));
                    469:                        geteol (tf);
                    470: 
                    471:                        switch (code) {
                    472: 
                    473:                        case BACKUP:
                    474:                                if (!subsumed (path))
                    475:                                        pkgfile (path);
                    476:                                break;
                    477: 
                    478:                        case INSTALL:
                    479:                                if (vflag) {
                    480:                                        fprintf (stderr, "remove file ");
                    481:                                        putpath (stderr, path);
                    482:                                        putc ('\n', stderr);
                    483:                                }
                    484:                                if (!nflag)
                    485:                                        rmall (path);
                    486:                                break;
                    487:                        }
                    488: 
                    489:                        break;
                    490: 
                    491:                case 'x':
                    492:                        xstr = getfield (tf);
                    493:                        geteol (tf);
                    494:                        if (code == INSTALL) {
                    495:                                if (vflag) {
                    496:                                        fprintf (stderr, "execute: ");
                    497:                                        putpath (stderr, xstr);
                    498:                                        fprintf (stderr, "\n");
                    499:                                }
                    500:                                if (!nflag) {
                    501:                                        fflush (stderr);
                    502:                                        system (xstr);
                    503:                                }
                    504:                        }
                    505:                        xstr = NULL;
                    506:                        break;
                    507: 
                    508:                case 'X':
                    509:                        Xstr = transname (getfield (tf));
                    510:                        geteol (tf);
                    511:                        if (code == INSTALL) {
                    512:                                if (vflag) {
                    513:                                        fprintf (stderr, "exec file: ");
                    514:                                        putpath (stderr, Xstr);
                    515:                                        fprintf (stderr, "\n");
                    516:                                }
                    517:                                if (!nflag) {
                    518:                                        int status, pid, w;
                    519:                                        Sig_typ istat, qstat;
                    520: 
                    521:                                        fflush (stderr);
                    522:                                        if ((pid = fork()) == 0) {
                    523:                                                execl (Xstr, Xstr, (char *)0);
                    524:                                                execl ("/bin/sh", "sh", Xstr, (char *) 0);
                    525:                                                putpath (stderr, Xstr);
                    526:                                                fprintf (stderr, ": ");
                    527:                                                fflush (stderr);
                    528:                                                perror ("");
                    529:                                                _exit(127);
                    530:                                        }
                    531:                                        istat = signal (SIGINT, SIG_IGN);
                    532:                                        qstat = signal (SIGQUIT, SIG_IGN);
                    533:                                        while ((w=wait(&status)) != pid && w != -1)
                    534:                                                ;
                    535:                                        signal(SIGINT, istat);
                    536:                                        signal(SIGQUIT, qstat);
                    537:                                }
                    538:                        }
                    539:                        Xstr = NULL;
                    540:                        break;
                    541: 
                    542:                default:
                    543:                        fprintf (stderr, "inspkg: invalid package\n");
                    544:                        delete(0);
                    545:                        exit (1);
                    546:                }
                    547:        }
                    548: 
                    549:        if (ferror (tf))
                    550:                perror ("inspkg: internal temp file");
                    551: 
                    552:        fclose (tf);
                    553: 
                    554: }
                    555: 
                    556: static void
                    557: delete(int sigarg)
                    558: {
                    559:        unlink (tfname);
                    560:        exit (3);
                    561: }

unix.superglobalmegacorp.com

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