home *** CD-ROM | disk | FTP | other *** search
- /* $Source: /u/mark/src/pax/RCS/list.c,v $
- *
- * $Revision: 1.2 $
- *
- * list.c - List all files on an archive
- *
- * DESCRIPTION
- *
- * These function are needed to support archive table of contents and
- * verbose mode during extraction and creation of achives.
- *
- * AUTHOR
- *
- * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- *
- * Sponsored by The USENIX Association for public distribution.
- *
- * Copyright (c) 1989 Mark H. Colburn.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice is duplicated in all such
- * forms and that any documentation, advertising materials, and other
- * materials related to such distribution and use acknowledge that the
- * software was developed * by Mark H. Colburn and sponsored by The
- * USENIX Association.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Log: list.c,v $
- * Revision 1.2 89/02/12 10:04:43 mark
- * 1.2 release fixes
- *
- * Revision 1.1 88/12/23 18:02:14 mark
- * Initial revision
- *
- */
-
- #ifndef lint
- static char *ident = "$Id: list.c,v 1.2 89/02/12 10:04:43 mark Exp $";
- static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
- #endif /* ! lint */
-
-
- /* Headers */
-
- #include "pax.h"
-
-
- /* Defines */
-
- /*
- * isodigit returns non zero iff argument is an octal digit, zero otherwise
- */
- #define ISODIGIT(c) (((c) >= '0') && ((c) <= '7'))
-
-
- /* Function Prototypes */
-
- #ifdef __STDC__
-
- static void cpio_entry(char *, Stat *);
- static void tar_entry(char *, Stat *);
- static void pax_entry(char *, Stat *);
- #ifdef _POSIX_SOURCE /* Xn */
- static void print_mode(mode_t); /* Xn */
- #else /* Xn */
- static void print_mode(ushort);
- #endif /* Xn */
- static long from_oct(int digs, char *where);
-
- #else /* !__STDC__ */
-
- static void cpio_entry();
- static void tar_entry();
- static void pax_entry();
- static void print_mode();
- static long from_oct();
-
- #endif /* __STDC__ */
-
-
- /* Internal Identifiers */
-
- static char *monnames[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
-
- /* read_header - read a header record
- *
- * DESCRIPTION
- *
- * Read a record that's supposed to be a header record. Return its
- * address in "head", and if it is good, the file's size in
- * asb->sb_size. Decode things from a file header record into a "Stat".
- * Also set "head_standard" to !=0 or ==0 depending whether header record
- * is "Unix Standard" tar format or regular old tar format.
- *
- * PARAMETERS
- *
- * char *name - pointer which will contain name of file
- * Stat *asb - pointer which will contain stat info
- *
- * RETURNS
- *
- * Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
- * record full of zeros (EOF marker).
- */
-
- #ifdef __STDC__
-
- int read_header(char *name, Stat *asb)
-
- #else
-
- int read_header(name, asb)
- char *name;
- Stat *asb;
-
- #endif
- {
- int i;
- long sum;
- long recsum;
- #if 0 /* Xn */
- Link *link;
- #endif /* Xn */
- char *p;
- char hdrbuf[BLOCKSIZE];
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: int read_header() in list.c\n");
- #endif
- memset((char *)asb, 0, sizeof(Stat));
- /* read the header from the buffer */
- #if 0
- (void) fprintf(stderr, "list.c/read_header - before buf_read\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- if (buf_read(hdrbuf, BLOCKSIZE) != 0) {
- return (EOF);
- }
- #if 0
- (void) fprintf(stderr, "list.c/read_header - after buf_read\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
-
- #if 0 && WIN_NT
- /*
- XXX.mjb: this code doesn't seem to handle filename which are
- not null-terminated.
- */
- #endif
-
- if ('\0' == hdrbuf[345]) {
- strcpy(name, &hdrbuf[0]);
- } else {
- strcpy(name, &hdrbuf[345]);
- strcat(name, "/");
- strcat(name, &hdrbuf[0]);
- }
-
-
- recsum = from_oct(8, &hdrbuf[148]);
- sum = 0;
- p = hdrbuf;
- for (i = 0 ; i < 500; i++) {
-
- /*
- * We can't use unsigned char here because of old compilers, e.g. V7.
- */
- sum += 0xFF & *p++;
- }
-
- /* Adjust checksum to count the "chksum" field as blanks. */
- for (i = 0; i < 8; i++) {
- sum -= 0xFF & hdrbuf[148 + i];
- }
- sum += ' ' * 8;
-
- if (sum == 8 * ' ') {
-
- /*
- * This is a zeroed record...whole record is 0's except for the 8
- * blanks we faked for the checksum field.
- */
- #if 0
- (void) fprintf(stderr, "list.c/read_header - returning 2\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- return (2);
- }
- if (sum == recsum) {
- /*
- * Good record. Decode file size and return.
- */
- #if 0
- (void) fprintf(stderr, "list.c/read_header - entering sum == recsum\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- if (hdrbuf[156] != LNKTYPE) {
- asb->sb_size = from_oct(1 + 12, &hdrbuf[124]);
- }
- asb->sb_mtime = from_oct(1 + 12, &hdrbuf[136]);
- asb->sb_mode = (from_oct(8, &hdrbuf[100]) & 0777);
-
- #if 0
- (void) fprintf(stderr, "list.c/read_header - before TMAGIC\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- if (strcmp(&hdrbuf[257], TMAGIC) == 0) {
- /* Unix Standard tar archive */
- #if 0
- (void) fprintf(stderr, "list.c/read_header - strcmp match\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- head_standard = 1;
- #ifdef NONAMES
- asb->sb_uid = from_oct(8, &hdrbuf[108]);
- asb->sb_gid = from_oct(8, &hdrbuf[116]);
- #else
- #if 0
- (void) fprintf(stderr, "list.c/read_header - before finduid\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- asb->sb_uid = finduid(&hdrbuf[265]);
- #if 0
- (void) fprintf(stderr, "list.c/read_header - after finduid; before findgid\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- asb->sb_gid = findgid(&hdrbuf[297]);
- #if 0
- (void) fprintf(stderr, "list.c/read_header - after findgid\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- #endif
- #if 0
- (void) fprintf(stderr, "list.c/read_header - before subswitch; hdrbuf[156]: '%c'\n", hdrbuf[156]);
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- switch (hdrbuf[156]) {
- case BLKTYPE:
- case CHRTYPE:
- #ifndef _POSIX_SOURCE
- asb->sb_rdev = makedev(from_oct(8, &hdrbuf[329]),
- from_oct(8, &hdrbuf[337]));
- #endif
- break;
- default:
- /* do nothing... */
- break;
- }
- #if 0
- (void) fprintf(stderr, "list.c/read_header - after subswitch\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- } else {
- /* Old fashioned tar archive */
- #if 0
- (void) fprintf(stderr, "list.c/read_header - strcmp mismatch\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- head_standard = 0;
- asb->sb_uid = from_oct(8, &hdrbuf[108]);
- asb->sb_gid = from_oct(8, &hdrbuf[116]);
- }
- #if 0
- (void) fprintf(stderr, "list.c/read_header - after TMAGIC; before switch\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
-
- switch (hdrbuf[156]) {
- case REGTYPE:
- case AREGTYPE:
- /*
- * Berkeley tar stores directories as regular files with a
- * trailing /
- */
- if (name[strlen(name) - 1] == '/') {
- name[strlen(name) - 1] = '\0';
- asb->sb_mode |= S_IFDIR;
- } else {
- asb->sb_mode |= S_IFREG;
- }
- break;
- case LNKTYPE:
- asb->sb_nlink = 2;
- linkto(&hdrbuf[157], asb);
- linkto(name, asb);
- asb->sb_mode |= S_IFREG;
- break;
- case BLKTYPE:
- asb->sb_mode |= S_IFBLK;
- break;
- case CHRTYPE:
- asb->sb_mode |= S_IFCHR;
- break;
- case DIRTYPE:
- asb->sb_mode |= S_IFDIR;
- break;
- #ifdef S_IFLNK
- case SYMTYPE:
- asb->sb_mode |= S_IFLNK;
- strcpy(asb->sb_link, &hdrbuf[157]);
- break;
- #endif
- #ifdef S_IFIFO
- case FIFOTYPE:
- asb->sb_mode |= S_IFIFO;
- break;
- #endif
- #ifdef S_IFCTG
- case CONTTYPE:
- asb->sb_mode |= S_IFCTG;
- break;
- #endif
- #ifdef S_IFSOCK /* Xn */
- case SOCKTYPE: /* Xn */
- asb->sb_mode |= S_IFSOCK; /* Xn */
- break; /* Xn */
- #endif /* Xn */
- }
- #if 0
- (void) fprintf(stderr, "list.c/read_header - exiting sum == recsum\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- return (1);
- }
- #if 0
- (void) fprintf(stderr, "list.c/read_header - sum != recsum\n");
- (void) fflush(stderr);
- #endif /* Xn 1993-06-22 */
- return (0);
- }
-
-
- /* print_entry - print a single table-of-contents entry
- *
- * DESCRIPTION
- *
- * Print_entry prints a single line of file information. The format
- * of the line is the same as that used by the LS command. For some
- * archive formats, various fields may not make any sense, such as
- * the link count on tar archives. No error checking is done for bad
- * or invalid data.
- *
- * PARAMETERS
- *
- * char *name - pointer to name to print an entry for
- * Stat *asb - pointer to the stat structure for the file
- */
-
- #ifdef __STDC__
-
- void print_entry(char *name, Stat *asb)
-
- #else
-
- void print_entry(name, asb)
- char *name;
- Stat *asb;
-
- #endif
- {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: void print_entry() in list.c\n");
- #endif
- switch (ar_interface) {
- case TAR:
- tar_entry(name, asb);
- break;
- case CPIO:
- cpio_entry(name, asb);
- break;
- case PAX:
- pax_entry(name, asb);
- break;
- }
- }
-
-
- /* cpio_entry - print a verbose cpio-style entry
- *
- * DESCRIPTION
- *
- * Print_entry prints a single line of file information. The format
- * of the line is the same as that used by the traditional cpio
- * command. No error checking is done for bad or invalid data.
- *
- * PARAMETERS
- *
- * char *name - pointer to name to print an entry for
- * Stat *asb - pointer to the stat structure for the file
- */
-
- #ifdef __STDC__
-
- static void cpio_entry(char *name, Stat *asb)
-
- #else
-
- static void cpio_entry(name, asb)
- char *name;
- Stat *asb;
-
- #endif
- {
- struct tm *atm;
- Link *from;
- struct passwd *pwp;
- #if 0 /* Xn */
- struct group *grp;
- #endif /* Xn */
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static void cpio_entry() in list.c\n");
- #endif
- if (f_list && f_verbose) {
- fprintf(msgfile, "%-7o", asb->sb_mode);
- atm = localtime(&asb->sb_mtime);
- if ((pwp = getpwuid((int) USH(asb->sb_uid))) != NULL) { /* Xn */
- fprintf(msgfile, "%-6s", pwp->pw_name);
- } else {
- fprintf(msgfile, "%-6u", USH(asb->sb_uid));
- }
- fprintf(msgfile,"%7ld %3s %2d %02d:%02d:%02d %4d ",
- asb->sb_size, monnames[atm->tm_mon],
- atm->tm_mday, atm->tm_hour, atm->tm_min,
- atm->tm_sec, atm->tm_year + 1900);
- }
- fprintf(msgfile, "%s", name);
- if ((asb->sb_nlink > 1) && ((from = islink(name, asb))) != NULL) { /* Xn */
- fprintf(msgfile, " linked to %s", from->l_name);
- }
- #ifdef S_IFLNK
- if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
- fprintf(msgfile, " symbolic link to %s", asb->sb_link);
- }
- #endif /* S_IFLNK */
- putc('\n', msgfile);
- }
-
-
- /* tar_entry - print a tar verbose mode entry
- *
- * DESCRIPTION
- *
- * Print_entry prints a single line of tar file information. The format
- * of the line is the same as that produced by the traditional tar
- * command. No error checking is done for bad or invalid data.
- *
- * PARAMETERS
- *
- * char *name - pointer to name to print an entry for
- * Stat *asb - pointer to the stat structure for the file
- */
-
- #ifdef __STDC__
-
- static void tar_entry(char *name, Stat *asb)
-
- #else
-
- static void tar_entry(name, asb)
- char *name;
- Stat *asb;
-
- #endif
- {
- struct tm *atm;
- #ifdef S_IFLNK /* Xn */
- int i;
- #endif /* Xn */
- #ifdef _POSIX_SOURCE /* Xn */
- mode_t mode; /* Xn */
- #else /* Xn */
- int mode;
- #endif /* Xn */
- char *symnam = "NULL";
- Link *link;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static void tar_entry() in list.c\n");
- #endif
- if ((mode = asb->sb_mode & S_IFMT) == S_IFDIR) {
- return; /* don't print directories */
- }
- if (f_extract) {
- switch (mode) {
- #ifdef S_IFLNK
- case S_IFLNK: /* This file is a symbolic link */
- i = readlink(name, symnam, PATH_MAX - 1);
- if (i < 0) { /* Could not find symbolic link */
- warn("can't read symbolic link", strerror(errno)); /* Xn */
- } else { /* Found symbolic link filename */
- symnam[i] = '\0';
- fprintf(msgfile, "x %s symbolic link to %s\n", name, symnam);
- }
- break;
- #endif
- case S_IFREG: /* It is a link or a file */
- if ((asb->sb_nlink > 1) && ((link = islink(name, asb)) != NULL)) { /* Xn */
- fprintf(msgfile, "%s linked to %s\n", name, link->l_name);
- } else {
- fprintf(msgfile, "x %s, %ld bytes, %d tape blocks\n",
- name, asb->sb_size, ROUNDUP(asb->sb_size,
- BLOCKSIZE) / BLOCKSIZE);
- }
- }
- } else if (f_append || f_create) {
- switch (mode) {
- #ifdef S_IFLNK
- case S_IFLNK: /* This file is a symbolic link */
- i = readlink(name, symnam, PATH_MAX - 1);
- if (i < 0) { /* Could not find symbolic link */
- warn("can't read symbolic link", strerror(errno)); /* Xn */
- } else { /* Found symbolic link filename */
- symnam[i] = '\0';
- fprintf(msgfile, "a %s symbolic link to %s\n", name, symnam);
- }
- break;
- #endif
- case S_IFREG: /* It is a link or a file */
- fprintf(msgfile, "a %s ", name);
- if ((asb->sb_nlink > 1) && ((link = islink(name, asb)) != NULL)) { /* Xn */
- fprintf(msgfile, "link to %s\n", link->l_name);
- } else {
- fprintf(msgfile, "%ld Blocks\n",
- ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
- }
- break;
- }
- } else if (f_list) {
- if (f_verbose) {
- atm = localtime(&asb->sb_mtime);
- print_mode(asb->sb_mode);
- fprintf(msgfile," %d/%d %6d %3s %2d %02d:%02d %4d %s",
- asb->sb_uid, asb->sb_gid, asb->sb_size,
- monnames[atm->tm_mon], atm->tm_mday, atm->tm_hour,
- atm->tm_min, atm->tm_year + 1900, name);
- } else {
- fprintf(msgfile, "%s", name);
- }
- switch (mode) {
- #ifdef S_IFLNK
- case S_IFLNK: /* This file is a symbolic link */
- i = readlink(name, symnam, PATH_MAX - 1);
- if (i < 0) { /* Could not find symbolic link */
- warn("can't read symbolic link", strerror(errno)); /* Xn */
- } else { /* Found symbolic link filename */
- symnam[i] = '\0';
- fprintf(msgfile, " symbolic link to %s", symnam);
- }
- break;
- #endif
- case S_IFREG: /* It is a link or a file */
- if ((asb->sb_nlink > 1) && ((link = islink(name, asb)) != NULL)) { /* Xn */
- fprintf(msgfile, " linked to %s", link->l_name);
- }
- break; /* Do not print out directories */
- }
- fputc('\n', msgfile);
- } else {
- fprintf(msgfile, "? %s %ld blocks\n", name,
- ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
- }
- }
-
-
- /* pax_entry - print a verbose cpio-style entry
- *
- * DESCRIPTION
- *
- * Print_entry prints a single line of file information. The format
- * of the line is the same as that used by the LS command.
- * No error checking is done for bad or invalid data.
- *
- * PARAMETERS
- *
- * char *name - pointer to name to print an entry for
- * Stat *asb - pointer to the stat structure for the file
- */
-
- #ifdef __STDC__
-
- static void pax_entry(char *name, Stat *asb)
-
- #else
-
- static void pax_entry(name, asb)
- char *name;
- Stat *asb;
-
- #endif
- {
- struct tm *atm;
- Link *from;
- struct passwd *pwp;
- struct group *grp;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static void pax_entry() in list.c\n");
- #endif
- if (f_list && f_verbose) {
- print_mode(asb->sb_mode);
- fprintf(msgfile, " %2d", asb->sb_nlink);
- atm = localtime(&asb->sb_mtime);
- if ((pwp = getpwuid((int) USH(asb->sb_uid))) != NULL) { /* Xn */
- fprintf(msgfile, " %-8s", pwp->pw_name);
- } else {
- fprintf(msgfile, " %-8u", USH(asb->sb_uid));
- }
- if ((grp = getgrgid((int) USH(asb->sb_gid))) != NULL) { /* Xn */
- #if 0
- (void) fprintf(stderr, "list.c/pax_entry - asb->sb_gid: %lu; grp->gr_name: \"%s\"\n",
- (unsigned long) asb->sb_gid, grp->gr_name);
- (void) fflush(stderr);
- #endif /* Xn 1993-06-23 */
- fprintf(msgfile, " %-8s", grp->gr_name);
- } else {
- #if 0
- (void) fprintf(stderr, "list.c/pax_entry - asb->sb_gid: %lu\n", (unsigned long) asb->sb_gid);
- (void) fflush(stderr);
- #endif /* Xn 1993-06-23 */
- fprintf(msgfile, " %-8u", USH(asb->sb_gid));
- }
- switch (asb->sb_mode & S_IFMT) {
- case S_IFBLK:
- case S_IFCHR:
- #ifndef _POSIX_SOURCE
- fprintf(msgfile, "\t%3d, %3d",
- major(asb->sb_rdev), minor(asb->sb_rdev));
- #endif
- break;
- case S_IFREG:
- fprintf(msgfile, "\t%8ld", asb->sb_size);
- break;
- default:
- fprintf(msgfile, "\t ");
- }
- fprintf(msgfile," %3s %2d %02d:%02d ",
- monnames[atm->tm_mon], atm->tm_mday,
- atm->tm_hour, atm->tm_min);
- }
- fprintf(msgfile, "%s", name);
- if ((asb->sb_nlink > 1) && ((from = islink(name, asb)) != NULL)) { /* Xn */
- fprintf(msgfile, " == %s", from->l_name);
- }
- #ifdef S_IFLNK
- if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
- fprintf(msgfile, " -> %s", asb->sb_link);
- }
- #endif /* S_IFLNK */
- putc('\n', msgfile);
- }
-
-
- /* print_mode - fancy file mode display
- *
- * DESCRIPTION
- *
- * Print_mode displays a numeric file mode in the standard unix
- * representation, ala ls (-rwxrwxrwx). No error checking is done
- * for bad mode combinations. FIFOS, sybmbolic links, sticky bits,
- * block- and character-special devices are supported if supported
- * by the hosting implementation.
- *
- * PARAMETERS
- *
- * ushort mode - The integer representation of the mode to print.
- */
-
- #ifdef __STDC__
-
- #ifdef _POSIX_SOURCE /* Xn */
- static void print_mode(mode_t mode) /* Xn */
- #else /* Xn */
- static void print_mode(ushort mode)
- #endif /* Xn */
-
- #else
-
- static void print_mode(mode)
- ushort mode;
-
- #endif
- {
- /* Tar does not print the leading identifier... */
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static void print_mode() in list.c\n");
- #endif
- if (ar_interface != TAR) {
- switch (mode & S_IFMT) {
- case S_IFDIR:
- putc('d', msgfile);
- break;
- #ifdef S_IFLNK
- case S_IFLNK:
- putc('l', msgfile);
- break;
- #endif /* S_IFLNK */
- case S_IFBLK:
- putc('b', msgfile);
- break;
- case S_IFCHR:
- putc('c', msgfile);
- break;
- #ifdef S_IFIFO
- case S_IFIFO:
- putc('p', msgfile);
- break;
- #endif /* S_IFIFO */
- case S_IFREG:
- default:
- putc('-', msgfile);
- break;
- }
- }
- putc(mode & 0400 ? 'r' : '-', msgfile);
- putc(mode & 0200 ? 'w' : '-', msgfile);
- putc(mode & 0100
- ? mode & 04000 ? 's' : 'x'
- : mode & 04000 ? 'S' : '-', msgfile);
- putc(mode & 0040 ? 'r' : '-', msgfile);
- putc(mode & 0020 ? 'w' : '-', msgfile);
- putc(mode & 0010
- ? mode & 02000 ? 's' : 'x'
- : mode & 02000 ? 'S' : '-', msgfile);
- putc(mode & 0004 ? 'r' : '-', msgfile);
- putc(mode & 0002 ? 'w' : '-', msgfile);
- putc(mode & 0001
- ? mode & 01000 ? 't' : 'x'
- : mode & 01000 ? 'T' : '-', msgfile);
- }
-
-
- /* from_oct - quick and dirty octal conversion
- *
- * DESCRIPTION
- *
- * From_oct will convert an ASCII representation of an octal number
- * to the numeric representation. The number of characters to convert
- * is given by the parameter "digs". If there are less numbers than
- * specified by "digs", then the routine returns -1.
- *
- * PARAMETERS
- *
- * int digs - Number to of digits to convert
- * char *where - Character representation of octal number
- *
- * RETURNS
- *
- * The value of the octal number represented by the first digs
- * characters of the string where. Result is -1 if the field
- * is invalid (all blank, or nonoctal).
- *
- * ERRORS
- *
- * If the field is all blank, then the value returned is -1.
- *
- */
-
- #ifdef __STDC__
-
- static long from_oct(int digs, char *where)
-
- #else
-
- static long from_oct(digs, where)
- int digs; /* number of characters to convert */
- char *where; /* character representation of octal number */
-
- #endif
- {
- long value;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static long from_oct() in list.c\n");
- #endif
- while (isspace(*where)) { /* Skip spaces */
- where++;
- if (--digs <= 0) {
- return(-1); /* All blank field */
- }
- }
- value = 0;
- while (digs > 0 && ISODIGIT(*where)) { /* Scan til nonoctal */
- value = (value << 3) | (*where++ - '0');
- --digs;
- }
-
- if (digs > 0 && *where && !isspace(*where)) {
- return(-1); /* Ended on non-space/nul */
- }
- return(value);
- }
-