1 /* 2 * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)login.c 5.49 (Berkeley) 02/02/90"; 26 #endif /* not lint */ 27 28 /* 29 * login [ name ] 30 * login -h hostname (for telnetd, etc.) 31 * login -f name (for pre-authenticated login: datakit, xterm, etc.) 32 */ 33 34 #include <sys/param.h> 35 #include <ufs/quota.h> 36 #include <sys/stat.h> 37 #include <sys/time.h> 38 #include <sys/resource.h> 39 #include <sys/file.h> 40 #include <sgtty.h> 41 42 #include <utmp.h> 43 #include <signal.h> 44 #include <errno.h> 45 #include <ttyent.h> 46 #include <syslog.h> 47 #include <grp.h> 48 #include <pwd.h> 49 #include <setjmp.h> 50 #include <stdio.h> 51 #include <strings.h> 52 #include <tzfile.h> 53 #include "pathnames.h" 54 55 #ifdef KERBEROS 56 #include <krb.h> 57 #include <netdb.h> 58 char realm[REALM_SZ]; 59 int kerror = KSUCCESS, notickets = 1; 60 KTEXT_ST ticket; 61 AUTH_DAT authdata; 62 char savehost[MAXHOSTNAMELEN]; 63 char tkfile[MAXPATHLEN]; 64 unsigned long faddr; 65 struct hostent *hp; 66 #define PRINCIPAL_NAME pwd->pw_name 67 #define PRINCIPAL_INST "" 68 #define INITIAL_TICKET "krbtgt" 69 #define VERIFY_SERVICE "rcmd" 70 #endif 71 72 #define TTYGRPNAME "tty" /* name of group to own ttys */ 73 74 /* 75 * This bounds the time given to login. Not a define so it can 76 * be patched on machines where it's too small. 77 */ 78 int timeout = 300; 79 80 struct passwd *pwd; 81 int failures; 82 char term[64], *hostname, *username, *tty; 83 84 struct sgttyb sgttyb; 85 struct tchars tc = { 86 CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 87 }; 88 struct ltchars ltc = { 89 CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 90 }; 91 92 char *months[] = 93 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", 94 "Sep", "Oct", "Nov", "Dec" }; 95 96 main(argc, argv) 97 int argc; 98 char **argv; 99 { 100 extern int errno, optind; 101 extern char *optarg, **environ; 102 struct timeval tp; 103 struct tm *ttp; 104 struct group *gr; 105 register int ch; 106 register char *p; 107 int ask, fflag, hflag, pflag, cnt, uid; 108 int quietlog, passwd_req, ioctlval, timedout(); 109 char *domain, *salt, *envinit[1], *ttyn, *pp; 110 char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; 111 char localhost[MAXHOSTNAMELEN]; 112 char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass(); 113 time_t time(); 114 off_t lseek(); 115 116 (void)signal(SIGALRM, timedout); 117 (void)alarm((u_int)timeout); 118 (void)signal(SIGQUIT, SIG_IGN); 119 (void)signal(SIGINT, SIG_IGN); 120 (void)setpriority(PRIO_PROCESS, 0, 0); 121 (void)quota(Q_SETUID, 0, 0, 0); 122 123 /* 124 * -p is used by getty to tell login not to destroy the environment 125 * -f is used to skip a second login authentication 126 * -h is used by other servers to pass the name of the remote 127 * host to login so that it may be placed in utmp and wtmp 128 */ 129 domain = NULL; 130 if (gethostname(localhost, sizeof(localhost)) < 0) 131 syslog(LOG_ERR, "couldn't get local hostname: %m"); 132 else 133 domain = index(localhost, '.'); 134 135 openlog("login", LOG_ODELAY, LOG_AUTH); 136 137 fflag = hflag = pflag = 0; 138 passwd_req = 1; 139 uid = getuid(); 140 while ((ch = getopt(argc, argv, "fh:p")) != EOF) 141 switch (ch) { 142 case 'f': 143 fflag = 1; 144 break; 145 case 'h': 146 if (uid) { 147 (void)fprintf(stderr, 148 "login: -h for super-user only.\n"); 149 exit(1); 150 } 151 hflag = 1; 152 if (domain && (p = index(optarg, '.')) && 153 strcasecmp(p, domain) == 0) 154 *p = 0; 155 hostname = optarg; 156 break; 157 case 'p': 158 pflag = 1; 159 break; 160 case '?': 161 default: 162 if (!uid) 163 syslog(LOG_ERR, "invalid flag %c", ch); 164 (void)fprintf(stderr, 165 "usage: login [-fp] [username]\n"); 166 exit(1); 167 } 168 argc -= optind; 169 argv += optind; 170 if (*argv) { 171 username = *argv; 172 ask = 0; 173 } else 174 ask = 1; 175 176 ioctlval = 0; 177 (void)ioctl(0, TIOCLSET, &ioctlval); 178 (void)ioctl(0, TIOCNXCL, 0); 179 (void)fcntl(0, F_SETFL, ioctlval); 180 (void)ioctl(0, TIOCGETP, &sgttyb); 181 sgttyb.sg_erase = CERASE; 182 sgttyb.sg_kill = CKILL; 183 (void)ioctl(0, TIOCSLTC, <c); 184 (void)ioctl(0, TIOCSETC, &tc); 185 (void)ioctl(0, TIOCSETP, &sgttyb); 186 187 for (cnt = getdtablesize(); cnt > 2; cnt--) 188 close(cnt); 189 190 ttyn = ttyname(0); 191 if (ttyn == NULL || *ttyn == '\0') { 192 (void)sprintf(tname, "%s??", _PATH_TTY); 193 ttyn = tname; 194 } 195 if (tty = rindex(ttyn, '/')) 196 ++tty; 197 else 198 tty = ttyn; 199 200 for (cnt = 0;; ask = 1) { 201 ioctlval = TTYDISC; 202 (void)ioctl(0, TIOCSETD, &ioctlval); 203 204 if (ask) { 205 fflag = 0; 206 getloginname(); 207 } 208 /* 209 * Note if trying multiple user names; log failures for 210 * previous user name, but don't bother logging one failure 211 * for nonexistent name (mistyped username). 212 */ 213 if (failures && strcmp(tbuf, username)) { 214 if (failures > (pwd ? 0 : 1)) 215 badlogin(tbuf); 216 failures = 0; 217 } 218 (void)strcpy(tbuf, username); 219 if (pwd = getpwnam(username)) 220 salt = pwd->pw_passwd; 221 else 222 salt = "xx"; 223 224 /* if user not super-user, check for disabled logins */ 225 if (pwd == NULL || pwd->pw_uid) 226 checknologin(); 227 228 /* 229 * Disallow automatic login to root; if not invoked by 230 * root, disallow if the uid's differ. 231 */ 232 if (fflag && pwd) { 233 passwd_req = 234 #ifndef KERBEROS 235 pwd->pw_uid == 0 || 236 #endif 237 (uid && uid != pwd->pw_uid); 238 } 239 240 /* 241 * If no pre-authentication and a password exists 242 * for this user, prompt for one and verify it. 243 */ 244 if (!passwd_req || (pwd && !*pwd->pw_passwd)) 245 break; 246 247 /* 248 * If trying to log in as root, but with insecure terminal, 249 * refuse the login attempt. 250 */ 251 if (pwd->pw_uid == 0 && !rootterm(tty)) { 252 (void)fprintf(stderr, 253 "%s login refused on this terminal.\n", 254 pwd->pw_name); 255 if (hostname) 256 syslog(LOG_NOTICE, 257 "LOGIN %s REFUSED FROM %s ON TTY %s", 258 pwd->pw_name, hostname, tty); 259 else 260 syslog(LOG_NOTICE, 261 "LOGIN %s REFUSED ON TTY %s", 262 pwd->pw_name, tty); 263 continue; 264 } 265 266 setpriority(PRIO_PROCESS, 0, -4); 267 pp = getpass("Password:"); 268 p = crypt(pp, salt); 269 setpriority(PRIO_PROCESS, 0, 0); 270 271 #ifdef KERBEROS 272 273 /* 274 * If not present in pw file, act as old login would. 275 * If we aren't Kerberos-authenticated, try the normal 276 * pw file for a password. If that's ok, log the user 277 * in without issueing any tickets. 278 */ 279 280 if (pwd && (krb_get_lrealm(realm,1) == KSUCCESS)) { 281 282 /* 283 * get TGT for local realm 284 * convention: store tickets in file associated 285 * with tty name, which should be available 286 */ 287 (void)sprintf(tkfile, "%s_%s", TKT_ROOT, tty); 288 kerror = INTK_ERR; 289 if (setenv("KRBTKFILE", tkfile, 1) < 0) 290 syslog(LOG_ERR, "couldn't set tkfile environ"); 291 else { 292 (void) unlink(tkfile); 293 kerror = krb_get_pw_in_tkt( 294 PRINCIPAL_NAME, /* user */ 295 PRINCIPAL_INST, /* (null) */ 296 realm, 297 INITIAL_TICKET, realm, 298 DEFAULT_TKT_LIFE, 299 pp); 300 } 301 /* 302 * If we got a TGT, get a local "rcmd" ticket and 303 * check it so as to ensure that we are not 304 * talking to a bogus Kerberos server 305 * 306 * There are 2 cases where we still allow a login: 307 * 1> the VERIFY_SERVICE doesn't exist in the KDC 308 * 2> local host has no srvtab, as (hopefully) 309 * indicated by a return value of RD_AP_UNDEC 310 * from krb_rd_req() 311 */ 312 if (kerror == INTK_OK) { 313 if (chown(tkfile, pwd->pw_uid, pwd->pw_gid) < 0) 314 syslog(LOG_ERR, "chown tkfile: %m"); 315 (void) strncpy(savehost, 316 krb_get_phost(localhost), 317 sizeof(savehost)); 318 savehost[sizeof(savehost)-1] = NULL; 319 kerror = krb_mk_req(&ticket, VERIFY_SERVICE, 320 savehost, realm, 33); 321 /* 322 * if the "VERIFY_SERVICE" doesn't exist in 323 * the KDC for this host, still allow login, 324 * but log the error condition 325 */ 326 if (kerror == KDC_PR_UNKNOWN) { 327 syslog(LOG_NOTICE, 328 "Warning: TGT not verified (%s)", 329 krb_err_txt[kerror]); 330 bzero(pp, strlen(pp)); 331 notickets = 0; 332 break; /* ok */ 333 } else if (kerror != KSUCCESS) { 334 printf("Unable to use TGT: (%s)\n", 335 krb_err_txt[kerror]); 336 syslog(LOG_NOTICE, 337 "Unable to use TGT: (%s)", 338 krb_err_txt[kerror]); 339 dest_tkt(); 340 /* fall thru: no login */ 341 } else { 342 if (!(hp = gethostbyname(localhost))) { 343 syslog(LOG_ERR, 344 "couldn't get local host address"); 345 } else { 346 bcopy((char *) hp->h_addr, 347 (char *) &faddr, sizeof(faddr)); 348 if ((kerror = krb_rd_req(&ticket, 349 VERIFY_SERVICE, savehost, faddr, 350 &authdata, "")) != KSUCCESS) { 351 352 if (kerror = RD_AP_UNDEC) { 353 syslog(LOG_NOTICE, 354 "krb_rd_req: (%s)\n", 355 krb_err_txt[kerror]); 356 bzero(pp, strlen(pp)); 357 notickets = 0; 358 break; /* ok */ 359 } else { 360 printf("Unable to verify %s ticket: (%s)\n", 361 VERIFY_SERVICE, 362 krb_err_txt[kerror]); 363 syslog(LOG_NOTICE, 364 "couldn't verify %s ticket: %s", 365 VERIFY_SERVICE, 366 krb_err_txt[kerror]); 367 } 368 /* fall thru: no login */ 369 } else { 370 bzero(pp, strlen(pp)); 371 notickets = 0; /* got ticket */ 372 break; /* ok */ 373 } 374 } 375 } 376 377 } else { 378 (void) unlink(tkfile); 379 if ((kerror != INTK_BADPW) && 380 kerror != KDC_PR_UNKNOWN) 381 syslog(LOG_ERR, 382 "Kerberos intkt error: %s", 383 krb_err_txt[kerror]); 384 } 385 } 386 387 #endif 388 (void) bzero(pp, strlen(pp)); 389 if (pwd && !strcmp(p, pwd->pw_passwd)) 390 break; 391 392 (void)printf("Login incorrect\n"); 393 failures++; 394 /* we allow 10 tries, but after 3 we start backing off */ 395 if (++cnt > 3) { 396 if (cnt >= 10) { 397 badlogin(username); 398 (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); 399 sleepexit(1); 400 } 401 sleep((u_int)((cnt - 3) * 5)); 402 } 403 } 404 405 /* committed to login -- turn off timeout */ 406 (void)alarm((u_int)0); 407 408 /* paranoia... */ 409 endpwent(); 410 411 if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 412 switch(errno) { 413 case EUSERS: 414 (void)fprintf(stderr, 415 "Too many users logged on already.\nTry again later.\n"); 416 break; 417 case EPROCLIM: 418 (void)fprintf(stderr, 419 "You have too many processes running.\n"); 420 break; 421 default: 422 perror("quota (Q_SETUID)"); 423 } 424 sleepexit(0); 425 } 426 427 if (chdir(pwd->pw_dir) < 0) { 428 (void)printf("No directory %s!\n", pwd->pw_dir); 429 if (chdir("/")) 430 exit(0); 431 pwd->pw_dir = "/"; 432 (void)printf("Logging in with home = \"/\".\n"); 433 } 434 435 quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; 436 437 #ifdef KERBEROS 438 if (notickets && !quietlog) 439 (void)printf("Warning: no Kerberos tickets issued\n"); 440 #endif 441 442 if (pwd->pw_change || pwd->pw_expire) 443 (void)gettimeofday(&tp, (struct timezone *)NULL); 444 if (pwd->pw_change) 445 if (tp.tv_sec >= pwd->pw_change) { 446 (void)printf("Sorry -- your password has expired.\n"); 447 sleepexit(1); 448 } 449 else if (pwd->pw_change - tp.tv_sec < 450 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) { 451 ttp = localtime(&pwd->pw_change); 452 (void)printf("Warning: your password expires on %s %d, %d\n", 453 months[ttp->tm_mon], ttp->tm_mday, 454 TM_YEAR_BASE + ttp->tm_year); 455 } 456 if (pwd->pw_expire) 457 if (tp.tv_sec >= pwd->pw_expire) { 458 (void)printf("Sorry -- your account has expired.\n"); 459 sleepexit(1); 460 } 461 else if (pwd->pw_expire - tp.tv_sec < 462 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) { 463 ttp = localtime(&pwd->pw_expire); 464 (void)printf("Warning: your account expires on %s %d, %d\n", 465 months[ttp->tm_mon], ttp->tm_mday, 466 TM_YEAR_BASE + ttp->tm_year); 467 } 468 469 /* nothing else left to fail -- really log in */ 470 { 471 struct utmp utmp; 472 473 bzero((char *)&utmp, sizeof(utmp)); 474 (void)time(&utmp.ut_time); 475 strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 476 if (hostname) 477 strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 478 strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 479 login(&utmp); 480 } 481 482 dolastlog(quietlog); 483 484 if (!hflag) { /* XXX */ 485 static struct winsize win = { 0, 0, 0, 0 }; 486 487 (void)ioctl(0, TIOCSWINSZ, &win); 488 } 489 490 (void)chown(ttyn, pwd->pw_uid, 491 (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 492 (void)chmod(ttyn, 0620); 493 (void)setgid(pwd->pw_gid); 494 495 initgroups(username, pwd->pw_gid); 496 497 quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 498 499 if (*pwd->pw_shell == '\0') 500 pwd->pw_shell = _PATH_BSHELL; 501 502 /* destroy environment unless user has requested preservation */ 503 if (!pflag) 504 environ = envinit; 505 (void)setenv("HOME", pwd->pw_dir, 1); 506 (void)setenv("SHELL", pwd->pw_shell, 1); 507 if (term[0] == '\0') 508 strncpy(term, stypeof(tty), sizeof(term)); 509 (void)setenv("TERM", term, 0); 510 (void)setenv("USER", pwd->pw_name, 1); 511 (void)setenv("PATH", _PATH_DEFPATH, 0); 512 513 if (tty[sizeof("tty")-1] == 'd') 514 syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 515 if (pwd->pw_uid == 0) 516 if (hostname) 517 syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", 518 tty, hostname); 519 else 520 syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); 521 522 if (!quietlog) { 523 struct stat st; 524 525 motd(); 526 (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); 527 if (stat(tbuf, &st) == 0 && st.st_size != 0) 528 (void)printf("You have %smail.\n", 529 (st.st_mtime > st.st_atime) ? "new " : ""); 530 } 531 532 (void)signal(SIGALRM, SIG_DFL); 533 (void)signal(SIGQUIT, SIG_DFL); 534 (void)signal(SIGINT, SIG_DFL); 535 (void)signal(SIGTSTP, SIG_IGN); 536 537 tbuf[0] = '-'; 538 strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? 539 p + 1 : pwd->pw_shell); 540 541 if (setlogin(pwd->pw_name) < 0) 542 syslog(LOG_ERR, "setlogin() failure: %m"); 543 544 /* discard permissions last so can't get killed and drop core */ 545 (void)setuid(pwd->pw_uid); 546 547 execlp(pwd->pw_shell, tbuf, 0); 548 (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); 549 exit(0); 550 } 551 552 getloginname() 553 { 554 register int ch; 555 register char *p; 556 static char nbuf[UT_NAMESIZE + 1]; 557 558 for (;;) { 559 (void)printf("login: "); 560 for (p = nbuf; (ch = getchar()) != '\n'; ) { 561 if (ch == EOF) { 562 badlogin(username); 563 exit(0); 564 } 565 if (p < nbuf + UT_NAMESIZE) 566 *p++ = ch; 567 } 568 if (p > nbuf) 569 if (nbuf[0] == '-') 570 (void)fprintf(stderr, 571 "login names may not start with '-'.\n"); 572 else { 573 *p = '\0'; 574 username = nbuf; 575 break; 576 } 577 } 578 } 579 580 timedout() 581 { 582 (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 583 exit(0); 584 } 585 586 rootterm(ttyn) 587 char *ttyn; 588 { 589 struct ttyent *t; 590 591 return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE); 592 } 593 594 jmp_buf motdinterrupt; 595 596 motd() 597 { 598 register int fd, nchars; 599 sig_t oldint; 600 int sigint(); 601 char tbuf[8192]; 602 603 if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) 604 return; 605 oldint = signal(SIGINT, sigint); 606 if (setjmp(motdinterrupt) == 0) 607 while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 608 (void)write(fileno(stdout), tbuf, nchars); 609 (void)signal(SIGINT, oldint); 610 (void)close(fd); 611 } 612 613 sigint() 614 { 615 longjmp(motdinterrupt, 1); 616 } 617 618 checknologin() 619 { 620 register int fd, nchars; 621 char tbuf[8192]; 622 623 if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { 624 while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 625 (void)write(fileno(stdout), tbuf, nchars); 626 sleepexit(0); 627 } 628 } 629 630 dolastlog(quiet) 631 int quiet; 632 { 633 struct lastlog ll; 634 int fd; 635 char *ctime(); 636 637 if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 638 (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 639 if (!quiet) { 640 if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 641 ll.ll_time != 0) { 642 (void)printf("Last login: %.*s ", 643 24-5, (char *)ctime(&ll.ll_time)); 644 if (*ll.ll_host != '\0') 645 (void)printf("from %.*s\n", 646 sizeof(ll.ll_host), ll.ll_host); 647 else 648 (void)printf("on %.*s\n", 649 sizeof(ll.ll_line), ll.ll_line); 650 } 651 (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 652 } 653 bzero((char *)&ll, sizeof(ll)); 654 (void)time(&ll.ll_time); 655 strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 656 if (hostname) 657 strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 658 (void)write(fd, (char *)&ll, sizeof(ll)); 659 (void)close(fd); 660 } 661 } 662 663 badlogin(name) 664 char *name; 665 { 666 if (failures == 0) 667 return; 668 if (hostname) 669 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", 670 failures, failures > 1 ? "S" : "", hostname, name); 671 else 672 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", 673 failures, failures > 1 ? "S" : "", tty, name); 674 } 675 676 #undef UNKNOWN 677 #define UNKNOWN "su" 678 679 char * 680 stypeof(ttyid) 681 char *ttyid; 682 { 683 struct ttyent *t; 684 685 return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 686 } 687 688 getstr(buf, cnt, err) 689 char *buf, *err; 690 int cnt; 691 { 692 char ch; 693 694 do { 695 if (read(0, &ch, sizeof(ch)) != sizeof(ch)) 696 exit(1); 697 if (--cnt < 0) { 698 (void)fprintf(stderr, "%s too long\r\n", err); 699 sleepexit(1); 700 } 701 *buf++ = ch; 702 } while (ch); 703 } 704 705 sleepexit(eval) 706 int eval; 707 { 708 sleep((u_int)5); 709 exit(eval); 710 } 711