Annotation of coherent/e/bin/pax/list.c, revision 1.1.1.1

1.1       root        1: /* $Source: /src386/usr/bin/pax/list.c,v $
                      2:  *
                      3:  * $Revision: 1.1 $
                      4:  *
                      5:  * list.c - List all files on an archive
                      6:  *
                      7:  * DESCRIPTION
                      8:  *
                      9:  *     These function are needed to support archive table of contents and
                     10:  *     verbose mode during extraction and creation of achives.
                     11:  *
                     12:  * AUTHOR
                     13:  *
                     14:  *     Mark H. Colburn, NAPS International ([email protected])
                     15:  *
                     16:  * Sponsored by The USENIX Association for public distribution. 
                     17:  *
                     18:  * Copyright (c) 1989 Mark H. Colburn.
                     19:  * All rights reserved.
                     20:  *
                     21:  * Redistribution and use in source and binary forms are permitted
                     22:  * provided that the above copyright notice is duplicated in all such 
                     23:  * forms and that any documentation, advertising materials, and other 
                     24:  * materials related to such distribution and use acknowledge that the 
                     25:  * software was developed * by Mark H. Colburn and sponsored by The 
                     26:  * USENIX Association. 
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     29:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     30:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     31:  *
                     32:  * $Log:       list.c,v $
                     33:  * Revision 1.1  92/08/28  08:02:15  bin
                     34:  * Initial revision
                     35:  * 
                     36:  * Revision 1.1  89/02/14  16:47:59  jep
                     37:  * Initial revision
                     38:  * 
                     39:  * Revision 1.1  88/12/23  18:02:14  mark
                     40:  * Initial revision
                     41:  * 
                     42:  */
                     43: 
                     44: #ifndef lint
                     45: static char *ident = "$Id: list.c,v 1.1 92/08/28 08:02:15 bin Exp Locker: bin $";
                     46: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                     47: #endif /* ! lint */
                     48: 
                     49: 
                     50: /* Headers */
                     51: 
                     52: #include "pax.h"
                     53: 
                     54: 
                     55: /* Defines */
                     56: 
                     57: /*
                     58:  * isodigit returns non zero iff argument is an octal digit, zero otherwise
                     59:  */
                     60: #define        ISODIGIT(c)     (((c) >= '0') && ((c) <= '7'))
                     61: 
                     62: 
                     63: /* Function Prototypes */
                     64: 
                     65: #if __STDC__
                     66: 
                     67: static void cpio_entry(char *, Stat *);
                     68: static void tar_entry(char *, Stat *);
                     69: static void pax_entry(char *, Stat *);
                     70: static void print_mode(ushort);
                     71: static long from_oct(int digs, char *where);
                     72: 
                     73: #else /* !__STDC__ */
                     74: 
                     75: static void cpio_entry();
                     76: static void tar_entry();
                     77: static void pax_entry();
                     78: static void print_mode();
                     79: static long from_oct();
                     80: 
                     81: #endif /* __STDC__ */
                     82: 
                     83: 
                     84: /* Internal Identifiers */
                     85: 
                     86: static char       *monnames[] = {
                     87:     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                     88:     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
                     89: };
                     90: 
                     91: 
                     92: /* read_header - read a header record
                     93:  *
                     94:  * DESCRIPTION
                     95:  *
                     96:  *     Read a record that's supposed to be a header record. Return its 
                     97:  *     address in "head", and if it is good, the file's size in 
                     98:  *     asb->sb_size.  Decode things from a file header record into a "Stat". 
                     99:  *     Also set "head_standard" to !=0 or ==0 depending whether header record 
                    100:  *     is "Unix Standard" tar format or regular old tar format. 
                    101:  *
                    102:  * PARAMETERS
                    103:  *
                    104:  *     char   *name            - pointer which will contain name of file
                    105:  *     Stat   *asb             - pointer which will contain stat info
                    106:  *
                    107:  * RETURNS
                    108:  *
                    109:  *     Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a 
                    110:  *     record full of zeros (EOF marker). 
                    111:  */
                    112: 
                    113: #if __STDC__
                    114: 
                    115: int read_header(char *name, Stat *asb)
                    116: 
                    117: #else
                    118:     
                    119: int read_header(name, asb)
                    120: char           *name;
                    121: Stat           *asb;
                    122: 
                    123: #endif
                    124: {
                    125:     int             i;
                    126:     long            sum;
                    127:     long           recsum;
                    128:     Link           *link;
                    129:     char           *p;
                    130:     char            hdrbuf[BLOCKSIZE];
                    131: 
                    132:     memset((char *)asb, 0, sizeof(Stat));
                    133:     /* read the header from the buffer */
                    134:     if (buf_read(hdrbuf, BLOCKSIZE) != 0) {
                    135:        return (EOF);
                    136:     }
                    137: 
                    138:     strcpy(name, hdrbuf);
                    139: 
                    140:     recsum = from_oct(8, &hdrbuf[148]);
                    141:     sum = 0;
                    142:     p = hdrbuf;
                    143:     for (i = 0 ; i < 500; i++) {
                    144: 
                    145:        /*
                    146:         * We can't use unsigned char here because of old compilers, e.g. V7. 
                    147:         */
                    148:        sum += 0xFF & *p++;
                    149:     }
                    150: 
                    151:     /* Adjust checksum to count the "chksum" field as blanks. */
                    152:     for (i = 0; i < 8; i++) {
                    153:        sum -= 0xFF & hdrbuf[148 + i];
                    154:     }
                    155:     sum += ' ' * 8;
                    156: 
                    157:     if (sum == 8 * ' ') {
                    158: 
                    159:        /*
                    160:         * This is a zeroed record...whole record is 0's except for the 8
                    161:         * blanks we faked for the checksum field. 
                    162:         */
                    163:        return (2);
                    164:     }
                    165:     if (sum == recsum) {
                    166:        /*
                    167:         * Good record.  Decode file size and return. 
                    168:         */
                    169:        if (hdrbuf[156] != LNKTYPE) {
                    170:            asb->sb_size = from_oct(1 + 12, &hdrbuf[124]);
                    171:        }
                    172:        asb->sb_mtime = from_oct(1 + 12, &hdrbuf[136]);
                    173:        asb->sb_mode = from_oct(8, &hdrbuf[100]);
                    174: 
                    175:        if (strcmp(&hdrbuf[257], TMAGIC) == 0) {
                    176:            /* Unix Standard tar archive */
                    177:            head_standard = 1;
                    178: #ifdef NONAMES
                    179:            asb->sb_uid = from_oct(8, &hdrbuf[108]);
                    180:            asb->sb_gid = from_oct(8, &hdrbuf[116]);
                    181: #else
                    182:            asb->sb_uid = finduid(&hdrbuf[265]);
                    183:            asb->sb_gid = findgid(&hdrbuf[297]);
                    184: #endif
                    185:            switch (hdrbuf[156]) {
                    186:            case BLKTYPE:
                    187:            case CHRTYPE:
                    188:                asb->sb_rdev = makedev(from_oct(8, &hdrbuf[329]),
                    189:                                      from_oct(8, &hdrbuf[337]));
                    190:                break;
                    191:            default:
                    192:                /* do nothing... */
                    193:                break;
                    194:            }
                    195:        } else {
                    196:            /* Old fashioned tar archive */
                    197:            head_standard = 0;
                    198:            asb->sb_uid = from_oct(8, &hdrbuf[108]);
                    199:            asb->sb_gid = from_oct(8, &hdrbuf[116]);
                    200:        }
                    201: 
                    202:        switch (hdrbuf[156]) {
                    203:        case REGTYPE:
                    204:        case AREGTYPE:
                    205:            /*
                    206:             * Berkeley tar stores directories as regular files with a
                    207:             * trailing /
                    208:             */
                    209:            if (name[strlen(name) - 1] == '/') {
                    210:                name[strlen(name) - 1] = '\0';
                    211:                asb->sb_mode |= S_IFDIR;
                    212:            } else {
                    213:                asb->sb_mode |= S_IFREG;
                    214:            }
                    215:            break;
                    216:        case LNKTYPE:
                    217:            asb->sb_nlink = 2;
                    218:            linkto(&hdrbuf[157], asb);
                    219:            linkto(name, asb);
                    220:            asb->sb_mode |= S_IFREG;
                    221:            break;
                    222:        case BLKTYPE:
                    223:            asb->sb_mode |= S_IFBLK;
                    224:            break;
                    225:        case CHRTYPE:
                    226:            asb->sb_mode |= S_IFCHR;
                    227:            break;
                    228:        case DIRTYPE:
                    229:            asb->sb_mode |= S_IFDIR;
                    230:            break;
                    231: #ifdef S_IFLNK
                    232:        case SYMTYPE:
                    233:            asb->sb_mode |= S_IFLNK;
                    234:            strcpy(asb->sb_link, &hdrbuf[157]);
                    235:            break;
                    236: #endif
                    237: #ifdef S_IFIFO
                    238:        case FIFOTYPE:
                    239:            asb->sb_mode |= S_IFIFO;
                    240:            break;
                    241: #endif
                    242: #ifdef S_IFCTG
                    243:        case CONTTYPE:
                    244:            asb->sb_mode |= S_IFCTG;
                    245:            break;
                    246: #endif
                    247:        }
                    248:        return (1);
                    249:     }
                    250:     return (0);
                    251: }
                    252: 
                    253: 
                    254: /* print_entry - print a single table-of-contents entry
                    255:  *
                    256:  * DESCRIPTION
                    257:  * 
                    258:  *     Print_entry prints a single line of file information.  The format
                    259:  *     of the line is the same as that used by the LS command.  For some
                    260:  *     archive formats, various fields may not make any sense, such as
                    261:  *     the link count on tar archives.  No error checking is done for bad
                    262:  *     or invalid data.
                    263:  *
                    264:  * PARAMETERS
                    265:  *
                    266:  *     char   *name            - pointer to name to print an entry for
                    267:  *     Stat   *asb             - pointer to the stat structure for the file
                    268:  */
                    269: 
                    270: #if __STDC__
                    271: 
                    272: void print_entry(char *name, Stat *asb)
                    273: 
                    274: #else
                    275:     
                    276: void print_entry(name, asb)
                    277: char           *name;
                    278: Stat           *asb;
                    279: 
                    280: #endif
                    281: {
                    282:     switch (ar_interface) {
                    283:     case TAR:
                    284:        tar_entry(name, asb);
                    285:        break;
                    286:     case CPIO:
                    287:        cpio_entry(name, asb);
                    288:        break;
                    289:     case PAX: pax_entry(name, asb);
                    290:        break;
                    291:     }
                    292: }
                    293: 
                    294: 
                    295: /* cpio_entry - print a verbose cpio-style entry
                    296:  *
                    297:  * DESCRIPTION
                    298:  *
                    299:  *     Print_entry prints a single line of file information.  The format
                    300:  *     of the line is the same as that used by the traditional cpio 
                    301:  *     command.  No error checking is done for bad or invalid data.
                    302:  *
                    303:  * PARAMETERS
                    304:  *
                    305:  *     char   *name            - pointer to name to print an entry for
                    306:  *     Stat   *asb             - pointer to the stat structure for the file
                    307:  */
                    308: 
                    309: #if __STDC__
                    310: 
                    311: static void cpio_entry(char *name, Stat *asb)
                    312: 
                    313: #else
                    314:     
                    315: static void cpio_entry(name, asb)
                    316: char          *name;
                    317: Stat          *asb;
                    318: 
                    319: #endif
                    320: {
                    321:     struct tm         *atm;
                    322:     Link              *from;
                    323:     struct passwd      *pwp;
                    324:     struct group       *grp;
                    325: 
                    326:     if (f_list && f_verbose) {
                    327:        fprintf(msgfile, "%-7o", asb->sb_mode);
                    328:        atm = localtime(&asb->sb_mtime);
                    329:        if (pwp = getpwuid((int) USH(asb->sb_uid))) {
                    330:            fprintf(msgfile, "%-6s", pwp->pw_name);
                    331:        } else {
                    332:            fprintf(msgfile, "%-6u", USH(asb->sb_uid));
                    333:        }
                    334:        fprintf(msgfile,"%7ld  %3s %2d %02d:%02d:%02d %4d  ",
                    335:                       asb->sb_size, monnames[atm->tm_mon], 
                    336:                       atm->tm_mday, atm->tm_hour, atm->tm_min, 
                    337:                       atm->tm_sec, atm->tm_year + 1900);
                    338:     }
                    339:     fprintf(msgfile, "%s", name);
                    340:     if ((asb->sb_nlink > 1) && (from = islink(name, asb))) {
                    341:        fprintf(msgfile, " linked to %s", from->l_name);
                    342:     }
                    343: #ifdef S_IFLNK
                    344:     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
                    345:        fprintf(msgfile, " symbolic link to %s", asb->sb_link);
                    346:     }
                    347: #endif /* S_IFLNK */
                    348:     putc('\n', msgfile);
                    349: }
                    350: 
                    351: 
                    352: /* tar_entry - print a tar verbose mode entry
                    353:  *
                    354:  * DESCRIPTION
                    355:  *
                    356:  *     Print_entry prints a single line of tar file information.  The format
                    357:  *     of the line is the same as that produced by the traditional tar 
                    358:  *     command.  No error checking is done for bad or invalid data.
                    359:  *
                    360:  * PARAMETERS
                    361:  *
                    362:  *     char   *name            - pointer to name to print an entry for
                    363:  *     Stat   *asb             - pointer to the stat structure for the file
                    364:  */
                    365: 
                    366: #if __STDC__
                    367: 
                    368: static void tar_entry(char *name, Stat *asb)
                    369: 
                    370: #else
                    371:     
                    372: static void tar_entry(name, asb)
                    373: char           *name;
                    374: Stat            *asb;
                    375: 
                    376: #endif
                    377: {
                    378:     struct tm                 *atm;
                    379:     int                        i;
                    380:     int                        mode;
                    381:     char               *symnam = "NULL";
                    382:     Link               *link;
                    383: 
                    384:     if ((mode = asb->sb_mode & S_IFMT) == S_IFDIR) {
                    385:        return;                 /* don't print directories */
                    386:     }
                    387:     if (f_extract) {
                    388:        switch (mode) {
                    389: #ifdef S_IFLNK
                    390:        case S_IFLNK:   /* This file is a symbolic link */
                    391:            i = readlink(name, symnam, PATH_MAX - 1);
                    392:            if (i < 0) {                /* Could not find symbolic link */
                    393:                warn("can't read symbolic link", strerror());
                    394:            } else {            /* Found symbolic link filename */
                    395:                symnam[i] = '\0';
                    396:                fprintf(msgfile, "x %s symbolic link to %s\n", name, symnam);
                    397:            }
                    398:            break;
                    399: #endif
                    400:        case S_IFREG:   /* It is a link or a file */
                    401:            if ((asb->sb_nlink > 1) && (link = islink(name, asb))) {
                    402:                fprintf(msgfile, "%s linked to %s\n", name, link->l_name); 
                    403:            } else {
                    404:                fprintf(msgfile, "x %s, %ld bytes, %d tape blocks\n", 
                    405:                        name, asb->sb_size, ROUNDUP(asb->sb_size, 
                    406:                        BLOCKSIZE) / BLOCKSIZE);
                    407:            }
                    408:        }
                    409:     } else if (f_append || f_create) {
                    410:        switch (mode) {
                    411: #ifdef S_IFLNK
                    412:        case S_IFLNK:   /* This file is a symbolic link */
                    413:            i = readlink(name, symnam, PATH_MAX - 1);
                    414:            if (i < 0) {                /* Could not find symbolic link */
                    415:                warn("can't read symbolic link", strerror());
                    416:            } else {            /* Found symbolic link filename */
                    417:                symnam[i] = '\0';
                    418:                fprintf(msgfile, "a %s symbolic link to %s\n", name, symnam);
                    419:            }
                    420:            break;
                    421: #endif
                    422:        case S_IFREG:   /* It is a link or a file */
                    423:            fprintf(msgfile, "a %s ", name);
                    424:            if ((asb->sb_nlink > 1) && (link = islink(name, asb))) {
                    425:                fprintf(msgfile, "link to %s\n", link->l_name); 
                    426:            } else {
                    427:                fprintf(msgfile, "%ld Blocks\n", 
                    428:                        ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
                    429:            }
                    430:            break;
                    431:        }
                    432:     } else if (f_list) {
                    433:        if (f_verbose) {
                    434:            atm = localtime(&asb->sb_mtime);
                    435:            print_mode(asb->sb_mode);
                    436:            fprintf(msgfile," %d/%d %6d %3s %2d %02d:%02d %4d %s",
                    437:                    asb->sb_uid, asb->sb_gid, asb->sb_size,
                    438:                    monnames[atm->tm_mon], atm->tm_mday, atm->tm_hour, 
                    439:                    atm->tm_min, atm->tm_year + 1900, name);
                    440:        } else {
                    441:            fprintf(msgfile, "%s", name);
                    442:        }
                    443:        switch (mode) {
                    444: #ifdef S_IFLNK
                    445:        case S_IFLNK:   /* This file is a symbolic link */
                    446:            i = readlink(name, symnam, PATH_MAX - 1);
                    447:            if (i < 0) {                /* Could not find symbolic link */
                    448:                warn("can't read symbolic link", strerror());
                    449:            } else {            /* Found symbolic link filename */
                    450:                symnam[i] = '\0';
                    451:                fprintf(msgfile, " symbolic link to %s", symnam);
                    452:            }
                    453:            break;
                    454: #endif
                    455:        case S_IFREG:   /* It is a link or a file */
                    456:            if ((asb->sb_nlink > 1) && (link = islink(name, asb))) {
                    457:                fprintf(msgfile, " linked to %s", link->l_name);
                    458:            }
                    459:            break;              /* Do not print out directories */
                    460:        }
                    461:        fputc('\n', msgfile);
                    462:     } else {
                    463:        fprintf(msgfile, "? %s %ld blocks\n", name,
                    464:                ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
                    465:     }
                    466: }
                    467: 
                    468: 
                    469: /* pax_entry - print a verbose cpio-style entry
                    470:  *
                    471:  * DESCRIPTION
                    472:  *
                    473:  *     Print_entry prints a single line of file information.  The format
                    474:  *     of the line is the same as that used by the LS command.  
                    475:  *     No error checking is done for bad or invalid data.
                    476:  *
                    477:  * PARAMETERS
                    478:  *
                    479:  *     char   *name            - pointer to name to print an entry for
                    480:  *     Stat   *asb             - pointer to the stat structure for the file
                    481:  */
                    482: 
                    483: #if __STDC__
                    484: 
                    485: static void pax_entry(char *name, Stat *asb)
                    486: 
                    487: #else
                    488:     
                    489: static void pax_entry(name, asb)
                    490: char          *name;
                    491: Stat          *asb;
                    492: 
                    493: #endif
                    494: {
                    495:     struct tm         *atm;
                    496:     Link              *from;
                    497:     struct passwd      *pwp;
                    498:     struct group       *grp;
                    499: 
                    500:     if (f_list && f_verbose) {
                    501:        print_mode(asb->sb_mode);
                    502:        fprintf(msgfile, " %2d", asb->sb_nlink);
                    503:        atm = localtime(&asb->sb_mtime);
                    504:        if (pwp = getpwuid((int) USH(asb->sb_uid))) {
                    505:            fprintf(msgfile, " %-8s", pwp->pw_name);
                    506:        } else {
                    507:            fprintf(msgfile, " %-8u", USH(asb->sb_uid));
                    508:        }
                    509:        if (grp = getgrgid((int) USH(asb->sb_gid))) {
                    510:            fprintf(msgfile, " %-8s", grp->gr_name);
                    511:        } else {
                    512:            fprintf(msgfile, " %-8u", USH(asb->sb_gid));
                    513:        }
                    514:        switch (asb->sb_mode & S_IFMT) {
                    515:        case S_IFBLK:
                    516:        case S_IFCHR:
                    517:            fprintf(msgfile, "\t%3d, %3d",
                    518:                           major(asb->sb_rdev), minor(asb->sb_rdev));
                    519:            break;
                    520:        case S_IFREG:
                    521:            fprintf(msgfile, "\t%8ld", asb->sb_size);
                    522:            break;
                    523:        default:
                    524:            fprintf(msgfile, "\t        ");
                    525:        }
                    526:        fprintf(msgfile," %3s %2d %02d:%02d ",
                    527:                monnames[atm->tm_mon], atm->tm_mday, 
                    528:                atm->tm_hour, atm->tm_min);
                    529:     }
                    530:     fprintf(msgfile, "%s", name);
                    531:     if ((asb->sb_nlink > 1) && (from = islink(name, asb))) {
                    532:        fprintf(msgfile, " == %s", from->l_name);
                    533:     }
                    534: #ifdef S_IFLNK
                    535:     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
                    536:        fprintf(msgfile, " -> %s", asb->sb_link);
                    537:     }
                    538: #endif /* S_IFLNK */
                    539:     putc('\n', msgfile);
                    540: }
                    541: 
                    542: 
                    543: /* print_mode - fancy file mode display
                    544:  *
                    545:  * DESCRIPTION
                    546:  *
                    547:  *     Print_mode displays a numeric file mode in the standard unix
                    548:  *     representation, ala ls (-rwxrwxrwx).  No error checking is done
                    549:  *     for bad mode combinations.  FIFOS, sybmbolic links, sticky bits,
                    550:  *     block- and character-special devices are supported if supported
                    551:  *     by the hosting implementation.
                    552:  *
                    553:  * PARAMETERS
                    554:  *
                    555:  *     ushort  mode    - The integer representation of the mode to print.
                    556:  */
                    557: 
                    558: #if __STDC__
                    559: 
                    560: static void print_mode(ushort mode)
                    561: 
                    562: #else
                    563:     
                    564: static void print_mode(mode)
                    565: ushort mode;
                    566: 
                    567: #endif
                    568: {
                    569:     /* Tar does not print the leading identifier... */
                    570:     if (ar_interface != TAR) {
                    571:        switch (mode & S_IFMT) {
                    572:        case S_IFDIR: 
                    573:            putc('d', msgfile); 
                    574:            break;
                    575: #ifdef S_IFLNK
                    576:        case S_IFLNK: 
                    577:            putc('l', msgfile); 
                    578:            break;
                    579: #endif /* S_IFLNK */
                    580:        case S_IFBLK: 
                    581:            putc('b', msgfile); 
                    582:            break;
                    583:        case S_IFCHR: 
                    584:            putc('c', msgfile); 
                    585:            break;
                    586: #ifdef S_IFIFO
                    587:        case S_IFIFO: 
                    588:            putc('p', msgfile); 
                    589:            break; 
                    590: #endif /* S_IFIFO */ 
                    591:        case S_IFREG: 
                    592:        default:
                    593:            putc('-', msgfile); 
                    594:            break;
                    595:        }
                    596:     }
                    597:     putc(mode & 0400 ? 'r' : '-', msgfile);
                    598:     putc(mode & 0200 ? 'w' : '-', msgfile);
                    599:     putc(mode & 0100
                    600:         ? mode & 04000 ? 's' : 'x'
                    601:         : mode & 04000 ? 'S' : '-', msgfile);
                    602:     putc(mode & 0040 ? 'r' : '-', msgfile);
                    603:     putc(mode & 0020 ? 'w' : '-', msgfile);
                    604:     putc(mode & 0010
                    605:         ? mode & 02000 ? 's' : 'x'
                    606:         : mode & 02000 ? 'S' : '-', msgfile);
                    607:     putc(mode & 0004 ? 'r' : '-', msgfile);
                    608:     putc(mode & 0002 ? 'w' : '-', msgfile);
                    609:     putc(mode & 0001
                    610:         ? mode & 01000 ? 't' : 'x'
                    611:         : mode & 01000 ? 'T' : '-', msgfile);
                    612: }
                    613: 
                    614: 
                    615: /* from_oct - quick and dirty octal conversion
                    616:  *
                    617:  * DESCRIPTION
                    618:  *
                    619:  *     From_oct will convert an ASCII representation of an octal number
                    620:  *     to the numeric representation.  The number of characters to convert
                    621:  *     is given by the parameter "digs".  If there are less numbers than
                    622:  *     specified by "digs", then the routine returns -1.
                    623:  *
                    624:  * PARAMETERS
                    625:  *
                    626:  *     int digs        - Number to of digits to convert 
                    627:  *     char *where     - Character representation of octal number
                    628:  *
                    629:  * RETURNS
                    630:  *
                    631:  *     The value of the octal number represented by the first digs
                    632:  *     characters of the string where.  Result is -1 if the field 
                    633:  *     is invalid (all blank, or nonoctal). 
                    634:  *
                    635:  * ERRORS
                    636:  *
                    637:  *     If the field is all blank, then the value returned is -1.
                    638:  *
                    639:  */
                    640: 
                    641: #if __STDC__
                    642: 
                    643: static long from_oct(int digs, char *where)
                    644: 
                    645: #else
                    646: 
                    647: static long from_oct(digs, where)
                    648: int             digs;          /* number of characters to convert */
                    649: char           *where;         /* character representation of octal number */
                    650: 
                    651: #endif
                    652: {
                    653:     long            value;
                    654: 
                    655:     while (isspace(*where)) {  /* Skip spaces */
                    656:        where++;
                    657:        if (--digs <= 0) {
                    658:            return(-1);         /* All blank field */
                    659:        }
                    660:     }
                    661:     value = 0;
                    662:     while (digs > 0 && ISODIGIT(*where)) {     /* Scan til nonoctal */
                    663:        value = (value << 3) | (*where++ - '0');
                    664:        --digs;
                    665:     }
                    666: 
                    667:     if (digs > 0 && *where && !isspace(*where)) {
                    668:        return(-1);             /* Ended on non-space/nul */
                    669:     }
                    670:     return(value);
                    671: }

unix.superglobalmegacorp.com

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