Annotation of coherent/f/usr/spool/uucppublic/ar.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * ar.c
                      3:  * Archive manager.
                      4:  * Also manages libraries for the
                      5:  * link editor,
                      6:  * including ranlib header updates.
                      7:  */
                      8: #define PORTAR 1       /* COFF frmat */
                      9: 
                     10: #ifdef COHERENT
                     11: #define SLASH '/'
                     12: #else
                     13: #define SLASH '\\'
                     14: #endif
                     15: 
                     16: #include <stdio.h>
                     17: #include <stdlib.h>
                     18: #include <arcoff.h>
                     19: #include <ar.h>
                     20: #if !PORTAR
                     21: #include <canon.h>
                     22: #else
                     23: #include <coff.h>
                     24: #endif
                     25: #include <sys/types.h>
                     26: #include <sys/stat.h>
                     27: 
                     28: #define        RO      0
                     29: #define        RW      1
                     30: 
                     31: #define        NONE    0
                     32: #define        BEFORE  1
                     33: #define        AFTER   2
                     34: 
                     35: #define        ALLOK   0
                     36: #define        NOTALL  1
                     37: #define        ERROR   2
                     38: 
                     39: #define        aechk() { if(ferror(afp)) ioerr(anp); }
                     40: #define        techk() { if(ferror(tfp)) ioerr(tnp); }
                     41: 
                     42: char   nwork[] = "No work";
                     43: char   found[] = "found";
                     44: char   copen[] = "%s: cannot open";
                     45: char   ccrea[] = "%s: cannot create";
                     46: char   creop[] = "%s: cannot reopen";
                     47: 
                     48: FILE   *afp;
                     49: FILE   *tfp;
                     50: FILE   *rfp;
                     51: #define DIRSIZ 14
                     52: #if PORTAR
                     53: struct old_ar_hdr ahb;
                     54: char   rnp[] = "";
                     55: char   rnpx[] = "SYMDEF.__";
                     56: #else
                     57: #define SARMAG sizeof(short)
                     58: char   rnp[] = HDRNAME;
                     59: char   *rnpx = rnp;
                     60: struct ar_hdr ahb;
                     61: #endif
                     62: 
                     63: long   fsize();
                     64: long   ftell();
                     65: long   atol();
                     66: char   *ctime();
                     67: char   *strchr();
                     68: char   *strrchr();
                     69: int    usage();
                     70: 
                     71: long   ranCt;  /* count of ranlib entrys for coff */
                     72: 
                     73: int    nname;
                     74: char   **namep;
                     75: int    cflag;
                     76: int    kflag;
                     77: int    lflag;
                     78: int    sflag;
                     79: int    uflag;
                     80: int    vflag;
                     81: int    xflag;
                     82: char   *pnp;
                     83: char   *anp;
                     84: char   *tnp;
                     85: int    xstat    = ALLOK;
                     86: int    pos      = NONE;
                     87: int    (*ffp)() = usage;
                     88: FILE *makeh();
                     89: 
                     90: char   state[] = "'%s' file not found";
                     91: 
                     92: /*
                     93:  * ar called as ranlib.
                     94:  */
                     95: ranlib(argv)
                     96: char *argv[];
                     97: {
                     98:        int rfunc();
                     99: 
                    100:        ffp = rfunc;
                    101:        ++sflag;
                    102:        anp = argv[1];
                    103:        (*ffp)();
                    104:        delexit(xstat);
                    105: }
                    106: 
                    107: main(argc, argv)
                    108: char *argv[];
                    109: {
                    110:        register i;
                    111:        char *p;
                    112:        int usage(), rfunc();
                    113: 
                    114:        if (NULL == (p = strrchr(argv[0], SLASH)))
                    115:                p = argv[0];
                    116:        else
                    117:                p++;
                    118: 
                    119:        if (!strcmp(p, "ranlib"))
                    120:                ranlib(argv);
                    121: 
                    122:        if (strcmp(p, "ar"))
                    123:                diag(1, "called as %s, expecting ar, or ranlib", p);
                    124: 
                    125:        _addargs("AR", &argc, &argv);
                    126:        if (argc < 2)
                    127:                usage();
                    128:        key(argv[1]);
                    129:        nname = argc - 2;
                    130:        namep = &argv[2];
                    131:        for (i = 2; i < argc; ++i) {
                    132:                if (pos != NONE && pnp == NULL) {
                    133:                        pnp = argv[i];
                    134:                        ++namep;
                    135:                        --nname;
                    136:                } else {
                    137:                        anp = argv[i];
                    138:                        ++namep;
                    139:                        --nname;
                    140:                        break;
                    141:                }
                    142:        }
                    143:        if (anp == NULL)
                    144:                usage();
                    145:        if (pos != NONE) {
                    146:                if (pnp == NULL)
                    147:                        usage();
                    148:                if (ffp == usage)
                    149:                        ffp = rfunc;
                    150:        }
                    151:        (*ffp)();
                    152:        delexit(xstat);
                    153: }
                    154: 
                    155: /*
                    156:  * Decode key.
                    157:  * Save function name in 'ffp'.
                    158:  * Set 'c', 'l', 'k' and 'v' flags.
                    159:  */
                    160: key(p)
                    161: register char *p;
                    162: {
                    163:        register c;
                    164:        int dfunc(), rfunc(), qfunc(), tfunc();
                    165:        int mfunc(), xfunc(), pfunc();
                    166: 
                    167:        while (c = *p++) {
                    168:                switch (c) {
                    169: 
                    170:                case 'd':       /* Delete */
                    171:                        ffp = dfunc;
                    172:                        break;
                    173: 
                    174:                case 'r':       /* Replace */
                    175:                        ffp = rfunc;
                    176:                        break;
                    177: 
                    178:                case 'q':       /* Quick append */
                    179:                        ffp = qfunc;
                    180:                        break;
                    181: 
                    182:                case 't':       /* Tabulate */
                    183:                        ffp = tfunc;
                    184:                        break;
                    185: 
                    186:                case 'p':       /* Print */
                    187:                        ffp = pfunc;
                    188:                        break;
                    189: 
                    190:                case 'm':       /* Move */
                    191:                        ffp = mfunc;
                    192:                        break;
                    193: 
                    194:                case 'x':       /* Extract */
                    195:                        ffp = xfunc;
                    196:                        ++xflag;
                    197:                        break;
                    198: 
                    199:                case 'c':       /* no create message */
                    200:                        ++cflag;
                    201:                        break;
                    202: 
                    203:                case 'k':       /* keep dates */
                    204:                        ++kflag;
                    205:                        break;
                    206: 
                    207:                case 'l':       /* local temp file */
                    208:                        ++lflag;
                    209:                        break;
                    210: 
                    211:                case 's':       /* ranlib symbol table */
                    212:                        ++sflag;
                    213:                        break;
                    214: 
                    215:                case 'u':       /* update replace */
                    216:                        ++uflag;
                    217:                        break;
                    218: 
                    219:                case 'v':       /* verbose */
                    220:                        ++vflag;
                    221:                        break;
                    222: 
                    223:                case 'a':       /* after position or append */
                    224:                        pos = AFTER;
                    225:                        break;
                    226: 
                    227:                case 'b':       /* before position */
                    228:                case 'i':       /* insert */
                    229:                        pos = BEFORE;
                    230:                        break;
                    231: 
                    232:                default:
                    233:                        usage();
                    234:                }
                    235:        }
                    236: }
                    237: 
                    238: /*
                    239:  * Seek forward for ahb.ar_size rounded up.
                    240:  */
                    241: static
                    242: seekPast()
                    243: {
                    244:        long len;
                    245: 
                    246:        len = (ahb.ar_size + 1) & ~1;
                    247:        fseek(afp, len, 1);
                    248: }
                    249: 
                    250: /*
                    251:  * Replace.
                    252:  * Eliminate dead stuff if 'u'.
                    253:  * Copy up to insert point.
                    254:  * Copy in new files.
                    255:  * Copy the rest of the file.
                    256:  * Copy back.
                    257:  */
                    258: rfunc()
                    259: {
                    260:        register char *qfn;
                    261:        register i, nef;
                    262:        FILE *qfp;
                    263: 
                    264:        if (nname == 0 && sflag == 0)
                    265:                diag(1, nwork);
                    266:        aopen(RW);      /* open archive */
                    267:        ropen();        /* maybe open ranlib */
                    268:        if (uflag) {
                    269:                update();
                    270:                fseek(afp, (long)SARMAG, 0);    /* bypass magic */
                    271:                if (rfp != NULL) {
                    272:                        geth();
                    273:                        if (eqh(rnp))   /* if SYMBOL header bypass */
                    274:                                seekPast();
                    275:                        else
                    276:                                fseek(afp, (long)SARMAG, 0);
                    277:                }
                    278:        }
                    279:        topen();        /* open tmpfile */
                    280:        while (nef = geth()) {
                    281:                if (pos==BEFORE && eqh(pnp)) {
                    282:                        fseek(afp, (long)-sizeof(struct ar_hdr), 1);
                    283:                        break;
                    284:                }
                    285:                if (pos == NONE) {
                    286:                        for (i=0; i<nname; ++i) {
                    287:                                if ((qfn=namep[i])!=NULL && eqh(qfn))
                    288:                                        break;
                    289:                        }
                    290:                        if (i != nname) {
                    291:                                seekPast();
                    292:                                namep[i] = NULL;
                    293:                                remove(i, qfn);
                    294:                                qfp = makeh(qfn);
                    295:                                if (vflag)
                    296:                                        printf("%s: in place replace.\n", qfn);
                    297:                                puth(tfp, tnp);
                    298:                                ffcopy(tfp, tnp, qfp, qfn, (long)ahb.ar_size);
                    299:                                fclose(qfp);
                    300:                                continue;
                    301:                        }
                    302:                }
                    303:                mmove(0);
                    304:                if (pos==AFTER &&  eqh(pnp))
                    305:                        break;
                    306:        }
                    307:        if (nef==0 && pos!=NONE)
                    308:                diag(1, "%s: not in archive", pnp);
                    309:        for (i=0; i<nname; ++i) {
                    310:                if ((qfn=namep[i]) == NULL)
                    311:                        continue;
                    312:                remove(i, qfn);
                    313:                qfp = makeh(qfn);
                    314:                if (vflag)
                    315:                        printf("%s: replaced.\n", qfn);
                    316:                puth(tfp, tnp);
                    317:                ffcopy(tfp, tnp, qfp, qfn, (long)ahb.ar_size);
                    318:                fclose(qfp);
                    319:        }
                    320:        while (geth())
                    321:                mmove(0);
                    322:        tacopy();
                    323: }
                    324: 
                    325: /*
                    326:  * Handle the 'u' option.
                    327:  * Read through the archive, comparing
                    328:  * the dates in the headers to the last
                    329:  * modification dates of the files in
                    330:  * the command line. Make some files
                    331:  * go away.
                    332:  */
                    333: update()
                    334: {
                    335:        register char *p;
                    336:        register i;
                    337:        struct stat sb;
                    338: 
                    339:        while (geth()) {
                    340:                for (i=0; i<nname; ++i) {
                    341:                        p = namep[i];
                    342:                        if (p!=NULL && eqh(p)) {
                    343:                                if (stat(p, &sb) < 0)
                    344:                                        diag(1, state, p);
                    345:                                if (ahb.ar_date >= sb.st_mtime) {
                    346:                                        if (vflag)
                    347:                                                printf("%s: no update.\n", p);
                    348:                                        namep[i] = NULL;
                    349:                                        remove(i, p);
                    350:                                }
                    351:                        }
                    352:                }
                    353:                seekPast();
                    354:        }
                    355:        for (i=0; i<nname && namep[i]==NULL; ++i)
                    356:                ;
                    357:        if (i >= nname) {
                    358:                if (vflag)
                    359:                        fprintf(stderr, "%s.\n", nwork);
                    360:                delexit(ALLOK);
                    361:        }
                    362: }
                    363: 
                    364: /*
                    365:  * Move.
                    366:  * Copy stuff before insert.
                    367:  * Copy moved stuff.
                    368:  * Copy remainder.
                    369:  * Copy back to archive.
                    370:  */
                    371: mfunc()
                    372: {
                    373:        register nef;
                    374:        long s;
                    375: 
                    376:        aopen(RW);
                    377:        ropen();
                    378:        topen();
                    379:        while (nef = geth()) {
                    380:                if (pos==BEFORE && eqh(pnp))
                    381:                        break;
                    382:                mmove(0);
                    383:                if (pos==AFTER &&  eqh(pnp))
                    384:                        break;
                    385:        }
                    386:        if (nef==0 && pos!=NONE)
                    387:                diag(1, "%s: not in archive", pnp);
                    388:        s = ftell(afp);
                    389:        if (pos == BEFORE)
                    390:                s -= sizeof(struct ar_hdr);
                    391:        fseek(afp, (long)SARMAG, 0);
                    392:        while (geth())
                    393:                mmove(1);
                    394:        if (nef) {
                    395:                fseek(afp, s, 0);
                    396:                while (geth())
                    397:                        mmove(0);
                    398:        }
                    399:        tacopy();
                    400: }
                    401: 
                    402: /*
                    403:  * Conditional move to the
                    404:  * temp file from the archive
                    405:  * file. Used by move and replace
                    406:  */
                    407: mmove(f1)
                    408: register f1;
                    409: {
                    410:        register f2, i;
                    411:        register long size;
                    412: 
                    413:        f2 = 0;
                    414:        for (i=0; i<nname; ++i) {
                    415:                if (eqh(namep[i])) {
                    416:                        ++f2;
                    417:                        break;
                    418:                }
                    419:        }
                    420:        if (f1 == f2) {
                    421:                if (vflag)
                    422:                        amsg("copied");
                    423:                size = ahb.ar_size;
                    424:                puth(tfp, tnp);
                    425:                ffcopy(tfp, tnp, afp, anp, size);
                    426:        } else {
                    427:                if (vflag)
                    428:                        amsg("skipped");
                    429:                seekPast();
                    430:        }
                    431: }
                    432: 
                    433: /*
                    434:  * Print.
                    435:  */
                    436: pfunc()
                    437: {
                    438:        aopen(RO);
                    439:        while (geth()) {
                    440:                if (nname==0 || match())
                    441:                        pfile();
                    442:                else
                    443:                        seekPast();
                    444:        }
                    445:        if (nname != 0)
                    446:                notdone(found);
                    447: }
                    448: 
                    449: pfile()
                    450: {
                    451:        if (vflag)
                    452:                amsg(NULL);
                    453:        ffcopy(stdout, "Stdout", afp, anp, ahb.ar_size);
                    454: }
                    455: 
                    456: /*
                    457:  * Delete.
                    458:  * Copy archive to temp, deleting
                    459:  * members along the way. If all of
                    460:  * the files have been deleted then
                    461:  * copy back.
                    462:  */
                    463: dfunc()
                    464: {
                    465:        register long size;
                    466: 
                    467:        if (nname == 0)
                    468:                diag(1, nwork);
                    469:        aopen(RW);
                    470:        ropen();
                    471:        topen();
                    472:        while (geth()) {
                    473:                if (match()) {
                    474:                        if (vflag)
                    475:                                amsg("deleted");
                    476:                        seekPast();
                    477:                        continue;
                    478:                }
                    479:                if (vflag)
                    480:                        amsg("copied");
                    481:                size = ahb.ar_size;
                    482:                puth(tfp, tnp);
                    483:                ffcopy(tfp, tnp, afp, anp, size);
                    484:        }
                    485:        if (notdone("deleted"))
                    486:                delexit(ERROR);
                    487:        tacopy();
                    488: }
                    489: 
                    490: /*
                    491:  * Quick insert.
                    492:  * Copy archive to temp file.
                    493:  * Tack new files onto the end.
                    494:  * If no errors, copy back.
                    495:  */
                    496: qfunc()
                    497: {
                    498:        register char *qfn;
                    499:        register FILE *qfp;
                    500:        register i;
                    501: 
                    502:        if (nname == 0)
                    503:                diag(1, nwork);
                    504:        aopen(RW);
                    505:        if (geth() != 0 && eqh(rnp)) {
                    506:                fseek(afp, (long)-sizeof(ahb), 1);
                    507:                ahb.ar_date = 0;
                    508:                puth(afp, anp);
                    509:        }
                    510:        fseek(afp, (long)0, 2);
                    511:        for (i=0; i<nname; ++i) {
                    512:                if ((qfn=namep[i]) == NULL)
                    513:                        continue;
                    514:                remove(i, qfn);
                    515:                qfp = makeh(qfn);
                    516:                if (vflag)
                    517:                        printf("%s: quick insert.\n", qfn);
                    518:                puth(afp, anp);
                    519:                ffcopy(afp, anp, qfp, qfn, (long)ahb.ar_size);
                    520:                fclose(qfp);
                    521:        }
                    522: }
                    523: 
                    524: /*
                    525:  * Table.
                    526:  * Read through archive.
                    527:  * If good member print its name.
                    528:  * If verbose, print extra stuff.
                    529:  */
                    530: tfunc()
                    531: {
                    532:        register char *p;
                    533:        register c, n;
                    534: 
                    535:        aopen(RO);
                    536:        while (geth()) {
                    537:                if (nname==0 || match()) {
                    538:                        if (!*(p = ahb.ar_name)) {
                    539:                                seekPast();
                    540:                                continue;
                    541:                        }
                    542:                        n = 0;
                    543:                        while (n<DIRSIZ && (c=*p++)) {
                    544:                                putchar(c);
                    545:                                ++n;
                    546:                        }
                    547:                        if (vflag) {
                    548:                                while (n++ < DIRSIZ+1)
                    549:                                        putchar(' ');
                    550: #if COHERENT
                    551:                                printf("%5d %5d ", ahb.ar_gid, ahb.ar_uid);
                    552:                                printf("%04o ",  ahb.ar_mode & 07777);
                    553: #endif
                    554:                                printf("%10ld ", ahb.ar_size);
                    555:                                printf("%s", ctime(&ahb.ar_date));
                    556:                        } else
                    557:                                putchar('\n');
                    558:                }
                    559:                seekPast();
                    560:        }
                    561:        if (nname != 0)
                    562:                notdone(found);
                    563: }
                    564: 
                    565: /*
                    566:  * Extract.
                    567:  * Read through archive.
                    568:  * Extract any files you find.
                    569:  * At end, mutter about files
                    570:  * that were not there.
                    571:  */
                    572: xfunc()
                    573: {
                    574:        register char *p1, *p2;
                    575:        register c;
                    576:        char fnb[DIRSIZ+1];
                    577:        FILE *xfp;
                    578: 
                    579:        aopen(RO);
                    580:        while (geth()) {
                    581:                if (nname==0 || match()) {
                    582:                        if (!*(p1 = ahb.ar_name)) {
                    583:                                seekPast();
                    584:                                continue;
                    585:                        }
                    586:                        p2 = fnb;
                    587:                        while (p1<&ahb.ar_name[DIRSIZ] && (c=*p1++))
                    588:                                *p2++ = c;
                    589:                        *p2 = 0;
                    590:                        if ((xfp=fopen(fnb, "wb")) == NULL) {
                    591:                                diag(0, ccrea, fnb);
                    592:                                seekPast();
                    593:                                continue;
                    594:                        }
                    595:                        if (vflag)
                    596:                                amsg("extracting");
                    597:                        ffcopy(xfp, fnb, afp, anp, ahb.ar_size);
                    598:                        chmod(fnb, ahb.ar_mode);
                    599: 
                    600:                        fclose(xfp);
                    601:                        if (kflag) {
                    602:                                time_t  times[2];
                    603:                                time_t  time();
                    604: 
                    605:                                time(times+0);
                    606:                                times[1] = ahb.ar_date;
                    607:                                if (utime(fnb, times) < 0)
                    608:                                        diag(0, "Unable to set time for %s",
                    609:                                         fnb);
                    610:                        }
                    611:                } else
                    612:                        seekPast();
                    613:        }
                    614:        if (nname != 0)
                    615:                notdone(found);
                    616: }
                    617: 
                    618: /*
                    619:  * Make an archive header.
                    620:  * Put it in the external archive
                    621:  * header buffer 'ahb'. The arg.
                    622:  * 'fn' is the file name. The file
                    623:  * is open on 'fp'.
                    624:  */
                    625: FILE *
                    626: makeh(fn)
                    627: char *fn;
                    628: {
                    629:        FILE *fp;
                    630:        char *p1;
                    631: 
                    632:        struct stat sb;
                    633: 
                    634: #if GEMDOS
                    635:        if (stat(fn, &sb) < 0)
                    636:                diag(1, state, fn);
                    637: 
                    638:        if (NULL == (fp = fopen(fn, "rb")))
                    639:                diag(1, copen, fn);
                    640: #else
                    641:        if (NULL == (fp = fopen(fn, "rb")))
                    642:                diag(1, copen, fn);
                    643: 
                    644:        if (fstat(fileno(fp), &sb) < 0)
                    645:                diag(1, state, fn);
                    646: #endif 
                    647:        if (fn == rnpx)
                    648:                fn = "";
                    649: 
                    650:        if (NULL == (p1 = strrchr(fn, SLASH)))
                    651:                p1 = fn - 1;
                    652: 
                    653:        strncpy(ahb.ar_name, p1 + 1, DIRSIZ);
                    654: 
                    655:        if (kflag)
                    656:                ahb.ar_date = sb.st_mtime;
                    657:        else
                    658:                time(&ahb.ar_date);
                    659:        ahb.ar_uid  = sb.st_uid;
                    660:        ahb.ar_gid  = sb.st_gid;
                    661:        ahb.ar_mode = sb.st_mode & 07777;
                    662:        ahb.ar_size = sb.st_size;
                    663: 
                    664:        return (fp);
                    665: }
                    666: 
                    667: /*
                    668:  * Test if the member whose
                    669:  * header is held in the archive
                    670:  * header buffer is mentioned in
                    671:  * the user's list of members.
                    672:  * Return the number of matches.
                    673:  * All matches are NULLed.
                    674:  */
                    675: match()
                    676: {
                    677:        register char *p;
                    678:        register i, n;
                    679: 
                    680:        n = 0;
                    681:        for (i=0; i<nname; ++i) {
                    682:                if ((p=namep[i]) == NULL)
                    683:                        continue;
                    684:                if (eqh(p)) {
                    685:                        ++n;
                    686:                        namep[i] = NULL;
                    687:                }
                    688:        }
                    689:        return (n);
                    690: }
                    691: 
                    692: /*
                    693:  * Remove all instances of name
                    694:  * 'fn' from the list of names that
                    695:  * is described by 'namep' and
                    696:  * 'nname'.
                    697:  * Start at index 'i+1'.
                    698:  */
                    699: remove(i, fn)
                    700: register i;
                    701: register char *fn;
                    702: {
                    703:        register char *p;
                    704: 
                    705:        for (++i; i<nname; ++i) {
                    706:                if ((p=namep[i]) == NULL)
                    707:                        continue;
                    708:                if (strcmp(fn, p) == 0)
                    709:                        namep[i] = NULL;
                    710:        }
                    711: }
                    712: 
                    713: /*
                    714:  * This routine digs through the
                    715:  * list of names described by 'namep'
                    716:  * and 'nname' looking for names that
                    717:  * have not been NULLed out. If any
                    718:  * are found it prints a title and 
                    719:  * the names. The number of names that
                    720:  * were found is returned.
                    721:  */
                    722: notdone(s)
                    723: char *s;
                    724: {
                    725:        register char *p;
                    726:        register i, n;
                    727: 
                    728:        n = 0;
                    729:        for (i=0; i<nname; ++i) {
                    730:                p = namep[i];
                    731:                if (p != NULL) {
                    732:                        if (n++ == 0)
                    733:                                fprintf(stderr, "Not %s:\n", s);
                    734:                        fprintf(stderr, "%s\n", p);
                    735:                }
                    736:        }
                    737:        return (n);
                    738: }
                    739: 
                    740: /*
                    741:  * File to file copy.
                    742:  * With ranlib construction.
                    743:  */
                    744: ffcopy(tfp, tfn, ffp, ffn, s)
                    745: FILE *tfp, *ffp;
                    746: char *tfn, *ffn;
                    747: long s;
                    748: {
                    749:        register n;
                    750:        int pad;
                    751:        static char fb[BUFSIZ];
                    752: 
                    753:        if (rfp != NULL)
                    754:                raddmod(tfp, ffp, s);
                    755: 
                    756:        pad = s & 1;
                    757:        for (n = ftell(ffp) % BUFSIZ; s; (s -= n), (n = 0)) {
                    758:                if ((n = BUFSIZ - n) > s)
                    759:                        n = s;
                    760:                if (fread (fb, sizeof(char), n, ffp) != n)
                    761:                        ioerr(ffn);
                    762:                if (fwrite(fb, sizeof(char), n, tfp) != n)
                    763:                        ioerr(tfn);
                    764:        }
                    765:        if (pad) {
                    766:                fgetc(ffp);
                    767:                if (!xflag)
                    768:                        fputc(0, tfp);
                    769:        }
                    770: }
                    771: 
                    772: /*
                    773:  * Get the next archive header
                    774:  * into 'ahb'. Check for any I/O
                    775:  * errors. Return true if a header
                    776:  * was read and false on EOF.
                    777:  */
                    778: geth()
                    779: {
                    780: #if PORTAR
                    781:        struct ar_hdr hdr;
                    782:        int uid, gid, mode;
                    783:        register char *p;
                    784: 
                    785:        if (fread(&hdr, sizeof(hdr), 1, afp) != 1) {
                    786:                aechk();
                    787:                return (0);
                    788:        }
                    789: 
                    790:        memset(&ahb, '\0', sizeof(ahb));
                    791:        memcpy(ahb.ar_name, hdr.ar_name, DIRSIZ);
                    792:        if (NULL != (p = strchr(ahb.ar_name, '/')))
                    793:                *p = '\0';
                    794: 
                    795:        sscanf(hdr.ar_date, "%d %d %d %o %d",
                    796:                &ahb.ar_date, &uid, &gid, &mode, &ahb.ar_size);
                    797:        ahb.ar_uid  = uid;      /* use intermediate fields for shorts */
                    798:        ahb.ar_gid  = gid;
                    799:        ahb.ar_mode = mode & 07777;
                    800: 
                    801: #else
                    802:        if (fread(&ahb, sizeof(ahb), 1, afp) != 1) {
                    803:                aechk();
                    804:                return (0);
                    805:        }
                    806:        cantime(ahb.ar_date);
                    807:        canshort(ahb.ar_gid);
                    808:        canshort(ahb.ar_uid);
                    809:        canshort(ahb.ar_mode);
                    810:        cansize(ahb.ar_size);
                    811: #endif
                    812:        return (1);
                    813: }
                    814: 
                    815: /*
                    816:  * Write the header in 'ahb' to
                    817:  * the temp file.
                    818:  */
                    819: puth(fp, np)
                    820: FILE *fp;
                    821: char *np;
                    822: {
                    823: #if PORTAR
                    824:        struct ar_hdr hdr;
                    825:        register i;
                    826: 
                    827:        sprintf(hdr.ar_date, "%-12ld%-6d%-6d%-8o%-10ld",
                    828:                ahb.ar_date, ahb.ar_uid,
                    829:                ahb.ar_gid, ahb.ar_mode & 07777, ahb.ar_size);
                    830:        
                    831:        memcpy(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag));
                    832: 
                    833:        for (i = 0; (i < DIRSIZ) && ahb.ar_name[i]; i++)
                    834:                hdr.ar_name[i] = ahb.ar_name[i];
                    835:        hdr.ar_name[i++] = '/';
                    836:        for (; i < sizeof(hdr.ar_name); i++)
                    837:                hdr.ar_name[i] = ' ';
                    838: 
                    839:        fwrite(&hdr, sizeof(hdr), 1, fp);
                    840: #else
                    841:        cantime(ahb.ar_date);
                    842:        canshort(ahb.ar_gid);
                    843:        canshort(ahb.ar_uid);
                    844:        canshort(ahb.ar_mode);
                    845:        cansize(ahb.ar_size);
                    846:        fwrite(&ahb, sizeof(ahb), 1, fp);
                    847: #endif
                    848:        if(ferror(fp))
                    849:                ioerr(np);
                    850: }
                    851: 
                    852: /*
                    853:  * Compare a string to the name
                    854:  * of the member in the archive header
                    855:  * buffer. True return if same.
                    856:  */
                    857: eqh(p)
                    858: char *p;
                    859: {
                    860:        register char *p1;
                    861: 
                    862:        if (NULL == (p1 = strrchr(p, SLASH)))
                    863:                p1 = p;
                    864:        else
                    865:                p1++;
                    866: 
                    867:        return (!strncmp(p1, ahb.ar_name, DIRSIZ));
                    868: }
                    869: 
                    870: /*
                    871:  * Open archive.
                    872:  * The argument 'aam' is the
                    873:  * access mode (RO or RW).
                    874:  */
                    875: aopen(aam)
                    876: {
                    877: #ifdef PORTAR
                    878:        char    buf[SARMAG];
                    879: #else
                    880:        int i;
                    881: #endif
                    882: 
                    883:        if ((afp=fopen(anp, "rb")) == NULL) {
                    884:                if (aam == RO)
                    885:                        diag(1, copen, anp);
                    886:                if ((afp=fopen(anp, "wb"))==NULL
                    887:                 || (afp=freopen(anp, "wrb", afp))==NULL)
                    888:                        diag(1, ccrea, anp);
                    889:                if (cflag == 0)
                    890:                        printf("%s: new archive.\n", anp);
                    891: #if PORTAR
                    892:                fputs(ARMAG, afp);
                    893: #else
                    894:                i = ARMAG;
                    895:                canint(i);
                    896:                fwrite(&i, sizeof(i), 1, afp);
                    897: #endif
                    898:                aechk();
                    899:                fflush(afp);            /* allow read after write */
                    900:                return;
                    901:        }
                    902:        if (aam != RO) {
                    903:                fclose(afp);
                    904:                if ((afp=fopen(anp, "rwb"))==NULL)
                    905:                        diag(1, copen, anp);
                    906:        }
                    907: #if PORTAR
                    908:        fread(buf, SARMAG, 1, afp);
                    909:        aechk();
                    910:        if(memcmp(buf, ARMAG, SARMAG))
                    911: #else
                    912:        fread(&i, sizeof(i), 1, afp);
                    913:        aechk();
                    914:        canint(i);
                    915:        if (i != ARMAG)
                    916: #endif
                    917:                diag(1, "%s: not an archive", anp);
                    918: }
                    919: 
                    920: /*
                    921:  * Open tempfile.
                    922:  * Stash the name in 'tnp' for
                    923:  * the benefit of 'delexit'.
                    924:  * Honour the 'l' option w.r.t.
                    925:  * file placement.
                    926:  */
                    927: topen()
                    928: {
                    929:        int i;
                    930: 
                    931:        extern char *tempnam();
                    932:        tnp = tempnam((lflag ? "." : NULL), "v");
                    933: 
                    934:        if ((tfp=fopen(tnp, "wb")) == NULL) 
                    935:                diag(1, ccrea, tnp);
                    936: #if PORTAR
                    937:        fputs(ARMAG, tfp);
                    938: #else
                    939:        i = ARMAG;
                    940:        canint(i);
                    941:        fwrite(&i, sizeof(i), 1, tfp);
                    942: #endif
                    943:        techk();
                    944: }
                    945: 
                    946: /*
                    947:  * Copy tempfile back to the
                    948:  * archive.
                    949:  */
                    950: tacopy()
                    951: {
                    952:        register FILE *xtp;
                    953: #if PORTAR
                    954:        char buf[SARMAG];
                    955: #else
                    956:        int i;
                    957: #endif
                    958: 
                    959:        fclose(tfp);
                    960:        tfp = NULL;  /* Scare off delexit */
                    961:        fclose(afp);
                    962:        if ((xtp=fopen(tnp, "rb")) == NULL)
                    963:                diag(1, creop, tnp);
                    964:        if ((afp=fopen(anp, "wb")) == NULL)
                    965:                diag(1, creop, anp);
                    966:        if (vflag)
                    967:                printf("%s: copy back.\n", anp);
                    968: #if PORTAR
                    969:        if (fread(buf, SARMAG, 1, xtp) != 1)
                    970:                ioerr(tnp);
                    971:        if (fwrite(buf, SARMAG, 1, afp) != 1)
                    972:                ioerr(anp);
                    973:        if (rfp != NULL)
                    974:                 rcopy();
                    975:        ffcopy(afp, anp, xtp, tnp, fsize(xtp, tnp) - SARMAG);
                    976: #else
                    977:        if (fread(&i, sizeof(i), 1, xtp) != 1)
                    978:                ioerr(tnp);
                    979:        if (fwrite(&i, sizeof(i), 1, afp) != 1)
                    980:                ioerr(anp);
                    981:        if (rfp != NULL)
                    982:                 rcopy();
                    983:        ffcopy(afp, anp, xtp, tnp, fsize(xtp, tnp) - sizeof(int));
                    984: #endif
                    985:        tfp = xtp;   /* Delete */
                    986: }
                    987: 
                    988: /*
                    989:  * Write diagnostic.
                    990:  * The flag 'f' marks fatal errors.
                    991:  */
                    992: diag(f, a)
                    993: {
                    994:        fprintf(stderr, "%r.\n", &a);
                    995:        if (f)
                    996:                delexit(ERROR);
                    997:        xstat = NOTALL;
                    998: }
                    999: 
                   1000: /*
                   1001:  * Print a message for a
                   1002:  * given archive member. The header
                   1003:  * is in the header buffer. 
                   1004:  */
                   1005: amsg(s)
                   1006: char *s;
                   1007: {
                   1008:        register char *p;
                   1009:        register c;
                   1010: 
                   1011:        p = ahb.ar_name;
                   1012:        while (p<&ahb.ar_name[DIRSIZ] && (c=*p++)!=0)
                   1013:                putchar(c);
                   1014:        putchar(':');
                   1015:        if (s != NULL)
                   1016:                printf(" %s.", s);
                   1017:        putchar('\n');
                   1018: }
                   1019: 
                   1020: /*
                   1021:  * Exit.
                   1022:  * Delete the tempfile if
                   1023:  * present.
                   1024:  */
                   1025: delexit(s)
                   1026: {
                   1027:        if (tfp != NULL)
                   1028:                unlink(tnp);
                   1029: #ifdef DEBUG
                   1030:        if (s)
                   1031:                abort();
                   1032: #endif
                   1033:        unlink(rnpx);
                   1034:        exit(s);
                   1035: }
                   1036: 
                   1037: /*
                   1038:  * Mutter about an I/O error
                   1039:  * on file 's'.
                   1040:  */
                   1041: ioerr(s)
                   1042: char *s;
                   1043: {
                   1044:        diag(1, "%s: I/O error", s);
                   1045: }
                   1046: 
                   1047: /*
                   1048:  * Print usage message.
                   1049:  */
                   1050: usage()
                   1051: {
                   1052:        fprintf(stderr, "Usage: ar options [posname] afile [name ...].\n");
                   1053:        delexit(ERROR);
                   1054: }
                   1055: 
                   1056: /*
                   1057:  * Compute the size of a file.
                   1058:  * In bytes.
                   1059:  * The file must not be seeked.
                   1060:  */
                   1061: long
                   1062: fsize(fp, fn)
                   1063: FILE *fp;
                   1064: char *fn;
                   1065: {
                   1066:        struct stat sb;
                   1067: 
                   1068: #if GEMDOS
                   1069:        if (stat(fn, &sb) < 0)
                   1070:                diag(1, state, fn);
                   1071: #else
                   1072:        fstat(fileno(fp), &sb);
                   1073: #endif
                   1074:        return (sb.st_size);
                   1075: }
                   1076: 
                   1077: /*
                   1078:  * Ranlib stuff.
                   1079:  * If the current archive has HDRNAME as first module,
                   1080:  * then skip it and open rfp for creation of new ranlib header,
                   1081:  * otherwise backup and make a vanilla archive.
                   1082:  * Unless sflag was set as an option,
                   1083:  * in which case make rfp anyway.
                   1084:  * Unless HDRNAME matches the name list and ffp == dfunc,
                   1085:  * in which case make rfp only if sflag was set.
                   1086:  */
                   1087: ropen()
                   1088: {
                   1089:        extern int dfunc();
                   1090:        long loc;
                   1091: 
                   1092:        ranCt = 0;
                   1093:        loc = ftell(afp);
                   1094:        if (geth() != 0) {      /* Must not be end of file */
                   1095:                if (eqh(rnp)) { /* Symbol header */
                   1096:                        seekPast();
                   1097:                        if (ffp == dfunc && match()) {
                   1098:                                if (vflag)
                   1099:                                        amsg("deleted");
                   1100:                        } else
                   1101:                                ++sflag;
                   1102:                } else {
                   1103:                        fseek(afp, loc, 0);
                   1104:                        if (sflag && ffp == dfunc) {
                   1105:                                strcpy(ahb.ar_name, rnp);
                   1106:                                match();
                   1107:                        }
                   1108:                }
                   1109:        }
                   1110:        if (sflag && (rfp = fopen(rnpx, "wb")) == NULL)
                   1111:                diag(1, ccrea, rnpx);
                   1112: }
                   1113: 
                   1114: /*
                   1115:  * Add the symbols in mfp to the ranlib header,
                   1116:  * and seek mfp back to where it began.
                   1117:  * The postion of this module in the archive
                   1118:  * is -sizeof(arhdr) from current position of afp.
                   1119:  */
                   1120: #if PORTAR
                   1121: raddmod(afp, mfp, s)
                   1122: FILE *afp, *mfp;
                   1123: long s;
                   1124: {
                   1125:        FILEHDR  fdh;
                   1126:        SYMENT  sym;
                   1127:        long    off;
                   1128:        long    str_length, aroff, i;
                   1129:        int     len, j, c, aux;
                   1130:        char    *str_tab;
                   1131: 
                   1132:        aroff = ftell(afp) - sizeof(struct ar_hdr);
                   1133:        off   = ftell(mfp);
                   1134:        str_length = fdh.f_magic = 0;
                   1135:        if (1 != fread(&fdh, sizeof(fdh), 1, mfp) ||
                   1136:            (C_386_MAGIC != fdh.f_magic) ||
                   1137:            !fdh.f_nsyms)
                   1138:                goto done;
                   1139: 
                   1140:        i = fdh.f_symptr + (SYMESZ * fdh.f_nsyms);
                   1141:        str_length = 0;
                   1142:        if (!fdh.f_symptr)
                   1143:                goto done;
                   1144:        if (i < s) {    /* make our own eof inside archive */
                   1145:                fseek(mfp, i + off, 0);
                   1146:                if (1 != fread(&str_length, sizeof(str_length), 1, mfp))
                   1147:                        str_length = 0;
                   1148:        }
                   1149:        if (str_length) {
                   1150:                len = str_length -= 4;
                   1151:                if (len != str_length)
                   1152:                        diag(1, "Cannot process %.*s small model",
                   1153:                                DIRSIZ, ahb.ar_name);
                   1154:                if(NULL == (str_tab = malloc(len)))
                   1155:                        diag(1, "out of space %.*s", DIRSIZ, ahb.ar_name);
                   1156:                if (1 != fread(str_tab, len, 1, mfp))
                   1157:                        diag(1, "truncated module %.*s", DIRSIZ, ahb.ar_name);
                   1158:        }
                   1159: 
                   1160:        fseek(mfp, fdh.f_symptr + off, 0);
                   1161: 
                   1162:        for (aux = i = 0; i < fdh.f_nsyms; i++) {
                   1163:                if (1 != fread(&sym, sizeof(sym), 1, mfp))
                   1164:                        diag(1, "truncated module %.*s", DIRSIZ, ahb.ar_name);
                   1165: 
                   1166:                /* bypass aux symbols */
                   1167:                if (aux) {
                   1168:                        aux--;
                   1169:                        continue;
                   1170:                }
                   1171:                aux = sym.n_numaux;
                   1172: 
                   1173:                if (C_EXT != sym.n_sclass ||
                   1174:                    (!sym.n_scnum && !sym.n_value))
                   1175:                        continue;
                   1176: 
                   1177:                fwrite(&aroff, sizeof(aroff), 1, rfp);
                   1178:                ranCt++;
                   1179: 
                   1180:                if (!sym._n._n_n._n_zeroes) {
                   1181:                        fputs(str_tab + sym._n._n_n._n_offset - 4, rfp);
                   1182:                        fputc(0, rfp);
                   1183:                        continue;
                   1184:                }
                   1185:                for (j = 0; (j < SYMNMLEN) && (c = sym._n._n_name[j]); j++)
                   1186:                        fputc(c, rfp);
                   1187:                fputc(0, rfp);
                   1188:        }
                   1189:        if (str_length)
                   1190:                free(str_tab);
                   1191: done:
                   1192:        fseek(mfp, off, 0);
                   1193: }
                   1194: 
                   1195: /*
                   1196:  * Reverse byte order on 386s
                   1197:  */
                   1198: flipwrite(x)
                   1199: unsigned long x;
                   1200: {
                   1201: #ifdef GEMDOS
                   1202:        if (1 != fwrite(&x, sizeof(x), 1, afp))
                   1203:                ioerr(anp);
                   1204: #else
                   1205:        union full {
                   1206:                unsigned char uc[4];
                   1207:                unsigned long ul;
                   1208:        } l;
                   1209:        unsigned char c;
                   1210: 
                   1211:        l.ul = x;       
                   1212:        c = l.uc[0]; l.uc[0] = l.uc[3]; l.uc[3] = c;
                   1213:        c = l.uc[1]; l.uc[1] = l.uc[2]; l.uc[2] = c;
                   1214: 
                   1215:        if (1 != fwrite(&l, sizeof(x), 1, afp))
                   1216:                ioerr(anp);
                   1217: #endif
                   1218: }
                   1219: 
                   1220: /*
                   1221:  * Copy the ranlib header to the output archive.
                   1222:  * Close and null the ranlib file pointer
                   1223:  */
                   1224: rcopy()
                   1225: {
                   1226:        register FILE *fp;
                   1227:        int c, pad;
                   1228:        long i, x, ranLen;
                   1229: 
                   1230:        ranLen = ftell(rfp); /* we are at the end */
                   1231:        fclose(rfp);
                   1232:        rfp = NULL;
                   1233: 
                   1234:        fp = makeh(rnpx);
                   1235:        pad = ranLen & 1;
                   1236:        ahb.ar_size = ranLen += pad + sizeof(ranCt);
                   1237: 
                   1238:        time(&ahb.ar_date);
                   1239:        ahb.ar_date += (long)(10*365+3)*24*60*60;
                   1240: 
                   1241:        puth(afp, anp);
                   1242:        tfp = NULL;
                   1243:        flipwrite(ranCt);
                   1244:        ranLen += sizeof(struct ar_hdr);
                   1245: 
                   1246:        for (i = 0; i < ranCt; i++) {
                   1247:                if (1 != fread(&x, sizeof(x), 1, fp))
                   1248:                        ioerr(rnpx);
                   1249:                flipwrite(x + ranLen);
                   1250:                while(fgetc(fp))
                   1251:                        ;
                   1252:        }
                   1253: 
                   1254:        fseek (fp, 0L, 0);
                   1255:        for (i = 0; i < ranCt; i++) {
                   1256:                if (1 != fread(&x, sizeof(x), 1, fp))
                   1257:                        ioerr(rnpx);
                   1258:                while (c = fgetc(fp))
                   1259:                        fputc(c, afp);
                   1260:                fputc(0, afp);
                   1261:        }
                   1262:        if (pad)
                   1263:                fputc(0, afp);
                   1264:        
                   1265:        fclose(fp);
                   1266:        unlink(rnpx);
                   1267: }
                   1268: #else
                   1269: struct ldheader ldh;
                   1270: struct ldsym lds;
                   1271: struct ar_sym ars;
                   1272: 
                   1273: xwrite()
                   1274: {
                   1275:        if (fwrite(lds.ls_id, sizeof(lds.ls_id), 1, rfp) != 1
                   1276:         || fwrite(&ars.ar_off, sizeof(ars.ar_off), 1, rfp) != 1)
                   1277:                ioerr(rnpx);
                   1278: }
                   1279: 
                   1280: xread(fp) register FILE *fp;
                   1281: {
                   1282:        register int r;
                   1283:        union { long l; unsigned u[2]; } u;
                   1284: 
                   1285:        if ((ldh.l_flag & LF_32) == 0) {
                   1286:                r = fread(&lds, sizeof(lds)-sizeof(short), 1, fp);
                   1287:                u.l = lds.ls_addr;
                   1288:                canshort(u.u[0]);
                   1289:                lds.ls_addr = u.u[0];
                   1290:        } else {
                   1291:                r = fread(&lds, sizeof(lds), 1, fp);
                   1292:                canlong(lds.ls_addr);
                   1293:        }
                   1294:        canshort(lds.ls_type);
                   1295:        return (r);
                   1296: }
                   1297: 
                   1298: raddmod(afp, mfp) FILE *afp, *mfp;
                   1299: {
                   1300:        fsize_t off, offset;
                   1301:        int     seg, nsym;
                   1302: 
                   1303:        ars.ar_off = ftell(afp) - sizeof(ahb) - SARMAG;
                   1304:        cansize(ars.ar_off);
                   1305:        off = ftell(mfp);
                   1306:        ldh.l_magic = 0;        /* in case fread fails */
                   1307:        if (fread(&ldh, sizeof ldh, 1, mfp) != 1)
                   1308:                goto done;
                   1309:        canshort(ldh.l_magic);
                   1310:        if (ldh.l_magic != L_MAGIC)
                   1311:                goto done;
                   1312:        canshort(ldh.l_flag);
                   1313:        if ((ldh.l_flag & LF_32) == 0)
                   1314:                ldh.l_tbase = sizeof(ldh) - 2*sizeof(short);
                   1315:        else
                   1316:                canshort(ldh.l_tbase);
                   1317:        offset = ldh.l_tbase - (fsize_t)sizeof(ldh);
                   1318:        for (seg=0; seg<L_SYM; seg++) {
                   1319:                if (seg==L_BSSI || seg==L_BSSD)
                   1320:                        continue;
                   1321:                cansize(ldh.l_ssize[seg]);
                   1322:                offset += ldh.l_ssize[seg];
                   1323:        }
                   1324:        fseek(mfp, offset, 1);
                   1325:        cansize(ldh.l_ssize[L_SYM]);
                   1326:        if ((ldh.l_flag & LF_32) == 0)
                   1327:                nsym = ldh.l_ssize[L_SYM]
                   1328:                    / (sizeof(struct ldsym) - sizeof(short));
                   1329:        else
                   1330:                nsym = ldh.l_ssize[L_SYM]/sizeof(struct ldsym);
                   1331:        while (nsym--) {
                   1332:                if (xread(mfp) == 0)
                   1333:                        diag(1, "truncated module %.*s", DIRSIZ, ahb.ar_name);
                   1334:                if ((lds.ls_type&L_GLOBAL) == 0)
                   1335:                        continue;
                   1336:                if ((lds.ls_type&LR_SEG) != L_REF)
                   1337:                        xwrite();
                   1338:        }
                   1339: done:
                   1340:        fseek(mfp, off, 0);     /* back to beginning of module */
                   1341: }
                   1342: 
                   1343: /*
                   1344:  * Copy the ranlib header to the output archive
                   1345:  * close and null the ranlib file pointer.
                   1346:  */
                   1347: rcopy()
                   1348: {
                   1349:        register FILE *fp;
                   1350:        fclose(rfp);
                   1351:        rfp = NULL;
                   1352:        fp = makeh(rnpx);
                   1353:        time(&ahb.ar_date);
                   1354:        ahb.ar_date += (long)(10*365+3)*24*60*60;
                   1355:        puth(afp, anp);
                   1356:        tfp = NULL;
                   1357:        ffcopy(afp, anp, fp, rnpx, fsize(fp, rnpx));
                   1358:        fclose(fp);
                   1359:        unlink(rnpx);
                   1360: }
                   1361: #endif
                   1362: 
                   1363: /* end of ar.c */

unix.superglobalmegacorp.com

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