Example #1
0
File: chfn.c Project: OPSF/uClinux
/*
 * new_fields - change the user's GECOS information interactively
 *
 * prompt the user for each of the four fields and fill in the fields from
 * the user's response, or leave alone if nothing was entered.
 */
static void new_fields (void)
{
	printf (_("Enter the new value, or press ENTER for the default\n"));

	if (may_change_field ('f'))
		change_field (fullnm, sizeof fullnm, _("Full Name"));
	else
		printf (_("\tFull Name: %s\n"), fullnm);

	if (may_change_field ('r'))
		change_field (roomno, sizeof roomno, _("Room Number"));
	else
		printf (_("\tRoom Number: %s\n"), roomno);

	if (may_change_field ('w'))
		change_field (workph, sizeof workph, _("Work Phone"));
	else
		printf (_("\tWork Phone: %s\n"), workph);

	if (may_change_field ('h'))
		change_field (homeph, sizeof homeph, _("Home Phone"));
	else
		printf (_("\tHome Phone: %s\n"), homeph);

	if (amroot)
		change_field (slop, sizeof slop, _("Other"));
}
Example #2
0
/*
 * new_fields - change the user's GECOS information interactively
 *
 * prompt the user for each of the four fields and fill in the fields from
 * the user's response, or leave alone if nothing was entered.
 */
static void new_fields (void)
{
	puts (_("Enter the new value, or press ENTER for the default"));

	if (may_change_field ('f')) {
		change_field (fullnm, sizeof fullnm, _("Full Name"));
	} else {
		printf (_("\t%s: %s\n"), _("Full Name"), fullnm);
	}

	if (may_change_field ('r')) {
		change_field (roomno, sizeof roomno, _("Room Number"));
	} else {
		printf (_("\t%s: %s\n"), _("Room Number"), fullnm);
	}

	if (may_change_field ('w')) {
		change_field (workph, sizeof workph, _("Work Phone"));
	} else {
		printf (_("\t%s: %s\n"), _("Work Phone"), fullnm);
	}

	if (may_change_field ('h')) {
		change_field (homeph, sizeof homeph, _("Home Phone"));
	} else {
		printf (_("\t%s: %s\n"), _("Home Phone"), fullnm);
	}

	if (amroot) {
		change_field (slop, sizeof slop, _("Other"));
	}
}
Example #3
0
File: chfn.c Project: OPSF/uClinux
/*
 * chfn - change a user's password file information
 *
 *	This command controls the GECOS field information in the password
 *	file entry.
 *
 *	The valid options are
 *
 *	-f	full name
 *	-r	room number
 *	-w	work phone number
 *	-h	home phone number
 *	-o	other information (*)
 *
 *	(*) requires root permission to execute.
 */
int main (int argc, char **argv)
{
	char *cp;		/* temporary character pointer       */
	const struct passwd *pw;	/* password file entry               */
	struct passwd pwent;	/* modified password file entry      */
	char old_gecos[BUFSIZ];	/* buffer for old GECOS fields       */
	char new_gecos[BUFSIZ];	/* buffer for new GECOS fields       */
	int flag;		/* flag currently being processed    */
	int fflg = 0;		/* -f - set full name                */
	int rflg = 0;		/* -r - set room number              */
	int wflg = 0;		/* -w - set work phone number        */
	int hflg = 0;		/* -h - set home phone number        */
	int oflg = 0;		/* -o - set other information        */
	char *user;

#ifdef USE_PAM
	pam_handle_t *pamh = NULL;
	struct passwd *pampw;
	int retval;
#endif

	sanitize_env ();
	setlocale (LC_ALL, "");
	bindtextdomain (PACKAGE, LOCALEDIR);
	textdomain (PACKAGE);

	/*
	 * This command behaves different for root and non-root
	 * users.
	 */
	amroot = (getuid () == 0);

	/*
	 * Get the program name. The program name is used as a
	 * prefix to most error messages.
	 */
	Prog = Basename (argv[0]);

	OPENLOG ("chfn");

	/* 
	 * The remaining arguments will be processed one by one and executed
	 * by this command. The name is the last argument if it does not
	 * begin with a "-", otherwise the name is determined from the
	 * environment and must agree with the real UID. Also, the UID will
	 * be checked for any commands which are restricted to root only.
	 */
	while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) {
		switch (flag) {
		case 'f':
			if (!may_change_field ('f')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			fflg++;
			STRFCPY (fullnm, optarg);
			break;
		case 'h':
			if (!may_change_field ('h')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			hflg++;
			STRFCPY (homeph, optarg);
			break;
		case 'r':
			if (!may_change_field ('r')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			rflg++;
			STRFCPY (roomno, optarg);
			break;
		case 'o':
			if (!amroot) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			oflg++;
			STRFCPY (slop, optarg);
			break;
		case 'w':
			if (!may_change_field ('w')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			wflg++;
			STRFCPY (workph, optarg);
			break;
		default:
			usage ();
		}
	}

	/*
	 * Get the name of the user to check. It is either the command line
	 * name, or the name getlogin() returns.
	 */
	if (optind < argc) {
		user = argv[optind];
		pw = getpwnam (user);
		if (!pw) {
			fprintf (stderr, _("%s: unknown user %s\n"), Prog,
				 user);
			exit (E_NOPERM);
		}
	} else {
		pw = get_my_pwent ();
		if (!pw) {
			fprintf (stderr,
				 _
				 ("%s: Cannot determine your user name.\n"),
				 Prog);
			exit (E_NOPERM);
		}
		user = xstrdup (pw->pw_name);
	}

#ifdef	USE_NIS
	/*
	 * Now we make sure this is a LOCAL password entry for this user ...
	 */
	if (__ispwNIS ()) {
		char *nis_domain;
		char *nis_master;

		fprintf (stderr,
			 _("%s: cannot change user `%s' on NIS client.\n"),
			 Prog, user);

		if (!yp_get_default_domain (&nis_domain) &&
		    !yp_master (nis_domain, "passwd.byname", &nis_master)) {
			fprintf (stderr,
				 _
				 ("%s: `%s' is the NIS master for this client.\n"),
				 Prog, nis_master);
		}
		exit (E_NOPERM);
	}
#endif

	/*
	 * Non-privileged users are only allowed to change the gecos field
	 * if the UID of the user matches the current real UID.
	 */
	if (!amroot && pw->pw_uid != getuid ()) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		closelog ();
		exit (E_NOPERM);
	}
#ifdef WITH_SELINUX
	/*
	 * If the UID of the user does not match the current real UID,
	 * check if the change is allowed by SELinux policy.
	 */
	if ((pw->pw_uid != getuid ())
	    && (selinux_check_passwd_access (PASSWD__CHFN) != 0)) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		closelog ();
		exit (E_NOPERM);
	}
#endif

#ifndef USE_PAM
	/*
	 * Non-privileged users are optionally authenticated (must enter the
	 * password of the user whose information is being changed) before
	 * any changes can be made. Idea from util-linux chfn/chsh. 
	 * --marekm
	 */
	if (!amroot && getdef_bool ("CHFN_AUTH"))
		passwd_check (pw->pw_name, pw->pw_passwd, "chfn");

#else				/* !USE_PAM */
	retval = PAM_SUCCESS;

	pampw = getpwuid (getuid ());
	if (pampw == NULL) {
		retval = PAM_USER_UNKNOWN;
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_start ("chfn", pampw->pw_name, &conv, &pamh);
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_authenticate (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_acct_mgmt (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval != PAM_SUCCESS) {
		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
		exit (E_NOPERM);
	}
#endif				/* USE_PAM */

	/*
	 * Now get the full name. It is the first comma separated field in
	 * the GECOS field.
	 */
	STRFCPY (old_gecos, pw->pw_gecos);
	cp = copy_field (old_gecos, fflg ? (char *) 0 : fullnm, slop);

	/*
	 * Now get the room number. It is the next comma separated field,
	 * if there is indeed one.
	 */
	if (cp)
		cp = copy_field (cp, rflg ? (char *) 0 : roomno, slop);

	/*
	 * Now get the work phone number. It is the third field.
	 */
	if (cp)
		cp = copy_field (cp, wflg ? (char *) 0 : workph, slop);

	/*
	 * Now get the home phone number. It is the fourth field.
	 */
	if (cp)
		cp = copy_field (cp, hflg ? (char *) 0 : homeph, slop);

	/*
	 * Anything left over is "slop".
	 */
	if (cp && !oflg) {
		if (slop[0])
			strcat (slop, ",");

		strcat (slop, cp);
	}

	/*
	 * If none of the fields were changed from the command line, let the
	 * user interactively change them.
	 */
	if (!fflg && !rflg && !wflg && !hflg && !oflg) {
		printf (_("Changing the user information for %s\n"), user);
		new_fields ();
	}

	/*
	 * Check all of the fields for valid information
	 */
	if (valid_field (fullnm, ":,=")) {
		fprintf (stderr, _("%s: invalid name: \"%s\"\n"), Prog, fullnm);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (roomno, ":,=")) {
		fprintf (stderr, _("%s: invalid room number: \"%s\"\n"),
			 Prog, roomno);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (workph, ":,=")) {
		fprintf (stderr, _("%s: invalid work phone: \"%s\"\n"),
			 Prog, workph);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (homeph, ":,=")) {
		fprintf (stderr, _("%s: invalid home phone: \"%s\"\n"),
			 Prog, homeph);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (slop, ":")) {
		fprintf (stderr,
			 _("%s: \"%s\" contains illegal characters\n"),
			 Prog, slop);
		closelog ();
		exit (E_NOPERM);
	}

	/*
	 * Build the new GECOS field by plastering all the pieces together,
	 * if they will fit ...
	 */
	if (strlen (fullnm) + strlen (roomno) + strlen (workph) +
	    strlen (homeph) + strlen (slop) > (unsigned int) 80) {
		fprintf (stderr, _("%s: fields too long\n"), Prog);
		closelog ();
		exit (E_NOPERM);
	}
	snprintf (new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
		  fullnm, roomno, workph, homeph, slop[0] ? "," : "", slop);

	/*
	 * Before going any further, raise the ulimit to prevent colliding
	 * into a lowered ulimit, and set the real UID to root to protect
	 * against unexpected signals. Any keyboard signals are set to be
	 * ignored.
	 */
	if (setuid (0)) {
		fprintf (stderr, _("Cannot change ID to root.\n"));
		SYSLOG ((LOG_ERR, "can't setuid(0)"));
		closelog ();
		exit (E_NOPERM);
	}
	pwd_init ();

	/*
	 * The passwd entry is now ready to be committed back to the
	 * password file. Get a lock on the file and open it.
	 */
	if (!pw_lock ()) {
		fprintf (stderr,
			 _
			 ("Cannot lock the password file; try again later.\n"));
		SYSLOG ((LOG_WARN, "can't lock /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}
	if (!pw_open (O_RDWR)) {
		fprintf (stderr, _("Cannot open the password file.\n"));
		pw_unlock ();
		SYSLOG ((LOG_ERR, "can't open /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}

	/*
	 * Get the entry to update using pw_locate() - we want the real one
	 * from /etc/passwd, not the one from getpwnam() which could contain
	 * the shadow password if (despite the warnings) someone enables
	 * AUTOSHADOW (or SHADOW_COMPAT in libc).  --marekm
	 */
	pw = pw_locate (user);
	if (!pw) {
		pw_unlock ();
		fprintf (stderr,
			 _("%s: %s not found in /etc/passwd\n"), Prog, user);
		exit (E_NOPERM);
	}

	/*
	 * Make a copy of the entry, then change the gecos field. The other
	 * fields remain unchanged.
	 */
	pwent = *pw;
	pwent.pw_gecos = new_gecos;

	/*
	 * Update the passwd file entry. If there is a DBM file, update that
	 * entry as well.
	 */
	if (!pw_update (&pwent)) {
		fprintf (stderr, _("Error updating the password entry.\n"));
		pw_unlock ();
		SYSLOG ((LOG_ERR, "error updating passwd entry"));
		closelog ();
		exit (E_NOPERM);
	}

	/*
	 * Changes have all been made, so commit them and unlock the file.
	 */
	if (!pw_close ()) {
		fprintf (stderr, _("Cannot commit password file changes.\n"));
		pw_unlock ();
		SYSLOG ((LOG_ERR, "can't rewrite /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}
	if (!pw_unlock ()) {
		fprintf (stderr, _("Cannot unlock the password file.\n"));
		SYSLOG ((LOG_ERR, "can't unlock /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}
	SYSLOG ((LOG_INFO, "changed user `%s' information", user));

	nscd_flush_cache ("passwd");

#ifdef USE_PAM
	if (retval == PAM_SUCCESS)
		pam_end (pamh, PAM_SUCCESS);
#endif				/* USE_PAM */

	closelog ();
	exit (E_SUCCESS);
}
Example #4
0
/*
 * process_flags - parse the command line options
 *
 *	It will not return if an error is encountered.
 */
static void process_flags (int argc, char **argv)
{
	int c;		/* flag currently being processed    */
	static struct option long_options[] = {
		{"full-name",  required_argument, NULL, 'f'},
		{"home-phone", required_argument, NULL, 'h'},
		{"other",      required_argument, NULL, 'o'},
		{"room",       required_argument, NULL, 'r'},
		{"root",       required_argument, NULL, 'R'},
		{"help",       no_argument,       NULL, 'u'},
		{"work-phone", required_argument, NULL, 'w'},
		{NULL, 0, NULL, '\0'}
	};

	/* 
	 * The remaining arguments will be processed one by one and executed
	 * by this command. The name is the last argument if it does not
	 * begin with a "-", otherwise the name is determined from the
	 * environment and must agree with the real UID. Also, the UID will
	 * be checked for any commands which are restricted to root only.
	 */
	while ((c = getopt_long (argc, argv, "f:h:o:r:R:uw:",
	                         long_options, NULL)) != -1) {
		switch (c) {
		case 'f':
			if (!may_change_field ('f')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			fflg = true;
			STRFCPY (fullnm, optarg);
			break;
		case 'h':
			if (!may_change_field ('h')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			hflg = true;
			STRFCPY (homeph, optarg);
			break;
		case 'o':
			if (!amroot) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			oflg = true;
			STRFCPY (slop, optarg);
			break;
		case 'r':
			if (!may_change_field ('r')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			rflg = true;
			STRFCPY (roomno, optarg);
			break;
		case 'R': /* no-op, handled in process_root_flag () */
			break;
		case 'u':
			usage (E_SUCCESS);
			/*@notreached@*/break;
		case 'w':
			if (!may_change_field ('w')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			wflg = true;
			STRFCPY (workph, optarg);
			break;
		default:
			usage (E_USAGE);
		}
	}
}
Example #5
0
int
main(int argc, char **argv)
{
	char	*cp;			/* temporary character pointer       */
	const struct passwd *pw;	/* password file entry               */
	struct	passwd	pwent;		/* modified password file entry      */
	char	old_gecos[BUFSIZ];	/* buffer for old GECOS fields       */
	char	new_gecos[BUFSIZ];	/* buffer for new GECOS fields       */
	int	flag;			/* flag currently being processed    */
	int	fflg = 0;		/* -f - set full name                */
	int	rflg = 0;		/* -r - set room number              */
	int	wflg = 0;		/* -w - set work phone number        */
	int	hflg = 0;		/* -h - set home phone number        */
	int	oflg = 0;		/* -o - set other information        */
	char *user;

	sanitize_env();
	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	/*
	 * This command behaves different for root and non-root
	 * users.
	 */

	amroot = (getuid () == 0);
#ifdef	NDBM
	pw_dbm_mode = O_RDWR;
#endif

	/*
	 * Get the program name.  The program name is used as a
	 * prefix to most error messages.  It is also used as input
	 * to the openlog() function for error logging.
	 */

	Prog = Basename(argv[0]);

	openlog("chfn", LOG_PID, LOG_AUTH);

	/* 
	 * The remaining arguments will be processed one by one and
	 * executed by this command.  The name is the last argument
	 * if it does not begin with a "-", otherwise the name is
	 * determined from the environment and must agree with the
	 * real UID.  Also, the UID will be checked for any commands
	 * which are restricted to root only.
	 */

	while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) {
		switch (flag) {
			case 'f':
				if (!may_change_field('f')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				fflg++;
				STRFCPY(fullnm, optarg);
				break;
			case 'r':
				if (!may_change_field('r')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				rflg++;
				STRFCPY(roomno, optarg);
				break;
			case 'w':
				if (!may_change_field('w')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				wflg++;
				STRFCPY(workph, optarg);
				break;
			case 'h':
				if (!may_change_field('h')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				hflg++;
				STRFCPY(homeph, optarg);
				break;
			case 'o':
				if (!amroot) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				oflg++;
				STRFCPY(slop, optarg);
				break;
			default:
				usage();
		}
	}

	/*
	 * Get the name of the user to check.  It is either
	 * the command line name, or the name getlogin()
	 * returns.
	 */

	if (optind < argc) {
		user = argv[optind];
		pw = getpwnam(user);
		if (!pw) {
			fprintf(stderr, _("%s: Unknown user %s\n"), Prog, user);
			exit(1);
		}
	} else {
		pw = get_my_pwent();
		if (!pw) {
			fprintf(stderr, _("%s: Cannot determine your user name.\n"), Prog);
			exit(1);
		}
		user = xstrdup(pw->pw_name);
	}

#ifdef	USE_NIS
	/*
	 * Now we make sure this is a LOCAL password entry for
	 * this user ...
	 */

	if (__ispwNIS ()) {
		char	*nis_domain;
		char	*nis_master;

		fprintf (stderr, _("%s: cannot change user `%s' on NIS client.\n"), Prog, user);

		if (! yp_get_default_domain (&nis_domain) &&
				! yp_master (nis_domain, "passwd.byname",
				&nis_master)) {
			fprintf (stderr, _("%s: `%s' is the NIS master for this client.\n"), Prog, nis_master);
		}
		exit (1);
	}
#endif

	/*
	 * Non-privileged users are only allowed to change the
	 * gecos field if the UID of the user matches the current
	 * real UID.
	 */

	if (!amroot && pw->pw_uid != getuid()) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		closelog();
		exit(1);
	}

	/*
	 * Non-privileged users are optionally authenticated
	 * (must enter the password of the user whose information
	 * is being changed) before any changes can be made.
	 * Idea from util-linux chfn/chsh.  --marekm
	 */

	if (!amroot && getdef_bool("CHFN_AUTH"))
		passwd_check(pw->pw_name, pw->pw_passwd, "chfn");
	
	/*
	 * Now get the full name.  It is the first comma separated field
	 * in the GECOS field.
	 */

	STRFCPY(old_gecos, pw->pw_gecos);
	cp = copy_field (old_gecos, fflg ? (char *) 0:fullnm, slop);

	/*
	 * Now get the room number.  It is the next comma separated field,
	 * if there is indeed one.
	 */

	if (cp)
		cp = copy_field (cp, rflg ? (char *) 0:roomno, slop);

	/*
	 * Now get the work phone number.  It is the third field.
	 */

	if (cp)
		cp = copy_field (cp, wflg ? (char *) 0:workph, slop);

	/*
	 * Now get the home phone number.  It is the fourth field.
	 */

	if (cp)
		cp = copy_field (cp, hflg ? (char *) 0:homeph, slop);

	/*
	 * Anything left over is "slop".
	 */

	if (cp && !oflg) {
		if (slop[0])
			strcat (slop, ",");

		strcat (slop, cp);
	}

	/*
	 * If none of the fields were changed from the command line,
	 * let the user interactively change them.
	 */

	if (!fflg && !rflg && !wflg && !hflg && !oflg) {
		printf(_("Changing the user information for %s\n"), user);
		new_fields();
	}

	/*
	 * Check all of the fields for valid information
	 */

	if (valid_field(fullnm, ":,=")) {
		fprintf(stderr, _("%s: invalid name: \"%s\"\n"), Prog, fullnm);
		closelog();
		exit(1);
	}
	if (valid_field(roomno, ":,=")) {
		fprintf(stderr, _("%s: invalid room number: \"%s\"\n"), Prog, roomno);
		closelog();
		exit(1);
	}
	if (valid_field(workph, ":,=")) {
		fprintf(stderr, _("%s: invalid work phone: \"%s\"\n"), Prog, workph);
		closelog();
		exit(1);
	}
	if (valid_field (homeph, ":,=")) {
		fprintf(stderr, _("%s: invalid home phone: \"%s\"\n"), Prog, homeph);
		closelog();
		exit(1);
	}
	if (valid_field(slop, ":")) {
		fprintf(stderr, _("%s: \"%s\" contains illegal characters\n"), Prog, slop);
		closelog();
		exit(1);
	}

	/*
	 * Build the new GECOS field by plastering all the pieces together,
	 * if they will fit ...
	 */

	if (strlen(fullnm) + strlen(roomno) + strlen(workph) +
			strlen(homeph) + strlen(slop) > (unsigned int) 80) {
		fprintf(stderr, _("%s: fields too long\n"), Prog);
		closelog();
		exit(1);
	}
	snprintf(new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
		 fullnm, roomno, workph, homeph, slop[0] ? "," : "", slop);

	/*
	 * Before going any further, raise the ulimit to prevent
	 * colliding into a lowered ulimit, and set the real UID
	 * to root to protect against unexpected signals.  Any
	 * keyboard signals are set to be ignored.
	 */

	if (setuid(0)) {
		fprintf(stderr, _("Cannot change ID to root.\n"));
		SYSLOG((LOG_ERR, NOTROOT2));
		closelog();
		exit(1);
	}
	pwd_init();

	/*
	 * The passwd entry is now ready to be committed back to
	 * the password file.  Get a lock on the file and open it.
	 */

	if (!pw_lock()) {
		fprintf(stderr, _("Cannot lock the password file; try again later.\n"));
		SYSLOG((LOG_WARN, PWDBUSY2));
		closelog();
		exit(1);
	}
	if (!pw_open(O_RDWR)) {
		fprintf(stderr, _("Cannot open the password file.\n"));
		pw_unlock();
		SYSLOG((LOG_ERR, OPNERROR2));
		closelog();
		exit(1);
	}

	/*
	 * Get the entry to update using pw_locate() - we want the real
	 * one from /etc/passwd, not the one from getpwnam() which could
	 * contain the shadow password if (despite the warnings) someone
	 * enables AUTOSHADOW (or SHADOW_COMPAT in libc).  --marekm
	 */
	pw = pw_locate(user);
	if (!pw) {
		pw_unlock();
		fprintf(stderr,
			_("%s: %s not found in /etc/passwd\n"), Prog, user);
		exit(1);
	}

	/*
	 * Make a copy of the entry, then change the gecos field.  The other
	 * fields remain unchanged.
	 */
	pwent = *pw;
	pwent.pw_gecos = new_gecos;

	/*
	 * Update the passwd file entry.  If there is a DBM file,
	 * update that entry as well.
	 */

	if (!pw_update(&pwent)) {
		fprintf(stderr, _("Error updating the password entry.\n"));
		pw_unlock();
		SYSLOG((LOG_ERR, UPDERROR2));
		closelog();
		exit(1);
	}
#ifdef NDBM
	if (pw_dbm_present() && !pw_dbm_update(&pwent)) {
		fprintf(stderr, _("Error updating the DBM password entry.\n"));
		pw_unlock ();
		SYSLOG((LOG_ERR, DBMERROR2));
		closelog();
		exit(1);
	}
	endpwent();
#endif

	/*
	 * Changes have all been made, so commit them and unlock the
	 * file.
	 */

	if (!pw_close()) {
		fprintf(stderr, _("Cannot commit password file changes.\n"));
		pw_unlock();
		SYSLOG((LOG_ERR, CLSERROR2));
		closelog();
		exit(1);
	}
	if (!pw_unlock()) {
		fprintf(stderr, _("Cannot unlock the password file.\n"));
		SYSLOG((LOG_ERR, UNLKERROR2));
		closelog();
		exit(1);
	}
	SYSLOG((LOG_INFO, CHGGECOS, user));
	closelog();
	exit (0);
}
Example #6
0
/*
 * process_flags - parse the command line options
 *
 *	It will not return if an error is encountered.
 */
static void process_flags (int argc, char **argv)
{
	int flag;		/* flag currently being processed    */

	/* 
	 * The remaining arguments will be processed one by one and executed
	 * by this command. The name is the last argument if it does not
	 * begin with a "-", otherwise the name is determined from the
	 * environment and must agree with the real UID. Also, the UID will
	 * be checked for any commands which are restricted to root only.
	 */
	while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) {
		switch (flag) {
		case 'f':
			if (!may_change_field ('f')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			fflg = true;
			STRFCPY (fullnm, optarg);
			break;
		case 'h':
			if (!may_change_field ('h')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			hflg = true;
			STRFCPY (homeph, optarg);
			break;
		case 'r':
			if (!may_change_field ('r')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			rflg = true;
			STRFCPY (roomno, optarg);
			break;
		case 'o':
			if (!amroot) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			oflg = true;
			STRFCPY (slop, optarg);
			break;
		case 'w':
			if (!may_change_field ('w')) {
				fprintf (stderr,
				         _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			wflg = true;
			STRFCPY (workph, optarg);
			break;
		default:
			usage ();
		}
	}
}