int x_lockscreen(void) { set_user_status(ST_LOCKSCREEN); screen_move(9, 0); screen_clrtobot(); screen_move(9, 0); prints("\033[1;37m" "\n _ _____ ___ _ _ ___ ___ __" "\n ( ) ( _ ) ( _`\\ ( ) ( ) ( _`\\ ( _`\\ | |" "\n | | | ( ) | | ( (_) | |/'/' | (_(_) | | ) | | |" "\n | | _ | | | | | | _ | , < | _)_ | | | ) | |" "\n | |_( ) | (_) | | (_( ) | |\\`\\ | (_( ) | |_) | |==|" "\n (____/' (_____) (____/' (_) (_) (____/' (____/' |__|\n" //% "\n\033[1;36m屏幕已在\033[33m %s\033[36m 时被%s暂时锁住了...\033[m", "\n\033[1;36m\xc6\xc1\xc4\xbb\xd2\xd1\xd4\xda\033[33m %s\033[36m \xca\xb1\xb1\xbb%s\xd4\xdd\xca\xb1\xcb\xf8\xd7\xa1\xc1\xcb...\033[m", format_time(fb_time(), TIME_FORMAT_ZH), currentuser.userid); char buf[PASSLEN + 1]; buf[0] = '\0'; while (*buf == '\0' || !passwd_check(currentuser.userid, buf)) { screen_move(18, 0); screen_clrtobot(); //% getdata(19, 0, "请输入您的密码以解锁: ", buf, PASSLEN, NOECHO, YEA); getdata(19, 0, "\xc7\xeb\xca\xe4\xc8\xeb\xc4\xfa\xb5\xc4\xc3\xdc\xc2\xeb\xd2\xd4\xbd\xe2\xcb\xf8: ", buf, PASSLEN, NOECHO, YEA); } return FULLUPDATE; }
bool ServerPasswd::validate(const char *type, const char *c_uname, const char *s_mnt_name, const char *s_nonce, const char *c_pwd, string& base) { ASSERT(c_uname); ASSERT(s_mnt_name); ASSERT(s_nonce); ASSERT(c_pwd); _DEBUG("VALIDATE: uname=%s mnt_name=%s nonce=%s pwd=%s", c_uname, s_mnt_name, s_nonce, c_pwd); struct server_passwd_entry e; string hash = userToKey(c_uname, s_mnt_name); ScopedMutex lock(&pwd_mutex); ServerPasswd p(Config::instance()->pwd_file().c_str()); bool found = p.getEntry(hash, e); _DEBUG("VALIDATE hash=%s found=%s", hash.c_str(), BOOL_STR(found)); if (found) { time_t now = time(0); if (e.expires > 0 && (uint64_t) now > e.expires) { return false; } #if 1 // CryptoUtils password check if (!passwd_check(type, e.passwd, s_nonce, c_pwd)) { return false; } #else // nonce + pwd == c_pwd string pwd = s_nonce; pwd += b64std2inet(e.passwd); #ifndef OLD_KEY make_hash64(type, pwd, pwd); #else sha2_digest_t digest; make_sha2(pwd, &digest); sha2_base64(&digest, pwd); #endif _DEBUG("VALIDATE: new_pwd=%s entry_pwd=%s", pwd.c_str(), e.passwd.c_str()); if (b64inet2std(c_pwd) != b64inet2std(pwd)) { return false; } #endif base = e.base; } return found; }
int bbs_auth(const char *name, const char *passwd) { if (!name || *name == '\0') return BBS_ENOUSR; if (currentuser.userid[0] == '\0') { if (session_count_online() > MAXACTIVE) return BBS_E2MANY; if (!dosearchuser(name, ¤tuser, &usernum)) return BBS_ENOUSR; } if (!passwd_check(currentuser.userid, passwd)) { log_attempt(currentuser.userid, fromhost, "telnet"); return BBS_EWPSWD; } if (strcasecmp(currentuser.userid, "guest") && !HAS_PERM(PERM_LOGIN)) { if (chk_giveupbbs()) return BBS_EGIVEUP; if (currentuser.userlevel == 0) { return BBS_ESUICIDE; } else { return BBS_EBANNED; } } #ifdef CHECK_FREQUENTLOGIN if (!HAS_PERM(PERM_SYSOPS) && strcasecmp(currentuser.userid, "guest") != 0 && abs(time(NULL) - currentuser.lastlogin) < 10) { return BBS_ELFREQ; } #endif session_set_uid(get_user_id(name)); return 0; }
/* * 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); }
/* * check_perms - check if the caller is allowed to add a group * * Non-root users are only allowed to change their gecos field. * (see also may_change_field()) * * Non-root users must be authenticated. * * It will not return if the user is not allowed. */ static void check_perms (const struct passwd *pw) { #ifdef USE_PAM pam_handle_t *pamh = NULL; int retval; struct passwd *pampw; #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 ()) && (is_selinux_enabled () > 0) && (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 */ pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */ if (NULL == pampw) { fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); exit (E_NOPERM); } retval = pam_start ("chfn", pampw->pw_name, &conv, &pamh); if (PAM_SUCCESS == retval) { retval = pam_authenticate (pamh, 0); } if (PAM_SUCCESS == retval) { retval = pam_acct_mgmt (pamh, 0); } if (PAM_SUCCESS != retval) { fprintf (stderr, _("%s: PAM: %s\n"), Prog, pam_strerror (pamh, retval)); SYSLOG((LOG_ERR, "%s", pam_strerror (pamh, retval))); if (NULL != pamh) { (void) pam_end (pamh, retval); } exit (E_NOPERM); } (void) pam_end (pamh, retval); #endif /* USE_PAM */ }
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); }