Annotation of cci/usr/src/ucb/chfn.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *sccsid = "@@(#)chfn.c     4.6 (Berkeley) 7/10/83";
                      3: #endif lint
                      4: 
                      5: /*
                      6:  *      changefinger - change finger entries
                      7:  */
                      8: #include <stdio.h>
                      9: #include <signal.h>
                     10: #include <pwd.h>
                     11: #include <sys/time.h>
                     12: #include <sys/resource.h>
                     13: #include <sys/file.h>
                     14: #include <ctype.h>
                     15: 
                     16: struct default_values {
                     17:        char *name;
                     18:        char *office_num;
                     19:        char *office_phone;
                     20:        char *home_phone;
                     21: };
                     22: 
                     23: char   passwd[] = "/etc/passwd";
                     24: char   temp[]   = "/etc/ptmp";
                     25: struct passwd *pwd;
                     26: struct passwd *getpwent(), *getpwnam(), *getpwuid();
                     27: int    endpwent();
                     28: char   *crypt();
                     29: char   *getpass();
                     30: int    hadQ = 0, hadZ = 0;
                     31: 
                     32: main(argc, argv)
                     33:        int argc;
                     34:        char *argv[];
                     35: {
                     36:        int user_uid;
                     37:        char replacement[4*BUFSIZ];
                     38:        int fd;
                     39:        FILE *tf;
                     40: 
                     41:        if (argc > 2) {
                     42:                printf("Usage: changefinger [user]\n");
                     43:                exit(1);
                     44:        }
                     45:        /*
                     46:         * Error check to make sure the user (foolishly) typed their own name.
                     47:         */
                     48:        user_uid = getuid();
                     49:        if ((argc == 2) && (user_uid != 0)) {
                     50:                pwd = getpwnam(argv[1]);
                     51:                if (pwd == NULL) {
                     52:                        printf("%s%s%s%s%s%s%s%s",
                     53:                                "There is no account for ", argv[1],
                     54:                                " on this machine.\n", 
                     55:                                "You probably mispelled your login name;\n",
                     56:                                "only root is allowed to change another",
                     57:                                " person's finger entry.\n",
                     58:                                "Note:  you do not need to type your login",
                     59:                                " name as an argument.\n");
                     60:                        exit(1);
                     61:                }
                     62:                if (pwd->pw_uid != user_uid) {
                     63:                        printf("%s%s",
                     64:                                "You are not allowed to change another",
                     65:                                " person's finger entry.\n");
                     66:                        exit(1);
                     67:                }
                     68:        }
                     69:        /*
                     70:         * If root is changing a finger entry, then find the uid that
                     71:         * corresponds to the user's login name.
                     72:         */
                     73:        if ((argc == 2) && (user_uid == 0)) {
                     74:                pwd = getpwnam(argv[1]);
                     75:                if (pwd == NULL) {
                     76:                        printf("There is no account for %s on this machine\n", 
                     77:                                pwd->pw_name);
                     78:                        exit(1);
                     79:                }
                     80:                user_uid = pwd->pw_uid;
                     81:        }
                     82:        if (argc == 1) {
                     83:                pwd = getpwuid(user_uid);
                     84:                if (pwd == NULL) {
                     85:                        fprintf(stderr, "No passwd file entry!?\n");
                     86:                        exit(1);
                     87:                }
                     88:        }
                     89:        /*
                     90:         * Collect name, office number, office phone, and home phone.
                     91:         */
                     92:        get_info(pwd->pw_gecos, replacement);
                     93: 
                     94:        (void) signal(SIGHUP, SIG_IGN);
                     95:        (void) signal(SIGINT, SIG_IGN);
                     96:        (void) signal(SIGQUIT, SIG_IGN);
                     97:        (void) signal(SIGTSTP, SIG_IGN);
                     98:        (void) umask(0);
                     99:        if ((fd = open(temp, O_CREAT|O_EXCL|O_RDWR, 0644)) < 0) {
                    100:                printf("Temporary file busy -- try again\n");
                    101:                exit(1);
                    102:        }
                    103:        if ((tf = fdopen(fd, "w")) == NULL) {
                    104:                printf("Absurd fdopen failure - seek help\n");
                    105:                goto out;
                    106:        }
                    107:        unlimit(RLIMIT_CPU);
                    108:        unlimit(RLIMIT_FSIZE);
                    109:        /*
                    110:         * Copy passwd to temp, replacing matching lines
                    111:         * with new gecos field.
                    112:         */
                    113:        while ((pwd = getpwent()) != NULL) {
                    114:                if (pwd->pw_uid == user_uid)
                    115:                        pwd->pw_gecos = replacement;
                    116:                fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
                    117:                        pwd->pw_name,
                    118:                        pwd->pw_passwd,
                    119:                        pwd->pw_uid,
                    120:                        pwd->pw_gid,
                    121:                        pwd->pw_gecos,
                    122:                        pwd->pw_dir,
                    123:                        pwd->pw_shell);
                    124:        }
                    125:        (void) endpwent();
                    126:        if (rename(temp, passwd) < 0) {
                    127:                fprintf(stderr, "chfn: "); perror("rename");
                    128:   out:
                    129:                (void) unlink(temp);
                    130:                exit(1);
                    131:        }
                    132:        (void) fclose(tf);
                    133:        exit(0);
                    134: }
                    135: 
                    136: unlimit(lim)
                    137: {
                    138:        struct rlimit rlim;
                    139: 
                    140:        rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
                    141:        (void) setrlimit(lim, &rlim);
                    142: }
                    143: 
                    144: /*
                    145:  * Get name, office number, office phone, and home phone.
                    146:  */
                    147: get_info(gecos_field, answer)
                    148:        char *gecos_field;
                    149:        char *answer;
                    150: {
                    151:        char *strcpy(), *strcat();
                    152:        char in_str[BUFSIZ];
                    153:        struct default_values *defaults, *get_defaults();
                    154:        int phflag;
                    155: 
                    156:        answer[0] = '\0';
                    157:        defaults = get_defaults(gecos_field);
                    158:        printf("Default values are printed inside of '[]'.\n");
                    159:        printf("Examples are printed inside of '()'.\n");
                    160:        printf("To accept the default, type <return>.\n");
                    161:        printf("To have a blank entry, type the word 'none'.\n");
                    162:        /*
                    163:         * Get name.
                    164:         */
                    165:        do {
                    166:                printf("\nName [%s]: ", defaults->name);
                    167:                (void) fgets(in_str, BUFSIZ, stdin);
                    168:                if (special_case(in_str, defaults->name)) 
                    169:                        break;
                    170:        } while (illegal_input(in_str));
                    171:        (void) strcpy(answer, in_str);
                    172:        /*
                    173:         * Get office number.
                    174:         */
                    175: again:
                    176:        do {
                    177:                printf("Office number (Exs: 597E or 197C) [%s]: ",
                    178:                        defaults->office_num);
                    179:                (void) fgets(in_str, BUFSIZ, stdin);
                    180:                if (special_case(in_str, defaults->office_num)) {
                    181:                        if (hadQ)
                    182:                                if (*in_str != '\0')
                    183:                                        strcat(in_str, "Q");
                    184:                        break;
                    185:                }
                    186:        } while (illegal_input(in_str));
                    187:        if (illegal_building(in_str))
                    188:                strcat(in_str, "Q");
                    189:        if (strlen(in_str) > 10) {
                    190:                printf("office number must be no more than 9 characters\n");
                    191:                goto again;
                    192:        }
                    193:        (void) strcat(strcat(answer, ","), in_str);
                    194:        /*
                    195:         * Get office phone number.
                    196:         * Remove hyphens and 642, x2, or 2 prefixes if present.
                    197:         */
                    198:        do {
                    199:                printf("Office Phone (Ex: 1632) [%s]: ",
                    200:                        defaults->office_phone);
                    201:                (void) fgets(in_str, BUFSIZ, stdin);
                    202:                phflag = 0;
                    203:                if (special_case(in_str, defaults->office_phone)) {
                    204:                        phflag = 1;
                    205:                        if (hadZ)
                    206:                                if (*in_str != '\0')
                    207:                                        strcat(in_str, "Z");
                    208:                        break;
                    209:                }
                    210:                remove_hyphens(in_str);
                    211:                if ((strlen(in_str) == 8) && (strcmpn(in_str, "642", 3) == 0)) {
                    212:                        (void) strcpy(in_str, in_str+3);
                    213:                        phflag = 1;
                    214:                }
                    215:                if ((strlen(in_str) == 7) && (strcmpn(in_str, "x2", 2) == 0)) {
                    216:                        (void) strcpy(in_str, in_str+2);
                    217:                        phflag = 1;
                    218:                }
                    219:                if ((strlen(in_str) == 6) && (in_str[0] == '2')) {
                    220:                        (void) strcpy(in_str, in_str+1);
                    221:                        phflag = 1;
                    222:                }
                    223:        } while (illegal_input(in_str) || wrong_length(in_str, 7));
                    224:        if (!phflag)
                    225:                strcat(in_str, "Z");
                    226:        (void) strcat(strcat(answer, ","), in_str);
                    227:        /*
                    228:         * Get home phone number.
                    229:         * Remove hyphens if present.
                    230:         */
                    231:        do {
                    232:                printf("Home Phone (Ex: 9875432) [%s]: ", defaults->home_phone);
                    233:                (void) fgets(in_str, BUFSIZ, stdin);
                    234:                if (special_case(in_str, defaults->home_phone))
                    235:                        break;
                    236:                remove_hyphens(in_str);
                    237:        } while (illegal_input(in_str));
                    238:        (void) strcat(strcat(answer, ","), in_str);
                    239: }
                    240: 
                    241: /*
                    242:  * Prints an error message if a ':' or a newline is found in the string.
                    243:  * A message is also printed if the input string is too long.
                    244:  * The password file uses :'s as seperators, and are not allowed in the "gcos"
                    245:  * field.  Newlines serve as delimiters between users in the password file,
                    246:  * and so, those too, are checked for.  (I don't think that it is possible to
                    247:  * type them in, but better safe than sorry)
                    248:  *
                    249:  * Returns '1' if a colon or newline is found or the input line is too long.
                    250:  */
                    251: illegal_input(input_str)
                    252:        char *input_str;
                    253: {
                    254:        char *index();
                    255:        char *ptr;
                    256:        int error_flag = 0;
                    257:        int length = strlen(input_str);
                    258: 
                    259:        if (index(input_str, ':')) {
                    260:                printf("':' is not allowed.\n");
                    261:                error_flag = 1;
                    262:        }
                    263:        if (input_str[length-1] != '\n') {
                    264:                /* the newline and the '\0' eat up two characters */
                    265:                printf("Maximum number of characters allowed is %d\n",
                    266:                        BUFSIZ-2);
                    267:                /* flush the rest of the input line */
                    268:                while (getchar() != '\n')
                    269:                        /* void */;
                    270:                error_flag = 1;
                    271:        }
                    272:        /*
                    273:         * Delete newline by shortening string by 1.
                    274:         */
                    275:        input_str[length-1] = '\0';
                    276:        /*
                    277:         * Don't allow control characters, etc in input string.
                    278:         */
                    279:        for (ptr=input_str; *ptr != '\0'; ptr++) {
                    280:                if ((int) *ptr < 040) {
                    281:                        printf("Control characters are not allowed.\n");
                    282:                        error_flag = 1;
                    283:                        break;
                    284:                }
                    285:        }
                    286:        return(error_flag);
                    287: }
                    288: 
                    289: /*
                    290:  * Removes '-'s from the input string.
                    291:  */
                    292: remove_hyphens(str)
                    293:        char *str;
                    294: {
                    295:        char *hyphen, *index(), *strcpy();
                    296: 
                    297:        while ((hyphen=index(str, '-')) != NULL) {
                    298:                (void) strcpy(hyphen, hyphen+1);
                    299:        }
                    300: }
                    301: 
                    302: /*
                    303:  * Returns 1 when the length of the input string is not zero and
                    304:  * greater than n.
                    305:  * Prints an error message in this case.
                    306:  */
                    307: wrong_length(str, n)
                    308:        char *str;
                    309:        int n;
                    310: {
                    311: 
                    312:        if ((strlen(str) != 0) && (strlen(str) >= n)) {
                    313:                printf("The phone number should be less than %d digits long.\n",
                    314:                        n);
                    315:                return(1);
                    316:        }
                    317:        return(0);
                    318: }
                    319: 
                    320: /*
                    321:  * Make sure that building is 'E', 'C' or 'L'.
                    322:  * Error correction is done if building is 'e', 'c', 'l',
                    323:  * "evans", "cory" or "lbl".
                    324:  * Correction changes "str".
                    325:  * The finger program determines the building by looking at the last
                    326:  * character.  Currently, finger only allows that character to be 'E', 'C'
                    327:  * or 'L'.
                    328:  *
                    329:  * Returns 1 if incorrect office format.
                    330:  * 
                    331:  * Note: this function assumes that the newline has been removed from str.
                    332:  */
                    333: illegal_building(str)
                    334:        char *str;
                    335: {
                    336:        int length = strlen(str);
                    337:        char *last_ch, *ptr;
                    338: 
                    339:        /*
                    340:         * Zero length strings are acceptable input.
                    341:         */
                    342:        if (length == 0)
                    343:                return(0);
                    344:        /*
                    345:         * Delete "vans", "ory" and "bl".
                    346:         */
                    347:        if (strcmpn(str+length-4, "vans", 4) == 0) {
                    348:                length -= 4;
                    349:                str[length] = '\0';
                    350:        }
                    351:        if (strcmpn(str+length-3, "ory", 3) == 0) {
                    352:                length -= 3;
                    353:                str[length] = '\0';
                    354:        }
                    355:        if (strcmpn(str+length-2, "bl", 2) == 0) {
                    356:                length -= 2;
                    357:                str[length] = '\0';
                    358:        }
                    359:        last_ch = str+length-1;
                    360:        /*
                    361:         * Now change e to E or c to C or l to L.
                    362:         */
                    363:        if (*last_ch == 'e')
                    364:                *last_ch = 'E';
                    365:        if (*last_ch == 'c')
                    366:                *last_ch = 'C';
                    367:        if (*last_ch == 'l')
                    368:                *last_ch = 'L';
                    369:        /*
                    370:         * Delete any spaces before the E, C or L.
                    371:         */
                    372:        for (ptr=last_ch-1; ptr>str; ptr--) {
                    373:                if (*ptr != ' ')
                    374:                        break;
                    375:        }
                    376:        (void) strcpy(ptr+1, last_ch);
                    377:        /*
                    378:         * Make sure building is evans, cory or lbl.
                    379:         */
                    380:        if ((*last_ch != 'E') && (*last_ch != 'C') && (*last_ch != 'L'))
                    381:                return(1);
                    382:        return(0);
                    383: }
                    384: 
                    385: /* get_defaults picks apart "str" and returns a structure points.
                    386:  * "str" contains up to 4 fields separated by commas.
                    387:  * Any field that is missing is set to blank.
                    388:  */
                    389: struct default_values 
                    390: *get_defaults(str)
                    391:        char *str;
                    392: {
                    393:        struct default_values *answer;
                    394:        char *malloc(), *index();
                    395:        int len;
                    396: 
                    397:        answer = (struct default_values *)
                    398:                malloc((unsigned)sizeof(struct default_values));
                    399:        if (answer == (struct default_values *) NULL) {
                    400:                fprintf(stderr,
                    401:                        "\nUnable to allocate storage in get_defaults!\n");
                    402:                exit(1);
                    403:        }
                    404:        /*
                    405:         * Values if no corresponding string in "str".
                    406:         */
                    407:        answer->name = str;
                    408:        answer->office_num = "";
                    409:        answer->office_phone = "";
                    410:        answer->home_phone = "";
                    411:        str = index(answer->name, ',');
                    412:        if (str == 0)
                    413:                return(answer);
                    414:        *str = '\0';
                    415:        answer->office_num = str + 1;
                    416:        str = index(answer->office_num, ',');
                    417:        if (str == 0)  {
                    418:                len = strlen(answer->office_num);
                    419:                if (answer->office_num[len - 1] == 'Q')  {
                    420:                        answer->office_num[len - 1] = '\0';
                    421:                        hadQ = 1;
                    422:                }
                    423:                return(answer);
                    424:        }
                    425:        *str = '\0';
                    426:        len = strlen(answer->office_num);
                    427:        if (answer->office_num[len - 1] == 'Q')  {
                    428:                answer->office_num[len - 1] = '\0';
                    429:                hadQ = 1;
                    430:        }
                    431:        answer->office_phone = str + 1;
                    432:        str = index(answer->office_phone, ',');
                    433:        if (str == 0)  {
                    434:                len = strlen(answer->office_phone);
                    435:                if (answer->office_phone[len - 1] == 'Z')  {
                    436:                        answer->office_phone[len - 1] = '\0';
                    437:                        hadZ = 1;
                    438:                }
                    439:                return(answer);
                    440:        }
                    441:        *str = '\0';
                    442:        len = strlen(answer->office_phone);
                    443:        if (answer->office_phone[len - 1] == 'Z')  {
                    444:                answer->office_phone[len - 1] = '\0';
                    445:                hadZ = 1;
                    446:        }
                    447:        answer->home_phone = str + 1;
                    448:        return(answer);
                    449: }
                    450: 
                    451: /*
                    452:  *  special_case returns true when either the default is accepted
                    453:  *  (str = '\n'), or when 'none' is typed.  'none' is accepted in
                    454:  *  either upper or lower case (or any combination).  'str' is modified
                    455:  *  in these two cases.
                    456:  */
                    457: int special_case(str,default_str)
                    458:        char *str;
                    459:        char *default_str;
                    460: {
                    461:        static char word[] = "none\n";
                    462:        char *ptr, *wordptr;
                    463: 
                    464:        /*
                    465:         *  If the default is accepted, then change the old string do the 
                    466:         *  default string.
                    467:         */
                    468:        if (*str == '\n') {
                    469:                (void) strcpy(str, default_str);
                    470:                return(1);
                    471:        }
                    472:        /*
                    473:         *  Check to see if str is 'none'.  (It is questionable if case
                    474:         *  insensitivity is worth the hair).
                    475:         */
                    476:        wordptr = word-1;
                    477:        for (ptr=str; *ptr != '\0'; ++ptr) {
                    478:                ++wordptr;
                    479:                if (*wordptr == '\0')   /* then words are different sizes */
                    480:                        return(0);
                    481:                if (*ptr == *wordptr)
                    482:                        continue;
                    483:                if (isupper(*ptr) && (tolower(*ptr) == *wordptr))
                    484:                        continue;
                    485:                /*
                    486:                 * At this point we have a mismatch, so we return
                    487:                 */
                    488:                return(0);
                    489:        }
                    490:        /*
                    491:         * Make sure that words are the same length.
                    492:         */
                    493:        if (*(wordptr+1) != '\0')
                    494:                return(0);
                    495:        /*
                    496:         * Change 'str' to be the null string
                    497:         */
                    498:        *str = '\0';
                    499:        return(1);
                    500: }

unix.superglobalmegacorp.com

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