Annotation of 43BSD/bin/passwd.c, revision 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.