+ argc -= optind;
+ argv += optind;
+ if (*argv) {
+ username = *argv;
+ ask = 0;
+ } else
+ ask = 1;
+ if (rflag)
+ ask = 0;
+
+ ioctlval = 0;
+ (void)ioctl(0, TIOCLSET, &ioctlval);
+ (void)ioctl(0, TIOCNXCL, 0);
+ (void)fcntl(0, F_SETFL, ioctlval);
+ (void)ioctl(0, TIOCGETP, &sgttyb);
+
+ /*
+ * If talking to an rlogin process, propagate the terminal type and
+ * baud rate across the network.
+ */
+ if (rflag)
+ doremoteterm(&sgttyb);
+ sgttyb.sg_erase = CERASE;
+ sgttyb.sg_kill = CKILL;
+ (void)ioctl(0, TIOCSLTC, <c);
+ (void)ioctl(0, TIOCSETC, &tc);
+ (void)ioctl(0, TIOCSETP, &sgttyb);
+
+ for (cnt = getdtablesize(); cnt > 2; cnt--)
+ close(cnt);
+
+ ttyn = ttyname(0);
+ if (ttyn == NULL || *ttyn == '\0') {
+ (void)sprintf(tname, "%s??", _PATH_TTY);
+ ttyn = tname;
+ }
+ if (tty = rindex(ttyn, '/'))
+ ++tty;
+ else
+ tty = ttyn;
+
+ openlog("login", LOG_ODELAY, LOG_AUTH);
+
+ for (cnt = 0;; ask = 1) {
+ ioctlval = TTYDISC;
+ (void)ioctl(0, TIOCSETD, &ioctlval);
+
+ if (ask) {
+ fflag = 0;
+ getloginname();
+ }
+ /*
+ * Note if trying multiple user names;
+ * log failures for previous user name,
+ * but don't bother logging one failure
+ * for nonexistent name (mistyped username).
+ */
+ if (failures && strcmp(tbuf, username)) {
+ if (failures > (pwd ? 0 : 1))
+ badlogin(tbuf);
+ failures = 0;
+ }
+ (void)strcpy(tbuf, username);
+ if (pwd = getpwnam(username))
+ salt = pwd->pw_passwd;
+ else
+ salt = "xx";
+
+ /* if user not super-user, check for disabled logins */
+ if (pwd == NULL || pwd->pw_uid)
+ checknologin();
+
+ /*
+ * Disallow automatic login to root; if not invoked by
+ * root, disallow if the uid's differ.
+ */
+ if (fflag && pwd) {
+ int uid = getuid();
+
+ passwd_req =
+#ifndef KERBEROS
+ pwd->pw_uid == 0 ||
+#endif
+ (uid && uid != pwd->pw_uid);
+ }
+
+ /*
+ * If no pre-authentication and a password exists
+ * for this user, prompt for one and verify it.
+ */
+ if (!passwd_req || (pwd && !*pwd->pw_passwd))
+ break;
+
+ setpriority(PRIO_PROCESS, 0, -4);
+ pp = getpass("Password:");
+ p = crypt(pp, salt);
+ setpriority(PRIO_PROCESS, 0, 0);
+
+ (void) bzero(pp, strlen(pp));
+ if (pwd && !strcmp(p, pwd->pw_passwd))
+ break;
+
+ (void)printf("Login incorrect\n");
+ failures++;
+ /* we allow 10 tries, but after 3 we start backing off */
+ if (++cnt > 3) {
+ if (cnt >= 10) {
+ badlogin(username);
+ (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL);
+ sleepexit(1);
+ }
+ sleep((u_int)((cnt - 3) * 5));