Annotation of coherent/b/conf/patch/patch.c, revision 1.1

1.1     ! root        1: static char Copyright[] =      "$Copyright: (c) 1985, INETCO Systems, Ltd.$";
        !             2: static char version[] =        "patch version 2.6 for COHERENT v.4.0";
        !             3: 
        !             4: /* (lgl-
        !             5:  *     The information contained herein is a trade secret of Mark Williams
        !             6:  *     Company, and  is confidential information.  It is provided  under a
        !             7:  *     license agreement,  and may be  copied or disclosed  only under the
        !             8:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
        !             9:  *     material without the express written authorization of Mark Williams
        !            10:  *     Company or persuant to the license agreement is unlawful.
        !            11:  *
        !            12:  *     COHERENT Version 2.3.35
        !            13:  *     Copyright (c) 1982, 1983, 1984.
        !            14:  *     An unpublished work by Mark Williams Company, Chicago.
        !            15:  *     All rights reserved.
        !            16:  -lgl) */
        !            17: /*
        !            18:  * Patch binary system images
        !            19:  * and possibly the running system.
        !            20:  * This program is not expected to work other than on PC Coherent.
        !            21:  * Certain hot patches may not be effective, since some values are only
        !            22:  * referenced once at system initialization.
        !            23:  *
        !            24:  * $Log:       patch.c,v $
        !            25:  * Revision 1.6  92/11/25  15:32:04  bin
        !            26:  * hal: update to read fom /dev/imem
        !            27:  * 
        !            28:  * Revision 1.5  92/07/06  15:41:09  bin
        !            29:  * piggy: all hex numbers have leading zeroes to indicate their length
        !            30:  * 
        !            31:  * Revision 1.1        91/04/24  14:20:20      bin
        !            32:  * Initial revision
        !            33:  * 
        !            34:  * 87/02/01    Allan Cornish           /usr/src/cmd/conf/patch.c
        !            35:  * myatol() routine added which recognizes numeric base specifications.
        !            36:  * All references to atol() modified to use myatol().
        !            37:  * main() now enables buffering on standard output.
        !            38:  *
        !            39:  */
        !            40: char short_helpmessage[] = "\
        !            41: patch -- alter COFF binary image\n\
        !            42: Usage: patch [ -v ][ -p ][ -k ] imagename symbol=value [ ... ]\n\
        !            43: ";
        !            44: 
        !            45: char helpmessage[] = "\
        !            46: Options:\n\
        !            47:        -v      Verbose mode--print what's being done.\n\
        !            48:        -p      Peek only--do not write.\n\
        !            49:        -k      Patch running system via /dev/kmem, /dev/kmemhi.\n\
        !            50:        -K      Like -k but do not alter imagename.\n\
        !            51: Patch alters the value of 'symbol' to 'value' in the binary 'imagename'.\n\
        !            52: Both 'symbol' and 'value' may be composed of a decimal numeric constant\n\
        !            53: or of a symbol in the image's symbol table, trailing '_' is significant,\n\
        !            54: optionally offset by + or - a decimal numeric constant.\n\
        !            55: The 'value' field may be optionally composed of 'makedev(d1, d2)' where 'd1'\n\
        !            56: and 'd2' are decimal numbers and the result is a dev_t value.\n\
        !            57: The size of the altered field is by default sizeof(int), but the 'value'\n\
        !            58: specification may be followed by a ':' and a 'c', 's', 'i', or 'l' to\n\
        !            59: explicitly specify a char, short, int, or long sized patch.\n\
        !            60: \
        !            61: ";
        !            62: 
        !            63: #include <stdio.h>
        !            64: #include <coff.h>
        !            65: #include <canon.h>
        !            66: #include <ctype.h>
        !            67: #include <fcntl.h>
        !            68: #include <sys/types.h>
        !            69: #include <sys/stat.h>
        !            70: #include "patch.h"
        !            71: 
        !            72: /*
        !            73:  * Nlist tables and patch records.
        !            74:  */
        !            75: #define NNLS   512
        !            76: int    nnls;   /* Number of nlist elements used */
        !            77: SYMENT nl[NNLS*2];
        !            78: int    sym_len = 0;    /* Number of bytes allocated for symbols.  */
        !            79: char   *symbols=NULL;
        !            80: 
        !            81: PLIST pl[NNLS];
        !            82: 
        !            83: char *namep;           /* Name of object file to patch.  */
        !            84: int nobin = 0;         /* Should we not patch the image?  */
        !            85: int hotpatch = 0;      /* Are we patching /dev/kmem,/dev/kmemhi?  */
        !            86: int verbose = 0;       /* Are we printing feedback?  */
        !            87: int peek = 0;          /* Just peek--don't actually do the patch.  */
        !            88: 
        !            89: void main();
        !            90: int getnames();
        !            91: void badsym();
        !            92: void getone();
        !            93: void setfile();
        !            94: void setkmem();
        !            95: int patch();
        !            96: long myatol();
        !            97: void usage();
        !            98: char *index();
        !            99: char *realloc();
        !           100: 
        !           101: 
        !           102: void
        !           103: main(argc, argv)
        !           104:        int argc;
        !           105:        char *argv[];
        !           106: {
        !           107:        static char obuf[BUFSIZ];
        !           108:        int c;                  /* For reading options from getopt().  */
        !           109:        int num_patches;        /* Number of patches to make on this file.  */
        !           110: 
        !           111:        extern int optind;
        !           112:        extern char *optarg;
        !           113: 
        !           114:        /*
        !           115:         * Enable output buffering.
        !           116:         */
        !           117:        setbuf( stdout, obuf );
        !           118: 
        !           119:        while ((c = getopt(argc, argv, "Kkpv?")) != EOF) {
        !           120:                switch (c) {
        !           121:                case 'K':
        !           122:                        hotpatch++;
        !           123:                        nobin++;
        !           124:                case 'k':
        !           125:                        hotpatch++;
        !           126:                        break;
        !           127:                case 'p':
        !           128:                        peek++;
        !           129:                        break;
        !           130:                case 'v':
        !           131:                        verbose++;
        !           132:                        break;
        !           133:                case '?':
        !           134:                        fprintf(stderr, "%s\n", version);
        !           135:                        usage(TRUE);    /* Does not return.  */
        !           136:                default:
        !           137:                        usage(FALSE);   /* Does not return.  */
        !           138:                }
        !           139:        }
        !           140: 
        !           141:        /*
        !           142:         * There must be at least 2 arguments left.
        !           143:         */
        !           144:        if (argc - optind < 2) {
        !           145:                fprintf(stderr, "Missing arguments.\n");
        !           146:                usage(FALSE);   /* Does not return */
        !           147:        }
        !           148:        
        !           149:        namep = argv[optind++]; /* Fetch the name of the file to patch.  */
        !           150: 
        !           151:        num_patches = (argc - optind);
        !           152:        if (getnames(num_patches, &(argv[optind])) == 0) {
        !           153:                if (!nobin) {
        !           154:                        setfile(namep, num_patches, pl);
        !           155:                }
        !           156:                if (hotpatch) {
        !           157:                        setkmem(num_patches);
        !           158:                }
        !           159:                exit(0);
        !           160:        }
        !           161:        exit(1);
        !           162: }
        !           163: 
        !           164: /*
        !           165:  * Fill in the array of patch structures 'pl[]' based on the command line.
        !           166:  * 'nn' is the number of symbol assignments; 'npp' is an argv of symbol
        !           167:  * assignments.
        !           168:  * Returns the number of invalid assignments.
        !           169:  */
        !           170: int
        !           171: getnames(nn, npp)
        !           172:        int nn;
        !           173:        char **npp;
        !           174: {
        !           175:        register int i;
        !           176:        register PLIST *p;
        !           177:        register SYMENT *np;
        !           178:        int nbad;
        !           179: 
        !           180:        nbad = 0;
        !           181:        for (i = 0; i < nn; i += 1)
        !           182:                if (i < NNLS-1)
        !           183:                        getone(i, npp[i]);
        !           184: 
        !           185:        /* Now we can look up all the symbols in the symbol table.  */
        !           186:        coffnlist(namep, nl, symbols, nnls);
        !           187: 
        !           188:        for (i = 0; i < nn; i += 1)
        !           189:                if (i >= NNLS)
        !           190:                        fprintf(stderr,
        !           191:                                "Too many patches: %s ignored\n", npp[i]);
        !           192:                else {
        !           193:                        /* 'p' is the struct we fill in this time around.  */
        !           194:                        p = &pl[i];
        !           195:                        
        !           196:                        /* If the LHS was (part) symbolic, add in the value
        !           197:                         * of the symbol.
        !           198:                         */
        !           199:                        if ((np = p->p_lvnp) != NULL) {
        !           200:                                if (0xffff != np->n_type) {
        !           201:                                        p->p_lval += np->n_value;
        !           202:                                } else {
        !           203:                                        nbad += 1;
        !           204:                                        badsym(np->n_offset);
        !           205:                                }
        !           206:                        }
        !           207:                        /* If the RHS was (part) symbolic, add in the value
        !           208:                         * of the symbol.
        !           209:                         */
        !           210:                        if ((np = p->p_rvnp) != NULL) {
        !           211:                                if (0xffff != np->n_type) {
        !           212:                                        p->p_rval += np->n_value;
        !           213:                                } else {
        !           214:                                        nbad += 1;
        !           215:                                        badsym(np->n_offset);
        !           216:                                }
        !           217:                        }
        !           218: 
        !           219:                        /* Fill in the value to be assigned.  */
        !           220:                        switch (p->p_type) {
        !           221:                        case 'c': p->p_val.p_char       = p->p_rval; break;
        !           222:                        case 's': p->p_val.p_short      = p->p_rval; break;
        !           223:                        case 'i': p->p_val.p_int        = p->p_rval; break;
        !           224:                        case 'l': p->p_val.p_long       = p->p_rval; break;
        !           225:                        default:
        !           226:                                nbad += 1;
        !           227:                                fprintf(stderr, "Bad data type %c in %s.\n",
        !           228:                                        p->p_type, npp[i]);
        !           229:                                break;
        !           230:                        }
        !           231:                }
        !           232:        return (nbad);
        !           233: }
        !           234: 
        !           235: void
        !           236: badsym(offset)
        !           237:        long offset;
        !           238: {
        !           239:        fprintf(stderr, "%s not found in %s\n",
        !           240:                &(symbols[offset - sizeof(long)]), namep);
        !           241: }
        !           242: 
        !           243: /*
        !           244:  * Parse a symbolic assignment, filling in pl[i].
        !           245:  */
        !           246: void
        !           247: getone(i, np)
        !           248:        int i;                  /* Which'th symbol assigment is this?  */
        !           249:        register char *np;      /* The symbol assignment itself.  */
        !           250: {
        !           251:        register int n;
        !           252:        register char *cp;
        !           253:        char *nsym;             /* Temporary holder for 'symbols' realloc().  */
        !           254:        long myatol();
        !           255: 
        !           256:        pl[i].p_lvnp = NULL;
        !           257:        pl[i].p_lval = 0;
        !           258:        pl[i].p_rvnp = NULL;
        !           259:        pl[i].p_rval = 0;
        !           260:        pl[i].p_type = 'i';
        !           261: 
        !           262:        /*
        !           263:         * If there is a type indicator, get it now.
        !           264:         */
        !           265:        if (NULL != (cp = index(np, ':'))) {
        !           266:                pl[i].p_type = cp[1];
        !           267:        }
        !           268: 
        !           269:        /* Pull apart LHS of assignment.  */
        !           270:        if (isalpha(*np) || *np == '_') {
        !           271:                pl[i].p_lvnp = nl + nnls;       /* Allocate another SYMENT.  */
        !           272:                /* Mark as not yet found.  */
        !           273:                nl[nnls].n_type = 0xffff;
        !           274:                /* Point at offset into 'symbols' for new name.  */
        !           275:                nl[nnls].n_zeroes = 0;
        !           276:                nl[nnls].n_offset = sizeof(long) + sym_len;
        !           277: 
        !           278:                /* Figure out how big the symbol is by looking for
        !           279:                 * a non-alphanumeric or _ character.
        !           280:                 */
        !           281:                cp = np;
        !           282:                for (n = 0; isalnum(*cp) || *cp == '_'; n += 1) {
        !           283:                        cp += 1;
        !           284:                }
        !           285:                /* Now allocate more space for symbol names.  */
        !           286:                sym_len += n + sizeof('\0');
        !           287:                if (NULL == (nsym = realloc(symbols, sym_len))) {
        !           288:                        /* This assignment is too long; skip it.  */
        !           289:                        sym_len -= n;
        !           290:                        fprintf(stderr,
        !           291:                                "Assignment too long; skipping:  %s\n", np);
        !           292:                        return;
        !           293:                }
        !           294:                symbols = nsym; /* The realloc() worked.  */
        !           295:                /* Copy the new symbol in place.  */
        !           296:                cp = symbols + sym_len - (n + sizeof('\0'));
        !           297:                strncpy(cp, np, n);
        !           298:                cp[n] = '\0';
        !           299: 
        !           300:                nnls += 1;      /* Move up to next empty SYMENT.  */
        !           301:                np += n;        /* Move on to next token.  */
        !           302:        }
        !           303:        /*
        !           304:         * If there is a '+' it has served its purpose by dropping us
        !           305:         * out of the for loop above.  Ignore it now.
        !           306:         */
        !           307:        if (*np == '+')
        !           308:                np += 1;
        !           309: 
        !           310:        /* Fetch a possible literal number.  */
        !           311:        pl[i].p_lval = myatol(np);
        !           312: 
        !           313:        /* Pull apart RHS of assignment.  */
        !           314:        np = index(np, '=');
        !           315:        if (np != NULL) {
        !           316:                np += 1;
        !           317:                if (strncmp(np, "makedev(", 8) == 0) {
        !           318:                        /* RHS is a makedev() expression.  */
        !           319:                        int d1, d2;
        !           320: 
        !           321:                        np = index(np, '(') + 1;
        !           322:                        d1 = myatol(np);
        !           323:                        np = index(np, ',');
        !           324:                        if (np != NULL) {
        !           325:                                d2 = myatol(np + 1);
        !           326:                                np = index(np, ')');
        !           327:                        } else
        !           328:                                d2 = 0;
        !           329:                        pl[i].p_rval = makedev(d1, d2);
        !           330:                        pl[i].p_type = 's';
        !           331:                        if (np == NULL)
        !           332:                                np = "";
        !           333:                        else
        !           334:                                np += 1;
        !           335:                        goto tail;
        !           336:        } else if (isalpha(*np) || *np == '_') {
        !           337:                        /* The RHS must be a object symbol.  */
        !           338:        
        !           339:                        pl[i].p_rvnp = nl + nnls;  /* Allocate another SYMENT.  */
        !           340:                        nl[nnls].n_type = 0xffff;  /* Mark as not yet found.  */
        !           341: 
        !           342:                        /* Point at offset into 'symbols' for new name.  */
        !           343:                        nl[nnls].n_zeroes = 0;
        !           344:                        nl[nnls].n_offset = sizeof(long) + sym_len;
        !           345:        
        !           346:                        /* Figure out how big the symbol is by looking for
        !           347:                         * a non-alphanumeric or _ character.
        !           348:                         */
        !           349:                        cp = np;
        !           350:                        for (n = 0; isalnum(*cp) || *cp == '_'; n += 1) {
        !           351:                                cp += 1;
        !           352:                        }
        !           353:                        /* Now allocate more space for symbol names.  */
        !           354:                        sym_len += n + sizeof('\0');
        !           355:                        if (NULL == (nsym = realloc(symbols, sym_len))) {
        !           356:                                /* This assignment is too long; skip it.  */
        !           357:                                sym_len -= n;
        !           358:                                fprintf(stderr,
        !           359:                                  "Assignment too long; skipping:  %s\n", np);
        !           360:                                return;
        !           361:                        }
        !           362:                        symbols = nsym; /* The realloc() worked.  */
        !           363:                        /* Copy the new symbol in place.  */
        !           364:                        cp = &(symbols[sym_len - (n + sizeof('\0'))]);
        !           365:                        strncpy(cp, np, n);
        !           366:                        cp[n] = '\0';
        !           367: 
        !           368:                        nnls += 1;      /* Move up to next empty SYMENT.  */
        !           369:                        np += n;        /* Move on to next token.  */
        !           370:                }
        !           371: 
        !           372: 
        !           373:                /*
        !           374:                 * If there is a '+' is has served its purpose by dropping us
        !           375:                 * out of the for loop above.  Ignore it now.
        !           376:                 */
        !           377:                if (*np == '+')
        !           378:                        np += 1;
        !           379:                /* Fetch a possible literal number.  */
        !           380:                pl[i].p_rval = myatol(np);
        !           381:        }
        !           382: tail:
        !           383:        return;
        !           384: }
        !           385: 
        !           386: /*
        !           387:  * Modify the contents of /dev/kmem to match the array of patch
        !           388:  * structures pl[].  The argument 'n' is the number of entries in pl[]
        !           389:  * that should be processed.
        !           390:  */
        !           391: void
        !           392: setkmem(n)
        !           393:        int n;
        !           394: {
        !           395:        int fdlo, fdhi;
        !           396:        register int i;
        !           397:        char *symname;  /* Name of symbol in LHS being patched.  */
        !           398: 
        !           399:        /* Open up live memory for patching.  */
        !           400:        if (peek) {
        !           401:                if ((fdlo=open("/dev/kmem", O_RDONLY)) < 0) {
        !           402:                        fprintf(stderr, "Cannot open /dev/kmem for reading.\n");
        !           403:                        return;
        !           404:                }
        !           405:                if ((fdhi=open("/dev/kmemhi", O_RDONLY)) < 0) {
        !           406:                        fprintf(stderr, "Cannot open /dev/kmemhi for reading.\n");
        !           407:                        return;
        !           408:                }
        !           409:        } else {
        !           410:                if ((fdlo=open("/dev/kmem", O_RDWR)) < 0) {
        !           411:                        fprintf(stderr, "Cannot open /dev/kmem.\n");
        !           412:                        return;
        !           413:                }
        !           414:                if ((fdhi=open("/dev/kmemhi", O_RDWR)) < 0) {
        !           415:                        fprintf(stderr, "Cannot open /dev/kmemhi.\n");
        !           416:                        return;
        !           417:                }
        !           418:        }
        !           419: 
        !           420:        /* Walk through pl[] blasting the new values into live memory.  */
        !           421:        for (i = 0; i < n; i += 1) {
        !           422:                int seekOffset = pl[i].p_lval;
        !           423:                symname = &(symbols[pl[i].p_lvnp->n_offset - sizeof(long)]);
        !           424: 
        !           425:                if ((seekOffset & 0x80000000) == 0) {
        !           426:                        if(lseek(fdlo, seekOffset, 0) != -1L) {
        !           427:                                if (patch(fdlo, &pl[i], "/dev/kmem",
        !           428:                                  symname) < 0)
        !           429:                                        fprintf(stderr,
        !           430:                                          "Write error in /dev/kmem\n");
        !           431:                        } else
        !           432:                                fprintf(stderr, "Seek error in /dev/kmem\n");
        !           433:                } else {
        !           434:                        if(lseek(fdhi, seekOffset-0x80000000, 0) != -1L) {
        !           435:                                if (patch(fdhi, &pl[i], "/dev/kmemhi",
        !           436:                                  symname) < 0)
        !           437:                                        fprintf(stderr,
        !           438:                                          "Write error in /dev/kmemhi\n");
        !           439:                        } else
        !           440:                                fprintf(stderr, "Seek error in /dev/kmemhi\n");
        !           441:                }
        !           442:        }
        !           443:        close(fdlo);
        !           444:        close(fdhi);
        !           445: }
        !           446: 
        !           447: 
        !           448: /*
        !           449:  * Modify the file attached to descriptor 'fd' to match the single patch
        !           450:  * structure 'p'.  The file descriptor should already be lseek()'d to
        !           451:  * the correct place.
        !           452:  * Returns 0 on success, -1 otherwise.  errno will be set on error.
        !           453:  */
        !           454: int
        !           455: patch(fd, p, file, sym)
        !           456:        int fd;
        !           457:        PLIST *p;
        !           458:        /* These two args are only for information.  */
        !           459:        char *file;     /* Name of the file being patched.  */
        !           460:        char *sym;      /* Name of the LHS symbol being patched.  */
        !           461: {
        !           462:        register char *bp;
        !           463:        register int nc;
        !           464:        union {
        !           465:                char    p_char;
        !           466:                short   p_short;
        !           467:                int     p_int;
        !           468:                long    p_long;
        !           469:        } old_val;
        !           470: 
        !           471:        bp = &p->p_val;
        !           472:        switch (p->p_type) {
        !           473:        case 'c':       nc = sizeof(char);      break;
        !           474:        case 's':       nc = sizeof(short);     break;
        !           475:        case 'i':       nc = sizeof(int);       break;
        !           476:        case 'l':       nc = sizeof(long);      break;
        !           477:        }
        !           478: 
        !           479:        if (verbose || peek) {
        !           480:            old_val.p_long = 0; /* Zero the whole buffer.  */
        !           481: 
        !           482:            if (read(fd, &old_val, nc) != nc) {
        !           483:                fprintf(stderr, "Can't read old value.\n");
        !           484:            } else {
        !           485: 
        !           486:                printf("%s: ", file);
        !           487: 
        !           488:                if (verbose) printf("old value of ");
        !           489: 
        !           490:                printf("%s: ", sym);
        !           491:                switch (p->p_type) {
        !           492:                case 'c':       printf("0x%02x", old_val.p_char);       break;
        !           493:                case 's':       printf("0x%04x", old_val.p_short);      break;
        !           494:                case 'i':       printf("0x%08x", old_val.p_int);        break;
        !           495:                case 'l':       printf("0x%08x", old_val.p_long);       break;
        !           496:                } /* switch */
        !           497: 
        !           498:                printf("\n");
        !           499: 
        !           500:                if (!peek) {    /* If only peeking, there is no new value.  */
        !           501:                        printf("%s: new value: ", file);
        !           502:                        switch (p->p_type) {
        !           503:                        case 'c':       printf("0x%02x", p->p_val.p_char);
        !           504:                                        break;
        !           505:                        case 's':       printf("0x%04x", p->p_val.p_short);
        !           506:                                        break;
        !           507:                        case 'i':       printf("0x%08x", p->p_val.p_int);
        !           508:                                        break;
        !           509:                        case 'l':       printf("0x%08x", p->p_val.p_long);
        !           510:                                        break;
        !           511:                        } /* switch */
        !           512: 
        !           513:                        printf("\n");
        !           514:                } /* if (verbose) */
        !           515: 
        !           516:                /* Go back for the write.  */
        !           517:                lseek(fd, (long) (-nc), 1);
        !           518:            } /* if (read...) */
        !           519: 
        !           520:        } /* if (verbose || peek) */
        !           521: 
        !           522:        if (peek) {
        !           523:                if (verbose) {
        !           524:                        printf("Just peeking, no write.\n");
        !           525:                }
        !           526:        } else if (write(fd, bp, nc) != nc) {
        !           527:                return (-1);
        !           528:        }
        !           529:        return (0);
        !           530: }
        !           531: 
        !           532: /**
        !           533:  *
        !           534:  * long
        !           535:  * myatol( s )         -- Ascii to Long integer conversion.
        !           536:  * char * s;
        !           537:  *
        !           538:  *     Input:  s = pointer to string containing a numeric prefix.
        !           539:  *
        !           540:  *     Action: Parse input string.
        !           541:  *             Parse optional leading sign character '-'.
        !           542:  *             Parse optional numeric base specification '0', '0o', and '0x'.
        !           543:  *             Parse following numeric digits.
        !           544:  *
        !           545:  *     Return: Long integer value.
        !           546:  *
        !           547:  *     Notes:  Numeric parsing terminates on first non-digit.
        !           548:  */
        !           549: long
        !           550: myatol( s )
        !           551:        register char * s;
        !           552: {
        !           553:        register int base;
        !           554:        register int sign;
        !           555:        auto    long valu;
        !           556: 
        !           557:        /*
        !           558:         * Check for leading negative sign.
        !           559:         */
        !           560:        sign = 1;
        !           561:        if ( *s == '-' ) {
        !           562:                sign = -1;
        !           563:                s++;
        !           564:        }
        !           565: 
        !           566:        /*
        !           567:         * Check for base specification.
        !           568:         */
        !           569:        base = 10;
        !           570:        if ( *s == '0' ) {
        !           571:                switch ( *++s ) {
        !           572:                case 'x':       base = 16;      ++s;    break;
        !           573:                case 'o':       base =  8;      ++s;    break;
        !           574:                default:        base =  8;
        !           575:                }
        !           576:        }
        !           577: 
        !           578:        for ( valu = 0L; *s != '\0'; s++ ) {
        !           579: 
        !           580:                /*
        !           581:                 * Decimal digit.
        !           582:                 */
        !           583:                if ( ('0' <= *s) && (*s <= '9') ) {
        !           584:                        valu *= base;
        !           585:                        valu += *s - '0';
        !           586:                }
        !           587: 
        !           588:                /*
        !           589:                 * Upper case hex digit.
        !           590:                 */
        !           591:                else if ( (base == 16) && ('A' <= *s) && (*s <= 'F') ) {
        !           592:                        valu *= base;
        !           593:                        valu += *s - ('A' - 10);
        !           594:                }
        !           595: 
        !           596:                /*
        !           597:                 * Lower case Hex digit.
        !           598:                 */
        !           599:                else if ( (base == 16) && ('a' <= *s) && (*s <= 'f') ) {
        !           600:                        valu *= base;
        !           601:                        valu += *s - ('a' - 10);
        !           602:                }
        !           603: 
        !           604:                /*
        !           605:                 * Not a digit.
        !           606:                 */
        !           607:                else
        !           608:                        break;
        !           609:        }
        !           610: 
        !           611:        if ( sign < 0 )
        !           612:                valu = -valu;
        !           613: 
        !           614:        return valu;
        !           615: }
        !           616: 
        !           617: /*
        !           618:  * Print out an usage message.
        !           619:  */
        !           620: void
        !           621: usage(verbose)
        !           622:        int verbose;
        !           623: {
        !           624:        fprintf(stderr, short_helpmessage);
        !           625:        if (verbose) {
        !           626:                fprintf(stderr, helpmessage);
        !           627:        }
        !           628:        exit(1);
        !           629: }

unix.superglobalmegacorp.com

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