Annotation of 43BSD/bin/passwd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)passwd.c   4.24 (Berkeley) 5/28/86";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  * Modify a field in the password file (either
                     19:  * password, login shell, or gecos field).
                     20:  * This program should be suid with an owner
                     21:  * with write permission on /etc/passwd.
                     22:  */
                     23: #include <sys/types.h>
                     24: #include <sys/file.h>
                     25: #include <sys/time.h>
                     26: #include <sys/resource.h>
                     27: 
                     28: #include <stdio.h>
                     29: #include <signal.h>
                     30: #include <pwd.h>
                     31: #include <ndbm.h>
                     32: #include <errno.h>
                     33: #include <strings.h>
                     34: #include <ctype.h>
                     35: 
                     36: /*
                     37:  * This should be the first thing returned from a getloginshells()
                     38:  * but too many programs know that it is /bin/sh.
                     39:  */
                     40: #define DEFSHELL "/bin/sh"
                     41: 
                     42: char   temp[] = "/etc/ptmp";
                     43: char   passwd[] = "/etc/passwd";
                     44: char   *getpass();
                     45: char   *getlogin();
                     46: char   *getfingerinfo();
                     47: char   *getloginshell();
                     48: char   *getnewpasswd();
                     49: char   *malloc();
                     50: char   *getusershell();
                     51: extern int errno;
                     52: 
                     53: main(argc, argv)
                     54:        char *argv[];
                     55: {
                     56:        struct passwd *pwd;
                     57:        char *cp, *uname, *progname;
                     58:        int fd, u, dochfn, dochsh, err;
                     59:        FILE *tf;
                     60:        DBM *dp;
                     61: 
                     62:        if ((progname = rindex(argv[0], '/')) == NULL)
                     63:                progname = argv[0];
                     64:        else
                     65:                progname++;
                     66:        dochfn = 0, dochsh = 0;
                     67:        argc--, argv++;
                     68:        while (argc > 0 && argv[0][0] == '-') {
                     69:                for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
                     70: 
                     71:                case 'f':
                     72:                        if (dochsh)
                     73:                                goto bad;
                     74:                        dochfn = 1;
                     75:                        break;
                     76: 
                     77:                case 's':
                     78:                        if (dochfn) {
                     79:                bad:
                     80:                                fprintf(stderr,
                     81:                                   "passwd: Only one of -f and -s allowed.\n"); 
                     82:                                exit(1);
                     83:                        }
                     84:                        dochsh = 1;
                     85:                        break;
                     86: 
                     87:                default:
                     88:                        fprintf(stderr, "passwd: -%c: unknown option.\n", *cp);
                     89:                        exit(1);
                     90:                }
                     91:                argc--, argv++;
                     92:        }
                     93:        if (!dochfn && !dochsh) {
                     94:                if (strcmp(progname, "chfn") == 0)
                     95:                        dochfn = 1;
                     96:                else if (strcmp(progname, "chsh") == 0)
                     97:                        dochsh = 1;
                     98:        }
                     99:        if (argc < 1) {
                    100:                if ((uname = getlogin()) == NULL) {
                    101:                        fprintf(stderr, "Usage: %s [-f] [-s] [user]\n", progname);
                    102:                        exit(1);
                    103:                }
                    104:                printf("Changing %s for %s.\n",
                    105:                    dochfn ? "finger information" :
                    106:                        dochsh ? "login shell" : "password",
                    107:                    uname);
                    108:        } else
                    109:                uname = *argv++;
                    110:        pwd = getpwnam(uname);
                    111:        if (pwd == NULL) {
                    112:                fprintf(stderr, "passwd: %s: unknown user.\n", uname);
                    113:                exit(1);
                    114:        }
                    115:        u = getuid();
                    116:        if (u != 0 && u != pwd->pw_uid) {
                    117:                printf("Permission denied.\n");
                    118:                exit(1);
                    119:        }
                    120:        if (dochfn)
                    121:                cp = getfingerinfo(pwd);
                    122:        else if (dochsh)
                    123:                cp = getloginshell(pwd, u, *argv);
                    124:        else
                    125:                cp = getnewpasswd(pwd, u);
                    126:        (void) signal(SIGHUP, SIG_IGN);
                    127:        (void) signal(SIGINT, SIG_IGN);
                    128:        (void) signal(SIGQUIT, SIG_IGN);
                    129:        (void) signal(SIGTSTP, SIG_IGN);
                    130:        (void) umask(0);
                    131:        fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
                    132:        if (fd < 0) {
                    133:                err = errno;
                    134: 
                    135:                fprintf(stderr, "passwd: ");
                    136:                if (err == EEXIST)
                    137:                        fprintf(stderr, "password file busy - try again.\n");
                    138:                else {
                    139:                        errno = err;
                    140:                        perror(temp);
                    141:                }
                    142:                exit(1);
                    143:        }
                    144:        if ((tf = fdopen(fd, "w")) == NULL) {
                    145:                fprintf(stderr, "passwd: fdopen failed?\n");
                    146:                exit(1);
                    147:        }
                    148:        if ((dp = dbm_open(passwd, O_RDWR, 0644)) == NULL) {
                    149:                err = errno;
                    150:                fprintf(stderr, "Warning: dbm_open failed: ");
                    151:                errno = err;
                    152:                perror(passwd);
                    153:        } else if (flock(dp->dbm_dirf, LOCK_EX) < 0) {
                    154:                perror("Warning: lock failed");
                    155:                dbm_close(dp);
                    156:                dp = NULL;
                    157:        }
                    158:        unlimit(RLIMIT_CPU);
                    159:        unlimit(RLIMIT_FSIZE);
                    160:        /*
                    161:         * Copy passwd to temp, replacing matching lines
                    162:         * with new password.
                    163:         */
                    164:        while ((pwd = getpwent()) != NULL) {
                    165:                if (strcmp(pwd->pw_name, uname) == 0) {
                    166:                        if (u && u != pwd->pw_uid) {
                    167:                                fprintf(stderr, "passwd: permission denied.\n");
                    168:                                goto out;
                    169:                        }
                    170:                        if (dochfn)
                    171:                                pwd->pw_gecos = cp;
                    172:                        else if (dochsh)
                    173:                                pwd->pw_shell = cp;
                    174:                        else
                    175:                                pwd->pw_passwd = cp;
                    176:                        if (pwd->pw_gecos[0] == '*')    /* ??? */
                    177:                                pwd->pw_gecos++;
                    178:                        replace(dp, pwd);
                    179:                }
                    180:                fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
                    181:                        pwd->pw_name,
                    182:                        pwd->pw_passwd,
                    183:                        pwd->pw_uid,
                    184:                        pwd->pw_gid,
                    185:                        pwd->pw_gecos,
                    186:                        pwd->pw_dir,
                    187:                        pwd->pw_shell);
                    188:        }
                    189:        endpwent();
                    190:        if (dp != NULL && dbm_error(dp))
                    191:                fprintf(stderr, "Warning: dbm_store failed\n");
                    192:        (void) fflush(tf);
                    193:        if (ferror(tf)) {
                    194:                fprintf(stderr, "Warning: %s write error, %s not updated\n",
                    195:                    temp, passwd);
                    196:                goto out;
                    197:        }
                    198:        (void) fclose(tf);
                    199:        if (dp != NULL)
                    200:                dbm_close(dp);
                    201:        if (rename(temp, passwd) < 0) {
                    202:                perror("passwd: rename");
                    203:        out:
                    204:                (void) unlink(temp);
                    205:                exit(1);
                    206:        }
                    207:        exit(0);
                    208: }
                    209: 
                    210: unlimit(lim)
                    211: {
                    212:        struct rlimit rlim;
                    213: 
                    214:        rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
                    215:        (void) setrlimit(lim, &rlim);
                    216: }
                    217: 
                    218: /*
                    219:  * Replace the password entry in the dbm data base with pwd.
                    220:  */
                    221: replace(dp, pwd)
                    222:        DBM *dp;
                    223:        struct passwd *pwd;
                    224: {
                    225:        datum key, content;
                    226:        register char *cp, *tp;
                    227:        char buf[BUFSIZ];
                    228: 
                    229:        if (dp == NULL)
                    230:                return;
                    231: 
                    232:        cp = buf;
                    233: #define        COMPACT(e)      tp = pwd->pw_/**/e; while (*cp++ = *tp++);
                    234:        COMPACT(name);
                    235:        COMPACT(passwd);
                    236:        bcopy((char *)&pwd->pw_uid, cp, sizeof (int));
                    237:        cp += sizeof (int);
                    238:        bcopy((char *)&pwd->pw_gid, cp, sizeof (int));
                    239:        cp += sizeof (int);
                    240:        bcopy((char *)&pwd->pw_quota, cp, sizeof (int));
                    241:        cp += sizeof (int);
                    242:        COMPACT(comment);
                    243:        COMPACT(gecos);
                    244:        COMPACT(dir);
                    245:        COMPACT(shell);
                    246:        content.dptr = buf;
                    247:        content.dsize = cp - buf;
                    248:        key.dptr = pwd->pw_name;
                    249:        key.dsize = strlen(pwd->pw_name);
                    250:        dbm_store(dp, key, content, DBM_REPLACE);
                    251:        key.dptr = (char *)&pwd->pw_uid;
                    252:        key.dsize = sizeof (int);
                    253:        dbm_store(dp, key, content, DBM_REPLACE);
                    254: }
                    255: 
                    256: char *
                    257: getnewpasswd(pwd, u)
                    258:        register struct passwd *pwd;
                    259:        int u;
                    260: {
                    261:        char saltc[2];
                    262:        long salt;
                    263:        int i, insist = 0, ok, flags;
                    264:        int c, pwlen;
                    265:        static char pwbuf[10];
                    266:        long time();
                    267:        char *crypt(), *pw, *p;
                    268: 
                    269:        if (pwd->pw_passwd[0] && u != 0) {
                    270:                (void) strcpy(pwbuf, getpass("Old password:"));
                    271:                pw = crypt(pwbuf, pwd->pw_passwd);
                    272:                if (strcmp(pw, pwd->pw_passwd) != 0) {
                    273:                        printf("Sorry.\n");
                    274:                        exit(1);
                    275:                }
                    276:        }
                    277: tryagain:
                    278:        (void) strcpy(pwbuf, getpass("New password:"));
                    279:        pwlen = strlen(pwbuf);
                    280:        if (pwlen == 0) {
                    281:                printf("Password unchanged.\n");
                    282:                exit(1);
                    283:        }
                    284:        /*
                    285:         * Insure password is of reasonable length and
                    286:         * composition.  If we really wanted to make things
                    287:         * sticky, we could check the dictionary for common
                    288:         * words, but then things would really be slow.
                    289:         */
                    290:        ok = 0;
                    291:        flags = 0;
                    292:        p = pwbuf;
                    293:        while (c = *p++) {
                    294:                if (c >= 'a' && c <= 'z')
                    295:                        flags |= 2;
                    296:                else if (c >= 'A' && c <= 'Z')
                    297:                        flags |= 4;
                    298:                else if (c >= '0' && c <= '9')
                    299:                        flags |= 1;
                    300:                else
                    301:                        flags |= 8;
                    302:        }
                    303:        if (flags >= 7 && pwlen >= 4)
                    304:                ok = 1;
                    305:        if ((flags == 2 || flags == 4) && pwlen >= 6)
                    306:                ok = 1;
                    307:        if ((flags == 3 || flags == 5 || flags == 6) && pwlen >= 5)
                    308:                ok = 1;
                    309:        if (!ok && insist < 2) {
                    310:                printf("Please use %s.\n", flags == 1 ?
                    311:                        "at least one non-numeric character" :
                    312:                        "a longer password");
                    313:                insist++;
                    314:                goto tryagain;
                    315:        }
                    316:        if (strcmp(pwbuf, getpass("Retype new password:")) != 0) {
                    317:                printf("Mismatch - password unchanged.\n");
                    318:                exit(1);
                    319:        }
                    320:        (void) time(&salt);
                    321:        salt = 9 * getpid();
                    322:        saltc[0] = salt & 077;
                    323:        saltc[1] = (salt>>6) & 077;
                    324:        for (i = 0; i < 2; i++) {
                    325:                c = saltc[i] + '.';
                    326:                if (c > '9')
                    327:                        c += 7;
                    328:                if (c > 'Z')
                    329:                        c += 6;
                    330:                saltc[i] = c;
                    331:        }
                    332:        return (crypt(pwbuf, saltc));
                    333: }
                    334: 
                    335: char *
                    336: getloginshell(pwd, u, arg)
                    337:        struct passwd *pwd;
                    338:        int u;
                    339:        char *arg;
                    340: {
                    341:        static char newshell[BUFSIZ];
                    342:        char *cp, *valid, *getusershell();
                    343: 
                    344:        if (pwd->pw_shell == 0 || *pwd->pw_shell == '\0')
                    345:                pwd->pw_shell = DEFSHELL;
                    346:        if (u != 0) {
                    347:                for (valid = getusershell(); valid; valid = getusershell())
                    348:                        if (strcmp(pwd->pw_shell, valid) == 0)
                    349:                                break;
                    350:                if (valid == NULL) {
                    351:                        printf("Cannot change from restricted shell %s\n",
                    352:                                pwd->pw_shell);
                    353:                        exit(1);
                    354:                }
                    355:        }
                    356:        if (arg != 0) {
                    357:                (void) strncpy(newshell, arg, sizeof newshell - 1);
                    358:                newshell[sizeof newshell - 1] = 0;
                    359:        } else {
                    360:                printf("Old shell: %s\nNew shell: ", pwd->pw_shell);
                    361:                (void)fgets(newshell, sizeof (newshell) - 1, stdin);
                    362:                cp = index(newshell, '\n');
                    363:                if (cp)
                    364:                        *cp = '\0';
                    365:        }
                    366:        if (newshell[0] == '\0' || strcmp(newshell, pwd->pw_shell) == 0) {
                    367:                printf("Login shell unchanged.\n");
                    368:                exit(1);
                    369:        }
                    370:        /*
                    371:         * Allow user to give shell name w/o preceding pathname.
                    372:         */
                    373:        if (u == 0) {
                    374:                valid = newshell;
                    375:        } else {
                    376:                for (valid = getusershell(); valid; valid = getusershell()) {
                    377:                        if (newshell[0] == '/') {
                    378:                                cp = valid;
                    379:                        } else {
                    380:                                cp = rindex(valid, '/');
                    381:                                if (cp == 0)
                    382:                                        cp = valid;
                    383:                                else
                    384:                                        cp++;
                    385:                        }
                    386:                        if (strcmp(newshell, cp) == 0)
                    387:                                break;
                    388:                }
                    389:        }
                    390:        if (valid == 0) {
                    391:                printf("%s is unacceptable as a new shell.\n",
                    392:                    newshell);
                    393:                exit(1);
                    394:        }
                    395:        if (access(valid, X_OK) < 0) {
                    396:                printf("%s is unavailable.\n", valid);
                    397:                exit(1);
                    398:        }
                    399:        if (strcmp(valid, DEFSHELL) == 0)
                    400:                valid[0] = '\0';
                    401:        return (valid);
                    402: }
                    403: 
                    404: struct default_values {
                    405:        char *name;
                    406:        char *office_num;
                    407:        char *office_phone;
                    408:        char *home_phone;
                    409: };
                    410: 
                    411: /*
                    412:  * Get name, room number, school phone, and home phone.
                    413:  */
                    414: char *
                    415: getfingerinfo(pwd)
                    416:        struct passwd *pwd;
                    417: {
                    418:        char in_str[BUFSIZ];
                    419:        struct default_values *defaults, *get_defaults();
                    420:        static char answer[4*BUFSIZ];
                    421: 
                    422:        answer[0] = '\0';
                    423:        defaults = get_defaults(pwd->pw_gecos);
                    424:        printf("Default values are printed inside of '[]'.\n");
                    425:        printf("To accept the default, type <return>.\n");
                    426:        printf("To have a blank entry, type the word 'none'.\n");
                    427:        /*
                    428:         * Get name.
                    429:         */
                    430:        do {
                    431:                printf("\nName [%s]: ", defaults->name);
                    432:                (void) fgets(in_str, BUFSIZ, stdin);
                    433:                if (special_case(in_str, defaults->name)) 
                    434:                        break;
                    435:        } while (illegal_input(in_str));
                    436:        (void) strcpy(answer, in_str);
                    437:        /*
                    438:         * Get room number.
                    439:         */
                    440:        do {
                    441:                printf("Room number (Exs: 597E or 197C) [%s]: ",
                    442:                        defaults->office_num);
                    443:                (void) fgets(in_str, BUFSIZ, stdin);
                    444:                if (special_case(in_str, defaults->office_num))
                    445:                        break;
                    446:        } while (illegal_input(in_str) || illegal_building(in_str));
                    447:        (void) strcat(strcat(answer, ","), in_str);
                    448:        /*
                    449:         * Get office phone number.
                    450:         * Remove hyphens.
                    451:         */
                    452:        do {
                    453:                printf("Office Phone (Ex: 6426000) [%s]: ",
                    454:                        defaults->office_phone);
                    455:                (void) fgets(in_str, BUFSIZ, stdin);
                    456:                if (special_case(in_str, defaults->office_phone))
                    457:                        break;
                    458:                remove_hyphens(in_str);
                    459:        } while (illegal_input(in_str) || not_all_digits(in_str));
                    460:        (void) strcat(strcat(answer, ","), in_str);
                    461:        /*
                    462:         * Get home phone number.
                    463:         * Remove hyphens if present.
                    464:         */
                    465:        do {
                    466:                printf("Home Phone (Ex: 9875432) [%s]: ", defaults->home_phone);
                    467:                (void) fgets(in_str, BUFSIZ, stdin);
                    468:                if (special_case(in_str, defaults->home_phone))
                    469:                        break;
                    470:                remove_hyphens(in_str);
                    471:        } while (illegal_input(in_str) || not_all_digits(in_str));
                    472:        (void) strcat(strcat(answer, ","), in_str);
                    473:        if (strcmp(answer, pwd->pw_gecos) == 0) {
                    474:                printf("Finger information unchanged.\n");
                    475:                exit(1);
                    476:        }
                    477:        return (answer);
                    478: }
                    479: 
                    480: /*
                    481:  * Prints an error message if a ':' or a newline is found in the string.
                    482:  * A message is also printed if the input string is too long.
                    483:  * The password file uses :'s as seperators, and are not allowed in the "gcos"
                    484:  * field.  Newlines serve as delimiters between users in the password file,
                    485:  * and so, those too, are checked for.  (I don't think that it is possible to
                    486:  * type them in, but better safe than sorry)
                    487:  *
                    488:  * Returns '1' if a colon or newline is found or the input line is too long.
                    489:  */
                    490: illegal_input(input_str)
                    491:        char *input_str;
                    492: {
                    493:        char *ptr;
                    494:        int error_flag = 0;
                    495:        int length = strlen(input_str);
                    496: 
                    497:        if (index(input_str, ':')) {
                    498:                printf("':' is not allowed.\n");
                    499:                error_flag = 1;
                    500:        }
                    501:        if (input_str[length-1] != '\n') {
                    502:                /* the newline and the '\0' eat up two characters */
                    503:                printf("Maximum number of characters allowed is %d\n",
                    504:                        BUFSIZ-2);
                    505:                /* flush the rest of the input line */
                    506:                while (getchar() != '\n')
                    507:                        /* void */;
                    508:                error_flag = 1;
                    509:        }
                    510:        /*
                    511:         * Delete newline by shortening string by 1.
                    512:         */
                    513:        input_str[length-1] = '\0';
                    514:        /*
                    515:         * Don't allow control characters, etc in input string.
                    516:         */
                    517:        for (ptr=input_str; *ptr != '\0'; ptr++) {
                    518:                if ((int) *ptr < 040) {
                    519:                        printf("Control characters are not allowed.\n");
                    520:                        error_flag = 1;
                    521:                        break;
                    522:                }
                    523:        }
                    524:        return (error_flag);
                    525: }
                    526: 
                    527: /*
                    528:  * Removes '-'s from the input string.
                    529:  */
                    530: remove_hyphens(str)
                    531:        char *str;
                    532: {
                    533:        char *hyphen;
                    534: 
                    535:        while ((hyphen = index(str, '-')) != NULL)
                    536:                (void) strcpy(hyphen, hyphen+1);
                    537: }
                    538: 
                    539: /*
                    540:  *  Checks to see if 'str' contains only digits (0-9).  If not, then
                    541:  *  an error message is printed and '1' is returned.
                    542:  */
                    543: not_all_digits(str)
                    544:        char *str;
                    545: {
                    546:        char *ptr;
                    547: 
                    548:        for (ptr = str; *ptr != '\0'; ++ptr)
                    549:                if (!isdigit(*ptr)) {
                    550:                        printf("Phone numbers can only contain digits.\n");
                    551:                        return (1);
                    552:                }
                    553:        return (0);
                    554: }
                    555: 
                    556: /*
                    557:  * Deal with Berkeley buildings.  Abbreviating Cory to C and Evans to E.
                    558:  * Correction changes "str".
                    559:  *
                    560:  * Returns 1 if incorrect room format.
                    561:  * 
                    562:  * Note: this function assumes that the newline has been removed from str.
                    563:  */
                    564: illegal_building(str)
                    565:        register char *str;
                    566: {
                    567:        int length = strlen(str);
                    568:        register char *ptr;
                    569: 
                    570:        /*
                    571:         * If the string is [Ee]vans or [Cc]ory or ends in
                    572:         * [ \t0-9][Ee]vans or [ \t0-9M][Cc]ory, then contract the name
                    573:         * into 'E' or 'C', as the case may be, and delete leading blanks.
                    574:         */
                    575:        if (length >= 5 && strcmp(ptr = str + length - 4, "vans") == 0 &&
                    576:            (*--ptr == 'e' || *ptr == 'E') &&
                    577:            (--ptr < str || isspace(*ptr) || isdigit(*ptr))) {
                    578:                for (; ptr > str && isspace(*ptr); ptr--)
                    579:                        ;
                    580:                ptr++;
                    581:                *ptr++ = 'E';
                    582:                *ptr = '\0';
                    583:        } else
                    584:        if (length >= 4 && strcmp(ptr = str + length - 3, "ory") == 0 &&
                    585:            (*--ptr == 'c' || *ptr == 'C') &&
                    586:            (--ptr < str || *ptr == 'M' || isspace(*ptr) || isdigit(*ptr))) {
                    587:                for (; ptr > str && isspace(*ptr); ptr--)
                    588:                        ;
                    589:                ptr++;
                    590:                *ptr++ = 'C';
                    591:                *ptr = '\0';
                    592:        }
                    593:        return (0);
                    594: }
                    595: 
                    596: /*
                    597:  * get_defaults picks apart "str" and returns a structure points.
                    598:  * "str" contains up to 4 fields separated by commas.
                    599:  * Any field that is missing is set to blank.
                    600:  */
                    601: struct default_values *
                    602: get_defaults(str)
                    603:        char *str;
                    604: {
                    605:        struct default_values *answer;
                    606: 
                    607:        answer = (struct default_values *)
                    608:                malloc((unsigned)sizeof(struct default_values));
                    609:        if (answer == (struct default_values *) NULL) {
                    610:                fprintf(stderr,
                    611:                        "\nUnable to allocate storage in get_defaults!\n");
                    612:                exit(1);
                    613:        }
                    614:        /*
                    615:         * Values if no corresponding string in "str".
                    616:         */
                    617:        answer->name = str;
                    618:        answer->office_num = "";
                    619:        answer->office_phone = "";
                    620:        answer->home_phone = "";
                    621:        str = index(answer->name, ',');
                    622:        if (str == 0) 
                    623:                return (answer);
                    624:        *str = '\0';
                    625:        answer->office_num = str + 1;
                    626:        str = index(answer->office_num, ',');
                    627:        if (str == 0) 
                    628:                return (answer);
                    629:        *str = '\0';
                    630:        answer->office_phone = str + 1;
                    631:        str = index(answer->office_phone, ',');
                    632:        if (str == 0) 
                    633:                return (answer);
                    634:        *str = '\0';
                    635:        answer->home_phone = str + 1;
                    636:        return (answer);
                    637: }
                    638: 
                    639: /*
                    640:  *  special_case returns true when either the default is accepted
                    641:  *  (str = '\n'), or when 'none' is typed.  'none' is accepted in
                    642:  *  either upper or lower case (or any combination).  'str' is modified
                    643:  *  in these two cases.
                    644:  */
                    645: special_case(str,default_str)
                    646:        char *str, *default_str;
                    647: {
                    648:        static char word[] = "none\n";
                    649:        char *ptr, *wordptr;
                    650: 
                    651:        /*
                    652:         *  If the default is accepted, then change the old string do the 
                    653:         *  default string.
                    654:         */
                    655:        if (*str == '\n') {
                    656:                (void) strcpy(str, default_str);
                    657:                return (1);
                    658:        }
                    659:        /*
                    660:         *  Check to see if str is 'none'.  (It is questionable if case
                    661:         *  insensitivity is worth the hair).
                    662:         */
                    663:        wordptr = word-1;
                    664:        for (ptr = str; *ptr != '\0'; ++ptr) {
                    665:                ++wordptr;
                    666:                if (*wordptr == '\0')   /* then words are different sizes */
                    667:                        return (0);
                    668:                if (*ptr == *wordptr)
                    669:                        continue;
                    670:                if (isupper(*ptr) && (tolower(*ptr) == *wordptr))
                    671:                        continue;
                    672:                /*
                    673:                 * At this point we have a mismatch, so we return
                    674:                 */
                    675:                return (0);
                    676:        }
                    677:        /*
                    678:         * Make sure that words are the same length.
                    679:         */
                    680:        if (*(wordptr+1) != '\0')
                    681:                return (0);
                    682:        /*
                    683:         * Change 'str' to be the null string
                    684:         */
                    685:        *str = '\0';
                    686:        return (1);
                    687: }

unix.superglobalmegacorp.com

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