|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.