]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - login-utils/chfn.c
2 * chfn.c -- change your finger information
3 * (c) 1994 by salvatore valente <svalente@athena.mit.edu>
5 * this program is free software. you can redistribute it and
6 * modify it under the terms of the gnu general public license.
7 * there is no warranty.
11 * $Date: 1995/10/12 14:46:35 $
13 * Updated Thu Oct 12 09:19:26 1995 by faith@cs.unc.edu with security
14 * patches from Zefram <A.Main@dcs.warwick.ac.uk>
18 static char rcsId
[] = "$Version: $Id: chfn.c,v 1.8 1995/10/12 14:46:35 faith Exp $ $";
20 #include <sys/types.h>
37 typedef unsigned char boolean
;
41 static char *version_string
= "chfn 0.9a beta";
44 static char buf
[1024];
56 static boolean parse_argv
P((int argc
, char *argv
[], struct finfo
*pinfo
));
57 static void usage
P((FILE *fp
));
58 static void parse_passwd
P((struct passwd
*pw
, struct finfo
*pinfo
));
59 static void ask_info
P((struct finfo
*oldfp
, struct finfo
*newfp
));
60 static char *prompt
P((char *question
, char *def_val
));
61 static int check_gecos_string
P((char *msg
, char *gecos
));
62 static boolean set_changed_data
P((struct finfo
*oldfp
, struct finfo
*newfp
));
63 static int save_new_data
P((struct finfo
*pinfo
));
64 static void *xmalloc
P((int bytes
));
66 extern int strcasecmp
P((char *, char *));
67 extern int setpwnam
P((struct passwd
*pwd
));
69 #define memzero(ptr, size) memset((char *) ptr, 0, size)
77 struct finfo oldf
, newf
;
82 /* whoami is the program name for error messages */
84 if (! whoami
) whoami
= "chfn";
85 for (cp
= whoami
; *cp
; cp
++)
86 if (*cp
== '/') whoami
= cp
+ 1;
89 * "oldf" contains the users original finger information.
90 * "newf" contains the changed finger information, and contains NULL
91 * in fields that haven't been changed.
92 * in the end, "newf" is folded into "oldf".
93 * the reason the new finger information is not put _immediately_ into
94 * "oldf" is that on the command line, new finger information can
95 * be specified before we know what user the information is being
99 memzero (&oldf
, sizeof (oldf
));
100 memzero (&newf
, sizeof (newf
));
102 interactive
= parse_argv (argc
, argv
, &newf
);
103 if (! newf
.username
) {
104 parse_passwd (getpwuid (uid
), &oldf
);
105 if (! oldf
.username
) {
106 fprintf (stderr
, "%s: you (user %d) don't exist.\n", whoami
, uid
);
110 parse_passwd (getpwnam (newf
.username
), &oldf
);
111 if (! oldf
.username
) {
113 fprintf (stderr
, "%s: user \"%s\" does not exist.\n", whoami
, cp
);
118 if (uid
!= 0 && uid
!= oldf
.pw
->pw_uid
) {
124 printf ("Changing finger information for %s.\n", oldf
.username
);
127 /* require password, unless root */
128 if(uid
!= 0 && oldf
.pw
->pw_passwd
&& oldf
.pw
->pw_passwd
[0]) {
129 pwdstr
= getpass("Password: ");
130 if(strncmp(oldf
.pw
->pw_passwd
,
131 crypt(pwdstr
, oldf
.pw
->pw_passwd
), 13)) {
132 puts("Incorrect password.");
139 if (interactive
) ask_info (&oldf
, &newf
);
141 if (! set_changed_data (&oldf
, &newf
)) {
142 printf ("Finger information not changed.\n");
145 status
= save_new_data (&oldf
);
151 * parse the command line arguments.
152 * returns true if no information beyond the username was given.
154 static boolean
parse_argv (argc
, argv
, pinfo
)
159 int index
, c
, status
;
162 static struct option long_options
[] = {
163 { "full-name", required_argument
, 0, 'f' },
164 { "office", required_argument
, 0, 'o' },
165 { "office-phone", required_argument
, 0, 'p' },
166 { "home-phone", required_argument
, 0, 'h' },
167 { "help", no_argument
, 0, 'u' },
168 { "version", no_argument
, 0, 'v' },
169 { NULL
, no_argument
, 0, '0' },
175 c
= getopt_long (argc
, argv
, "f:r:p:h:o:uv", long_options
, &index
);
177 /* version? output version and exit. */
179 printf ("%s\n", version_string
);
186 /* all other options must have an argument. */
191 /* ok, we were given an argument */
194 strcpy (buf
, whoami
); strcat (buf
, ": ");
196 /* now store the argument */
199 pinfo
->full_name
= optarg
;
200 strcat (buf
, "full name");
201 status
= check_gecos_string (buf
, optarg
);
204 pinfo
->office
= optarg
;
205 strcat (buf
, "office");
206 status
= check_gecos_string (buf
, optarg
);
209 pinfo
->office_phone
= optarg
;
210 strcat (buf
, "office phone");
211 status
= check_gecos_string (buf
, optarg
);
214 pinfo
->home_phone
= optarg
;
215 strcat (buf
, "home phone");
216 status
= check_gecos_string (buf
, optarg
);
222 if (status
< 0) exit (status
);
224 /* done parsing arguments. check for a username. */
226 if (optind
+ 1 < argc
) {
230 pinfo
->username
= argv
[optind
];
232 return (! info_given
);
237 * print out a usage message.
239 static void usage (fp
)
242 fprintf (fp
, "Usage: %s [ -f full-name ] [ -o office ] ", whoami
);
243 fprintf (fp
, "[ -p office-phone ]\n [ -h home-phone ] ");
244 fprintf (fp
, "[ --help ] [ --version ]\n");
249 * take a struct password and fill in the fields of the
252 static void parse_passwd (pw
, pinfo
)
260 pinfo
->username
= pw
->pw_name
;
263 pinfo
->full_name
= cp
;
264 cp
= strchr (cp
, ',');
265 if (cp
) { *cp
= 0, cp
++; } else return;
267 cp
= strchr (cp
, ',');
268 if (cp
) { *cp
= 0, cp
++; } else return;
269 pinfo
->office_phone
= cp
;
270 cp
= strchr (cp
, ',');
271 if (cp
) { *cp
= 0, cp
++; } else return;
272 pinfo
->home_phone
= cp
;
273 /* extra fields contain site-specific information, and
274 * can not be changed by this version of chfn. */
275 cp
= strchr (cp
, ',');
276 if (cp
) { *cp
= 0, cp
++; } else return;
283 * prompt the user for the finger information and store it.
285 static void ask_info (oldfp
, newfp
)
289 newfp
->full_name
= prompt ("Name", oldfp
->full_name
);
290 newfp
->office
= prompt ("Office", oldfp
->office
);
291 newfp
->office_phone
= prompt ("Office Phone", oldfp
->office_phone
);
292 newfp
->home_phone
= prompt ("Home Phone", oldfp
->home_phone
);
298 * ask the user for a given field and check that the string is legal.
300 static char *prompt (question
, def_val
)
304 static char *blank
= "none";
309 if (! def_val
) def_val
= "";
310 printf("%s [%s]: ", question
, def_val
);
312 if (fgets (buf
, sizeof (buf
), stdin
) == NULL
) {
313 printf ("\nAborted.\n");
316 /* remove the newline at the end of buf. */
318 while (isspace (*ans
)) ans
++;
320 while (len
> 0 && isspace (ans
[len
-1])) len
--;
321 if (len
<= 0) return NULL
;
323 if (! strcasecmp (ans
, blank
)) return "";
324 if (check_gecos_string (NULL
, ans
) >= 0) break;
326 cp
= (char *) xmalloc (len
+ 1);
332 * check_gecos_string () --
333 * check that the given gecos string is legal. if it's not legal,
334 * output "msg" followed by a description of the problem, and
337 static int check_gecos_string (msg
, gecos
)
343 for (i
= 0; i
< strlen (gecos
); i
++) {
345 if (c
== ',' || c
== ':' || c
== '=' || c
== '"' || c
== '\n') {
346 if (msg
) printf ("%s: ", msg
);
347 printf ("'%c' is not allowed.\n", c
);
351 if (msg
) printf ("%s: ", msg
);
352 printf ("Control characters are not allowed.\n");
360 * set_changed_data () --
361 * incorporate the new data into the old finger info.
363 static boolean
set_changed_data (oldfp
, newfp
)
367 boolean changed
= false;
369 if (newfp
->full_name
) {
370 oldfp
->full_name
= newfp
->full_name
; changed
= true; }
372 oldfp
->office
= newfp
->office
; changed
= true; }
373 if (newfp
->office_phone
) {
374 oldfp
->office_phone
= newfp
->office_phone
; changed
= true; }
375 if (newfp
->home_phone
) {
376 oldfp
->home_phone
= newfp
->home_phone
; changed
= true; }
382 * save_new_data () --
383 * save the given finger info in /etc/passwd.
384 * return zero on success.
386 static int save_new_data (pinfo
)
392 /* null fields will confuse printf(). */
393 if (! pinfo
->full_name
) pinfo
->full_name
= "";
394 if (! pinfo
->office
) pinfo
->office
= "";
395 if (! pinfo
->office_phone
) pinfo
->office_phone
= "";
396 if (! pinfo
->home_phone
) pinfo
->home_phone
= "";
397 if (! pinfo
->other
) pinfo
->other
= "";
399 /* create the new gecos string */
400 len
= (strlen (pinfo
->full_name
) + strlen (pinfo
->office
) +
401 strlen (pinfo
->office_phone
) + strlen (pinfo
->home_phone
) +
402 strlen (pinfo
->other
) + 4);
403 gecos
= (char *) xmalloc (len
+ 1);
404 sprintf (gecos
, "%s,%s,%s,%s,%s", pinfo
->full_name
, pinfo
->office
,
405 pinfo
->office_phone
, pinfo
->home_phone
, pinfo
->other
);
407 /* write the new struct passwd to the passwd file. */
408 pinfo
->pw
->pw_gecos
= gecos
;
409 if (setpwnam (pinfo
->pw
) < 0) {
411 printf( "Finger information *NOT* changed. Try again later.\n" );
414 printf ("Finger information changed.\n");
419 * xmalloc () -- malloc that never fails.
421 static void *xmalloc (bytes
)
427 if (! vp
&& bytes
> 0) {
428 perror ("malloc failed");