119843Sdist /* 219843Sdist * Copyright (c) 1980 Regents of the University of California. 319843Sdist * All rights reserved. The Berkeley software License Agreement 419843Sdist * specifies the terms and conditions for redistribution. 519843Sdist */ 619843Sdist 712678Ssam #ifndef lint 819843Sdist char copyright[] = 919843Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1019843Sdist All rights reserved.\n"; 1119843Sdist #endif not lint 1212678Ssam 1319843Sdist #ifndef lint 14*29992Skarels static char sccsid[] = "@(#)login.c 5.16 (Berkeley) 11/10/86"; 1519843Sdist #endif not lint 1619843Sdist 171043Sbill /* 181043Sbill * login [ name ] 1912687Ssam * login -r hostname (for rlogind) 2012687Ssam * login -h hostname (for telnetd, etc.) 211043Sbill */ 221043Sbill 2312984Ssam #include <sys/param.h> 2412687Ssam #include <sys/quota.h> 2512687Ssam #include <sys/stat.h> 2612687Ssam #include <sys/time.h> 2712687Ssam #include <sys/resource.h> 2816453Sroot #include <sys/file.h> 2912687Ssam 301043Sbill #include <sgtty.h> 311043Sbill #include <utmp.h> 321043Sbill #include <signal.h> 331043Sbill #include <pwd.h> 341043Sbill #include <stdio.h> 351043Sbill #include <lastlog.h> 3612678Ssam #include <errno.h> 3716453Sroot #include <ttyent.h> 3816453Sroot #include <syslog.h> 3926862Smckusick #include <grp.h> 401043Sbill 4127056Skarels #define TTYGRPNAME "tty" /* name of group to own ttys */ 4227056Skarels #define TTYGID(gid) tty_gid(gid) /* gid that owns all ttys */ 4326862Smckusick 4416453Sroot #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 452822Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 462822Swnj 476197Sroot #define NMAX sizeof(utmp.ut_name) 4825230Smckusick #define HMAX sizeof(utmp.ut_host) 491043Sbill 502822Swnj #define FALSE 0 512822Swnj #define TRUE -1 522822Swnj 532822Swnj char nolog[] = "/etc/nologin"; 542822Swnj char qlog[] = ".hushlogin"; 551043Sbill char maildir[30] = "/usr/spool/mail/"; 561043Sbill char lastlog[] = "/usr/adm/lastlog"; 579867Ssam struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; 581043Sbill struct sgttyb ttyb; 591043Sbill struct utmp utmp; 601043Sbill char minusnam[16] = "-"; 6118549Ssam char *envinit[] = { 0 }; /* now set by setenv calls */ 6212687Ssam /* 6312687Ssam * This bounds the time given to login. We initialize it here 6412687Ssam * so it can be patched on machines where it's too small. 6512687Ssam */ 6612687Ssam int timeout = 60; 676005Swnj 6818549Ssam char term[64]; 696005Swnj 701043Sbill struct passwd *pwd; 7118549Ssam char *strcat(), *rindex(), *index(), *malloc(), *realloc(); 7212687Ssam int timedout(); 731043Sbill char *ttyname(); 741043Sbill char *crypt(); 751043Sbill char *getpass(); 761043Sbill char *stypeof(); 771043Sbill extern char **environ; 7812678Ssam extern int errno; 791043Sbill 8013074Ssam struct tchars tc = { 8113074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 821365Sbill }; 8313074Ssam struct ltchars ltc = { 8413074Ssam CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 8513074Ssam }; 861365Sbill 8718549Ssam struct winsize win = { 0, 0, 0, 0 }; 8818549Ssam 896005Swnj int rflag; 9024712Sbloom int usererr = -1; 916197Sroot char rusername[NMAX+1], lusername[NMAX+1]; 926005Swnj char rpassword[NMAX+1]; 936878Smckusick char name[NMAX+1]; 94*29992Skarels char me[MAXHOSTNAMELEN]; 956197Sroot char *rhost; 966005Swnj 971043Sbill main(argc, argv) 9812687Ssam char *argv[]; 991043Sbill { 1001043Sbill register char *namep; 10118549Ssam int pflag = 0, hflag = 0, t, f, c; 10212687Ssam int invalid, quietlog; 1032822Swnj FILE *nlfd; 10416453Sroot char *ttyn, *tty; 10518549Ssam int ldisc = 0, zero = 0, i; 10618549Ssam char **envnew; 107*29992Skarels char *p, *domain, *index(); 1081043Sbill 10912687Ssam signal(SIGALRM, timedout); 11012687Ssam alarm(timeout); 1111043Sbill signal(SIGQUIT, SIG_IGN); 1121043Sbill signal(SIGINT, SIG_IGN); 11312687Ssam setpriority(PRIO_PROCESS, 0, 0); 11412678Ssam quota(Q_SETUID, 0, 0, 0); 11512687Ssam /* 11618549Ssam * -p is used by getty to tell login not to destroy the environment 11712687Ssam * -r is used by rlogind to cause the autologin protocol; 11812687Ssam * -h is used by other servers to pass the name of the 11912687Ssam * remote host to login so that it may be placed in utmp and wtmp 12012687Ssam */ 121*29992Skarels (void) gethostname(me, sizeof(me)); 122*29992Skarels domain = index(me, '.'); 12324712Sbloom while (argc > 1) { 12412687Ssam if (strcmp(argv[1], "-r") == 0) { 12524712Sbloom if (rflag || hflag) { 12624712Sbloom printf("Only one of -r and -h allowed\n"); 12724712Sbloom exit(1); 12824712Sbloom } 12924712Sbloom rflag = 1; 13024712Sbloom usererr = doremotelogin(argv[2]); 131*29992Skarels if ((p = index(argv[2], '.')) && strcmp(p, domain) == 0) 132*29992Skarels *p = 0; 13312687Ssam SCPYN(utmp.ut_host, argv[2]); 13424712Sbloom argc -= 2; 13524712Sbloom argv += 2; 13624712Sbloom continue; 1376197Sroot } 13812687Ssam if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { 13924712Sbloom if (rflag || hflag) { 14024712Sbloom printf("Only one of -r and -h allowed\n"); 14124712Sbloom exit(1); 14224712Sbloom } 14318549Ssam hflag = 1; 144*29992Skarels if ((p = index(argv[2], '.')) && strcmp(p, domain) == 0) 145*29992Skarels *p = 0; 14612687Ssam SCPYN(utmp.ut_host, argv[2]); 14724712Sbloom argc -= 2; 14824712Sbloom argv += 2; 14924712Sbloom continue; 1506197Sroot } 15118549Ssam if (strcmp(argv[1], "-p") == 0) { 15218549Ssam argc--; 15318549Ssam argv++; 15418549Ssam pflag = 1; 15524712Sbloom continue; 15618549Ssam } 15724712Sbloom break; 1586005Swnj } 15913074Ssam ioctl(0, TIOCLSET, &zero); 1601547Sbill ioctl(0, TIOCNXCL, 0); 1616329Swnj ioctl(0, FIONBIO, &zero); 1626329Swnj ioctl(0, FIOASYNC, &zero); 16313074Ssam ioctl(0, TIOCGETP, &ttyb); 16412687Ssam /* 16512687Ssam * If talking to an rlogin process, 16612687Ssam * propagate the terminal type and 16712687Ssam * baud rate across the network. 16812687Ssam */ 16912687Ssam if (rflag) 17012687Ssam doremoteterm(term, &ttyb); 17126482Skarels ttyb.sg_erase = CERASE; 17226482Skarels ttyb.sg_kill = CKILL; 17313074Ssam ioctl(0, TIOCSLTC, <c); 17413074Ssam ioctl(0, TIOCSETC, &tc); 17513074Ssam ioctl(0, TIOCSETP, &ttyb); 17624849Smckusick for (t = getdtablesize(); t > 2; t--) 1771043Sbill close(t); 1781043Sbill ttyn = ttyname(0); 17925426Sbloom if (ttyn == (char *)0 || *ttyn == '\0') 1801043Sbill ttyn = "/dev/tty??"; 18116453Sroot tty = rindex(ttyn, '/'); 18216453Sroot if (tty == NULL) 18316453Sroot tty = ttyn; 18416453Sroot else 18516453Sroot tty++; 18624852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 18716453Sroot t = 0; 18825163Sbloom invalid = FALSE; 1892822Swnj do { 1902822Swnj ldisc = 0; 1912822Swnj ioctl(0, TIOCSETD, &ldisc); 1922822Swnj SCPYN(utmp.ut_name, ""); 19312687Ssam /* 19412687Ssam * Name specified, take it. 19512687Ssam */ 19612687Ssam if (argc > 1) { 1972822Swnj SCPYN(utmp.ut_name, argv[1]); 1982822Swnj argc = 0; 1991043Sbill } 20012687Ssam /* 20112687Ssam * If remote login take given name, 20212687Ssam * otherwise prompt user for something. 20312687Ssam */ 20425163Sbloom if (rflag && !invalid) 2059867Ssam SCPYN(utmp.ut_name, lusername); 20624883Smckusick else 20712687Ssam getloginname(&utmp); 20825163Sbloom invalid = FALSE; 2092822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 2102822Swnj ldisc = NTTYDISC; 2112822Swnj ioctl(0, TIOCSETD, &ldisc); 2122822Swnj } 21312687Ssam /* 21412687Ssam * If no remote login authentication and 21512687Ssam * a password exists for this user, prompt 21612687Ssam * for one and verify it. 21712687Ssam */ 21824712Sbloom if (usererr == -1 && *pwd->pw_passwd != '\0') { 21912687Ssam char *pp; 22012687Ssam 22112687Ssam setpriority(PRIO_PROCESS, 0, -4); 22212687Ssam pp = getpass("Password:"); 22312687Ssam namep = crypt(pp, pwd->pw_passwd); 22412687Ssam setpriority(PRIO_PROCESS, 0, 0); 22512687Ssam if (strcmp(namep, pwd->pw_passwd)) 22612687Ssam invalid = TRUE; 2272822Swnj } 22812687Ssam /* 22912687Ssam * If user not super-user, check for logins disabled. 23012687Ssam */ 2312822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 2322822Swnj while ((c = getc(nlfd)) != EOF) 2332822Swnj putchar(c); 2342822Swnj fflush(stdout); 2352822Swnj sleep(5); 2362822Swnj exit(0); 2372822Swnj } 23812687Ssam /* 23912687Ssam * If valid so far and root is logging in, 24012687Ssam * see if root logins on this terminal are permitted. 24112687Ssam */ 24216453Sroot if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { 24325230Smckusick if (utmp.ut_host[0]) 24425230Smckusick syslog(LOG_CRIT, 24525230Smckusick "ROOT LOGIN REFUSED ON %s FROM %.*s", 24625230Smckusick tty, HMAX, utmp.ut_host); 24725230Smckusick else 24825230Smckusick syslog(LOG_CRIT, 24925230Smckusick "ROOT LOGIN REFUSED ON %s", tty); 2502822Swnj invalid = TRUE; 2512822Swnj } 2522822Swnj if (invalid) { 2531043Sbill printf("Login incorrect\n"); 25416453Sroot if (++t >= 5) { 25525230Smckusick if (utmp.ut_host[0]) 25625230Smckusick syslog(LOG_CRIT, 25725230Smckusick "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s", 25825230Smckusick tty, HMAX, utmp.ut_host, 25925230Smckusick NMAX, utmp.ut_name); 26025230Smckusick else 26125230Smckusick syslog(LOG_CRIT, 26225230Smckusick "REPEATED LOGIN FAILURES ON %s, %.*s", 26325230Smckusick tty, NMAX, utmp.ut_name); 26416453Sroot ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 26518549Ssam close(0), close(1), close(2); 26616453Sroot sleep(10); 26716453Sroot exit(1); 26816453Sroot } 2691043Sbill } 2702822Swnj if (*pwd->pw_shell == '\0') 2712822Swnj pwd->pw_shell = "/bin/sh"; 2722822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 2732822Swnj if (chdir("/") < 0) { 2742822Swnj printf("No directory!\n"); 2752822Swnj invalid = TRUE; 2762822Swnj } else { 27712687Ssam printf("No directory! %s\n", 27812687Ssam "Logging in with home=/"); 2792822Swnj pwd->pw_dir = "/"; 2802822Swnj } 2811043Sbill } 28212687Ssam /* 28312687Ssam * Remote login invalid must have been because 28412687Ssam * of a restriction of some sort, no extra chances. 28512687Ssam */ 28624712Sbloom if (!usererr && invalid) 2876005Swnj exit(1); 2882822Swnj } while (invalid); 28912687Ssam /* committed to login turn off timeout */ 29012687Ssam alarm(0); 2911043Sbill 29221083Smckusick if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 29312678Ssam if (errno == EUSERS) 29412678Ssam printf("%s.\n%s.\n", 29512678Ssam "Too many users logged on already", 29612678Ssam "Try again later"); 29712678Ssam else if (errno == EPROCLIM) 29812678Ssam printf("You have too many processes running.\n"); 29912678Ssam else 30017664Sserge perror("quota (Q_SETUID)"); 30112678Ssam sleep(5); 30212678Ssam exit(0); 30312678Ssam } 3041043Sbill time(&utmp.ut_time); 3051043Sbill t = ttyslot(); 30616453Sroot if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { 3071043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 30816453Sroot SCPYN(utmp.ut_line, tty); 3091043Sbill write(f, (char *)&utmp, sizeof(utmp)); 3101043Sbill close(f); 3111043Sbill } 31216453Sroot if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { 3131043Sbill write(f, (char *)&utmp, sizeof(utmp)); 3141043Sbill close(f); 3151043Sbill } 31616453Sroot quietlog = access(qlog, F_OK) == 0; 31716453Sroot if ((f = open(lastlog, O_RDWR)) >= 0) { 3182822Swnj struct lastlog ll; 3192822Swnj 3202822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3212822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 32212687Ssam ll.ll_time != 0 && !quietlog) { 32312687Ssam printf("Last login: %.*s ", 32412687Ssam 24-5, (char *)ctime(&ll.ll_time)); 32512687Ssam if (*ll.ll_host != '\0') 32612687Ssam printf("from %.*s\n", 32712687Ssam sizeof (ll.ll_host), ll.ll_host); 32812687Ssam else 32912687Ssam printf("on %.*s\n", 33012687Ssam sizeof (ll.ll_line), ll.ll_line); 3312822Swnj } 3322822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3332822Swnj time(&ll.ll_time); 33416453Sroot SCPYN(ll.ll_line, tty); 33512687Ssam SCPYN(ll.ll_host, utmp.ut_host); 3362822Swnj write(f, (char *) &ll, sizeof ll); 3372822Swnj close(f); 3382822Swnj } 33927056Skarels chown(ttyn, pwd->pw_uid, TTYGID(pwd->pw_gid)); 34024849Smckusick if (!hflag && !rflag) /* XXX */ 34118549Ssam ioctl(0, TIOCSWINSZ, &win); 34226862Smckusick chmod(ttyn, 0620); 3431043Sbill setgid(pwd->pw_gid); 3446878Smckusick strncpy(name, utmp.ut_name, NMAX); 3456878Smckusick name[NMAX] = '\0'; 3469224Ssam initgroups(name, pwd->pw_gid); 34712678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 3481043Sbill setuid(pwd->pw_uid); 34918549Ssam /* destroy environment unless user has asked to preserve it */ 35018549Ssam if (!pflag) 35118549Ssam environ = envinit; 35218549Ssam 35318549Ssam /* set up environment, this time without destruction */ 35418549Ssam /* copy the environment before setenving */ 35518549Ssam i = 0; 35618549Ssam while (environ[i] != NULL) 35718549Ssam i++; 35818549Ssam envnew = (char **) malloc(sizeof (char *) * (i + 1)); 35918549Ssam for (; i >= 0; i--) 36018549Ssam envnew[i] = environ[i]; 36118549Ssam environ = envnew; 36218549Ssam 36324966Skarels setenv("HOME=", pwd->pw_dir, 1); 36424966Skarels setenv("SHELL=", pwd->pw_shell, 1); 36518549Ssam if (term[0] == '\0') 36618549Ssam strncpy(term, stypeof(tty), sizeof(term)); 36724966Skarels setenv("TERM=", term, 0); 36824966Skarels setenv("USER=", pwd->pw_name, 1); 36924966Skarels setenv("PATH=", ":/usr/ucb:/bin:/usr/bin", 0); 37018549Ssam 3711043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 3721043Sbill namep = pwd->pw_shell; 3731043Sbill else 3741043Sbill namep++; 3751043Sbill strcat(minusnam, namep); 37616453Sroot if (tty[sizeof("tty")-1] == 'd') 37718549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 37818549Ssam if (pwd->pw_uid == 0) 37925230Smckusick if (utmp.ut_host[0]) 38025230Smckusick syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", 38125230Smckusick tty, HMAX, utmp.ut_host); 38225230Smckusick else 38325230Smckusick syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); 3846329Swnj if (!quietlog) { 38517664Sserge struct stat st; 38618549Ssam 3872822Swnj showmotd(); 3882822Swnj strcat(maildir, pwd->pw_name); 38917664Sserge if (stat(maildir, &st) == 0 && st.st_size != 0) 39017664Sserge printf("You have %smail.\n", 39118549Ssam (st.st_mtime > st.st_atime) ? "new " : ""); 3922822Swnj } 39312687Ssam signal(SIGALRM, SIG_DFL); 3941043Sbill signal(SIGQUIT, SIG_DFL); 3951043Sbill signal(SIGINT, SIG_DFL); 3963935Sroot signal(SIGTSTP, SIG_IGN); 3971043Sbill execlp(pwd->pw_shell, minusnam, 0); 3982822Swnj perror(pwd->pw_shell); 3991043Sbill printf("No shell\n"); 4001043Sbill exit(0); 4011043Sbill } 4021043Sbill 40312687Ssam getloginname(up) 40412687Ssam register struct utmp *up; 40512687Ssam { 40612687Ssam register char *namep; 40712712Ssam char c; 40812687Ssam 40912687Ssam while (up->ut_name[0] == '\0') { 41014897Sedward namep = up->ut_name; 41112712Ssam printf("login: "); 41212687Ssam while ((c = getchar()) != '\n') { 41312687Ssam if (c == ' ') 41412687Ssam c = '_'; 41512687Ssam if (c == EOF) 41612687Ssam exit(0); 41712687Ssam if (namep < up->ut_name+NMAX) 41812687Ssam *namep++ = c; 41912687Ssam } 42012687Ssam } 42114897Sedward strncpy(lusername, up->ut_name, NMAX); 42214897Sedward lusername[NMAX] = 0; 42314897Sedward if ((pwd = getpwnam(lusername)) == NULL) 42412687Ssam pwd = &nouser; 42512687Ssam } 42612687Ssam 42712687Ssam timedout() 42812687Ssam { 42912687Ssam 43012687Ssam printf("Login timed out after %d seconds\n", timeout); 43112687Ssam exit(0); 43212687Ssam } 43312687Ssam 4341043Sbill int stopmotd; 4351043Sbill catch() 4361043Sbill { 4376466Swnj 4381043Sbill signal(SIGINT, SIG_IGN); 4391043Sbill stopmotd++; 4401043Sbill } 4411043Sbill 4422822Swnj rootterm(tty) 4436466Swnj char *tty; 4442822Swnj { 44516453Sroot register struct ttyent *t; 4462822Swnj 44716453Sroot if ((t = getttynam(tty)) != NULL) { 44816453Sroot if (t->ty_status & TTY_SECURE) 44916453Sroot return (1); 4502822Swnj } 45116453Sroot return (0); 4522822Swnj } 4532822Swnj 4541043Sbill showmotd() 4551043Sbill { 4561043Sbill FILE *mf; 4571043Sbill register c; 4581043Sbill 4591043Sbill signal(SIGINT, catch); 46016453Sroot if ((mf = fopen("/etc/motd", "r")) != NULL) { 4612822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 4621043Sbill putchar(c); 4631043Sbill fclose(mf); 4641043Sbill } 4651043Sbill signal(SIGINT, SIG_IGN); 4661043Sbill } 4671043Sbill 4682822Swnj #undef UNKNOWN 4691043Sbill #define UNKNOWN "su" 4701043Sbill 4711043Sbill char * 4721043Sbill stypeof(ttyid) 47312687Ssam char *ttyid; 4741043Sbill { 47516453Sroot register struct ttyent *t; 4761043Sbill 47716453Sroot if (ttyid == NULL || (t = getttynam(ttyid)) == NULL) 4781043Sbill return (UNKNOWN); 47916453Sroot return (t->ty_type); 4801043Sbill } 4816005Swnj 48212687Ssam doremotelogin(host) 48312687Ssam char *host; 48412687Ssam { 48512687Ssam getstr(rusername, sizeof (rusername), "remuser"); 48612687Ssam getstr(lusername, sizeof (lusername), "locuser"); 48718549Ssam getstr(term, sizeof(term), "Terminal type"); 48813470Ssam if (getuid()) { 48913470Ssam pwd = &nouser; 49024712Sbloom return(-1); 49113470Ssam } 49212687Ssam pwd = getpwnam(lusername); 49313470Ssam if (pwd == NULL) { 49413470Ssam pwd = &nouser; 49524712Sbloom return(-1); 49613470Ssam } 49724712Sbloom return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername)); 49812687Ssam } 49912687Ssam 5006005Swnj getstr(buf, cnt, err) 5016005Swnj char *buf; 5026005Swnj int cnt; 5036005Swnj char *err; 5046005Swnj { 5056005Swnj char c; 5066005Swnj 5076005Swnj do { 5086005Swnj if (read(0, &c, 1) != 1) 5096005Swnj exit(1); 5106005Swnj if (--cnt < 0) { 5116005Swnj printf("%s too long\r\n", err); 5126005Swnj exit(1); 5136005Swnj } 5146005Swnj *buf++ = c; 5156005Swnj } while (c != 0); 5166005Swnj } 5176329Swnj 51812687Ssam char *speeds[] = 51912687Ssam { "0", "50", "75", "110", "134", "150", "200", "300", 52012687Ssam "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 52112687Ssam #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 52212687Ssam 52312687Ssam doremoteterm(term, tp) 52412687Ssam char *term; 52512687Ssam struct sgttyb *tp; 52612687Ssam { 52718549Ssam register char *cp = index(term, '/'), **cpp; 52818549Ssam char *speed; 52912687Ssam 53012687Ssam if (cp) { 53118549Ssam *cp++ = '\0'; 53218549Ssam speed = cp; 53318549Ssam cp = index(speed, '/'); 53418549Ssam if (cp) 53518549Ssam *cp++ = '\0'; 53618549Ssam for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) 53718549Ssam if (strcmp(*cpp, speed) == 0) { 53818549Ssam tp->sg_ispeed = tp->sg_ospeed = cpp-speeds; 53912687Ssam break; 54012687Ssam } 54112687Ssam } 54212687Ssam tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; 54312687Ssam } 54418549Ssam 54518549Ssam /* 54618549Ssam * Set the value of var to be arg in the Unix 4.2 BSD environment env. 54718549Ssam * Var should end with '='. 54818549Ssam * (bindings are of the form "var=value") 54918549Ssam * This procedure assumes the memory for the first level of environ 55018549Ssam * was allocated using malloc. 55118549Ssam */ 55224966Skarels setenv(var, value, clobber) 55318549Ssam char *var, *value; 55418549Ssam { 55518549Ssam extern char **environ; 55618549Ssam int index = 0; 55718549Ssam int varlen = strlen(var); 55818549Ssam int vallen = strlen(value); 55918549Ssam 56018549Ssam for (index = 0; environ[index] != NULL; index++) { 56118549Ssam if (strncmp(environ[index], var, varlen) == 0) { 56218549Ssam /* found it */ 56324966Skarels if (!clobber) 56424966Skarels return; 56518549Ssam environ[index] = malloc(varlen + vallen + 1); 56618549Ssam strcpy(environ[index], var); 56718549Ssam strcat(environ[index], value); 56818549Ssam return; 56918549Ssam } 57018549Ssam } 57118549Ssam environ = (char **) realloc(environ, sizeof (char *) * (index + 2)); 57218549Ssam if (environ == NULL) { 57318549Ssam fprintf(stderr, "login: malloc out of memory\n"); 57418549Ssam exit(1); 57518549Ssam } 57618549Ssam environ[index] = malloc(varlen + vallen + 1); 57718549Ssam strcpy(environ[index], var); 57818549Ssam strcat(environ[index], value); 57918549Ssam environ[++index] = NULL; 58018549Ssam } 58126862Smckusick 58227056Skarels tty_gid(default_gid) 58326876Smckusick int default_gid; 58426862Smckusick { 58526862Smckusick struct group *getgrnam(), *gr; 58626876Smckusick int gid = default_gid; 58726862Smckusick 58827056Skarels gr = getgrnam(TTYGRPNAME); 58926862Smckusick if (gr != (struct group *) 0) 59026862Smckusick gid = gr->gr_gid; 59126862Smckusick 59226862Smckusick endgrent(); 59326862Smckusick 59426876Smckusick return (gid); 59526862Smckusick } 596