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