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

unix.superglobalmegacorp.com

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