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*25230Smckusick static char sccsid[] = "@(#)login.c 5.9 (Berkeley) 10/18/85"; 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> 391043Sbill 4016453Sroot #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 412822Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 422822Swnj 436197Sroot #define NMAX sizeof(utmp.ut_name) 44*25230Smckusick #define HMAX sizeof(utmp.ut_host) 451043Sbill 462822Swnj #define FALSE 0 472822Swnj #define TRUE -1 482822Swnj 492822Swnj char nolog[] = "/etc/nologin"; 502822Swnj char qlog[] = ".hushlogin"; 511043Sbill char maildir[30] = "/usr/spool/mail/"; 521043Sbill char lastlog[] = "/usr/adm/lastlog"; 539867Ssam struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; 541043Sbill struct sgttyb ttyb; 551043Sbill struct utmp utmp; 561043Sbill char minusnam[16] = "-"; 5718549Ssam char *envinit[] = { 0 }; /* now set by setenv calls */ 5812687Ssam /* 5912687Ssam * This bounds the time given to login. We initialize it here 6012687Ssam * so it can be patched on machines where it's too small. 6112687Ssam */ 6212687Ssam int timeout = 60; 636005Swnj 6418549Ssam char term[64]; 656005Swnj 661043Sbill struct passwd *pwd; 6718549Ssam char *strcat(), *rindex(), *index(), *malloc(), *realloc(); 6812687Ssam int timedout(); 691043Sbill char *ttyname(); 701043Sbill char *crypt(); 711043Sbill char *getpass(); 721043Sbill char *stypeof(); 731043Sbill extern char **environ; 7412678Ssam extern int errno; 751043Sbill 7613074Ssam struct tchars tc = { 7713074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 781365Sbill }; 7913074Ssam struct ltchars ltc = { 8013074Ssam CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 8113074Ssam }; 821365Sbill 8318549Ssam struct winsize win = { 0, 0, 0, 0 }; 8418549Ssam 856005Swnj int rflag; 8624712Sbloom int usererr = -1; 876197Sroot char rusername[NMAX+1], lusername[NMAX+1]; 886005Swnj char rpassword[NMAX+1]; 896878Smckusick char name[NMAX+1]; 906197Sroot char *rhost; 916005Swnj 921043Sbill main(argc, argv) 9312687Ssam char *argv[]; 941043Sbill { 951043Sbill register char *namep; 9618549Ssam int pflag = 0, hflag = 0, t, f, c; 9712687Ssam int invalid, quietlog; 982822Swnj FILE *nlfd; 9916453Sroot char *ttyn, *tty; 10018549Ssam int ldisc = 0, zero = 0, i; 10118549Ssam char **envnew; 1021043Sbill 10312687Ssam signal(SIGALRM, timedout); 10412687Ssam alarm(timeout); 1051043Sbill signal(SIGQUIT, SIG_IGN); 1061043Sbill signal(SIGINT, SIG_IGN); 10712687Ssam setpriority(PRIO_PROCESS, 0, 0); 10812678Ssam quota(Q_SETUID, 0, 0, 0); 10912687Ssam /* 11018549Ssam * -p is used by getty to tell login not to destroy the environment 11112687Ssam * -r is used by rlogind to cause the autologin protocol; 11212687Ssam * -h is used by other servers to pass the name of the 11312687Ssam * remote host to login so that it may be placed in utmp and wtmp 11412687Ssam */ 11524712Sbloom while (argc > 1) { 11612687Ssam if (strcmp(argv[1], "-r") == 0) { 11724712Sbloom if (rflag || hflag) { 11824712Sbloom printf("Only one of -r and -h allowed\n"); 11924712Sbloom exit(1); 12024712Sbloom } 12124712Sbloom rflag = 1; 12224712Sbloom usererr = doremotelogin(argv[2]); 12312687Ssam SCPYN(utmp.ut_host, argv[2]); 12424712Sbloom argc -= 2; 12524712Sbloom argv += 2; 12624712Sbloom continue; 1276197Sroot } 12812687Ssam if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { 12924712Sbloom if (rflag || hflag) { 13024712Sbloom printf("Only one of -r and -h allowed\n"); 13124712Sbloom exit(1); 13224712Sbloom } 13318549Ssam hflag = 1; 13412687Ssam SCPYN(utmp.ut_host, argv[2]); 13524712Sbloom argc -= 2; 13624712Sbloom argv += 2; 13724712Sbloom continue; 1386197Sroot } 13918549Ssam if (strcmp(argv[1], "-p") == 0) { 14018549Ssam argc--; 14118549Ssam argv++; 14218549Ssam pflag = 1; 14324712Sbloom continue; 14418549Ssam } 14524712Sbloom break; 1466005Swnj } 14713074Ssam ioctl(0, TIOCLSET, &zero); 1481547Sbill ioctl(0, TIOCNXCL, 0); 1496329Swnj ioctl(0, FIONBIO, &zero); 1506329Swnj ioctl(0, FIOASYNC, &zero); 15113074Ssam ioctl(0, TIOCGETP, &ttyb); 15212687Ssam /* 15312687Ssam * If talking to an rlogin process, 15412687Ssam * propagate the terminal type and 15512687Ssam * baud rate across the network. 15612687Ssam */ 15712687Ssam if (rflag) 15812687Ssam doremoteterm(term, &ttyb); 15913074Ssam ioctl(0, TIOCSLTC, <c); 16013074Ssam ioctl(0, TIOCSETC, &tc); 16113074Ssam ioctl(0, TIOCSETP, &ttyb); 16224849Smckusick for (t = getdtablesize(); t > 2; t--) 1631043Sbill close(t); 1641043Sbill ttyn = ttyname(0); 16516453Sroot if (ttyn == (char *)0) 1661043Sbill ttyn = "/dev/tty??"; 16716453Sroot tty = rindex(ttyn, '/'); 16816453Sroot if (tty == NULL) 16916453Sroot tty = ttyn; 17016453Sroot else 17116453Sroot tty++; 17224852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 17316453Sroot t = 0; 17425163Sbloom invalid = FALSE; 1752822Swnj do { 1762822Swnj ldisc = 0; 1772822Swnj ioctl(0, TIOCSETD, &ldisc); 1782822Swnj SCPYN(utmp.ut_name, ""); 17912687Ssam /* 18012687Ssam * Name specified, take it. 18112687Ssam */ 18212687Ssam if (argc > 1) { 1832822Swnj SCPYN(utmp.ut_name, argv[1]); 1842822Swnj argc = 0; 1851043Sbill } 18612687Ssam /* 18712687Ssam * If remote login take given name, 18812687Ssam * otherwise prompt user for something. 18912687Ssam */ 19025163Sbloom if (rflag && !invalid) 1919867Ssam SCPYN(utmp.ut_name, lusername); 19224883Smckusick else 19312687Ssam getloginname(&utmp); 19425163Sbloom invalid = FALSE; 1952822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 1962822Swnj ldisc = NTTYDISC; 1972822Swnj ioctl(0, TIOCSETD, &ldisc); 1982822Swnj } 19912687Ssam /* 20012687Ssam * If no remote login authentication and 20112687Ssam * a password exists for this user, prompt 20212687Ssam * for one and verify it. 20312687Ssam */ 20424712Sbloom if (usererr == -1 && *pwd->pw_passwd != '\0') { 20512687Ssam char *pp; 20612687Ssam 20712687Ssam setpriority(PRIO_PROCESS, 0, -4); 20812687Ssam pp = getpass("Password:"); 20912687Ssam namep = crypt(pp, pwd->pw_passwd); 21012687Ssam setpriority(PRIO_PROCESS, 0, 0); 21112687Ssam if (strcmp(namep, pwd->pw_passwd)) 21212687Ssam invalid = TRUE; 2132822Swnj } 21412687Ssam /* 21512687Ssam * If user not super-user, check for logins disabled. 21612687Ssam */ 2172822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 2182822Swnj while ((c = getc(nlfd)) != EOF) 2192822Swnj putchar(c); 2202822Swnj fflush(stdout); 2212822Swnj sleep(5); 2222822Swnj exit(0); 2232822Swnj } 22412687Ssam /* 22512687Ssam * If valid so far and root is logging in, 22612687Ssam * see if root logins on this terminal are permitted. 22712687Ssam */ 22816453Sroot if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { 229*25230Smckusick if (utmp.ut_host[0]) 230*25230Smckusick syslog(LOG_CRIT, 231*25230Smckusick "ROOT LOGIN REFUSED ON %s FROM %.*s", 232*25230Smckusick tty, HMAX, utmp.ut_host); 233*25230Smckusick else 234*25230Smckusick syslog(LOG_CRIT, 235*25230Smckusick "ROOT LOGIN REFUSED ON %s", tty); 2362822Swnj invalid = TRUE; 2372822Swnj } 2382822Swnj if (invalid) { 2391043Sbill printf("Login incorrect\n"); 24016453Sroot if (++t >= 5) { 241*25230Smckusick if (utmp.ut_host[0]) 242*25230Smckusick syslog(LOG_CRIT, 243*25230Smckusick "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s", 244*25230Smckusick tty, HMAX, utmp.ut_host, 245*25230Smckusick NMAX, utmp.ut_name); 246*25230Smckusick else 247*25230Smckusick syslog(LOG_CRIT, 248*25230Smckusick "REPEATED LOGIN FAILURES ON %s, %.*s", 249*25230Smckusick tty, NMAX, utmp.ut_name); 25016453Sroot ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 25118549Ssam close(0), close(1), close(2); 25216453Sroot sleep(10); 25316453Sroot exit(1); 25416453Sroot } 2551043Sbill } 2562822Swnj if (*pwd->pw_shell == '\0') 2572822Swnj pwd->pw_shell = "/bin/sh"; 2582822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 2592822Swnj if (chdir("/") < 0) { 2602822Swnj printf("No directory!\n"); 2612822Swnj invalid = TRUE; 2622822Swnj } else { 26312687Ssam printf("No directory! %s\n", 26412687Ssam "Logging in with home=/"); 2652822Swnj pwd->pw_dir = "/"; 2662822Swnj } 2671043Sbill } 26812687Ssam /* 26912687Ssam * Remote login invalid must have been because 27012687Ssam * of a restriction of some sort, no extra chances. 27112687Ssam */ 27224712Sbloom if (!usererr && invalid) 2736005Swnj exit(1); 2742822Swnj } while (invalid); 27512687Ssam /* committed to login turn off timeout */ 27612687Ssam alarm(0); 2771043Sbill 27821083Smckusick if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 27912678Ssam if (errno == EUSERS) 28012678Ssam printf("%s.\n%s.\n", 28112678Ssam "Too many users logged on already", 28212678Ssam "Try again later"); 28312678Ssam else if (errno == EPROCLIM) 28412678Ssam printf("You have too many processes running.\n"); 28512678Ssam else 28617664Sserge perror("quota (Q_SETUID)"); 28712678Ssam sleep(5); 28812678Ssam exit(0); 28912678Ssam } 2901043Sbill time(&utmp.ut_time); 2911043Sbill t = ttyslot(); 29216453Sroot if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { 2931043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 29416453Sroot SCPYN(utmp.ut_line, tty); 2951043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2961043Sbill close(f); 2971043Sbill } 29816453Sroot if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { 2991043Sbill write(f, (char *)&utmp, sizeof(utmp)); 3001043Sbill close(f); 3011043Sbill } 30216453Sroot quietlog = access(qlog, F_OK) == 0; 30316453Sroot if ((f = open(lastlog, O_RDWR)) >= 0) { 3042822Swnj struct lastlog ll; 3052822Swnj 3062822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3072822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 30812687Ssam ll.ll_time != 0 && !quietlog) { 30912687Ssam printf("Last login: %.*s ", 31012687Ssam 24-5, (char *)ctime(&ll.ll_time)); 31112687Ssam if (*ll.ll_host != '\0') 31212687Ssam printf("from %.*s\n", 31312687Ssam sizeof (ll.ll_host), ll.ll_host); 31412687Ssam else 31512687Ssam printf("on %.*s\n", 31612687Ssam sizeof (ll.ll_line), ll.ll_line); 3172822Swnj } 3182822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3192822Swnj time(&ll.ll_time); 32016453Sroot SCPYN(ll.ll_line, tty); 32112687Ssam SCPYN(ll.ll_host, utmp.ut_host); 3222822Swnj write(f, (char *) &ll, sizeof ll); 3232822Swnj close(f); 3242822Swnj } 3251043Sbill chown(ttyn, pwd->pw_uid, pwd->pw_gid); 32624849Smckusick if (!hflag && !rflag) /* XXX */ 32718549Ssam ioctl(0, TIOCSWINSZ, &win); 3289867Ssam chmod(ttyn, 0622); 3291043Sbill setgid(pwd->pw_gid); 3306878Smckusick strncpy(name, utmp.ut_name, NMAX); 3316878Smckusick name[NMAX] = '\0'; 3329224Ssam initgroups(name, pwd->pw_gid); 33312678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 3341043Sbill setuid(pwd->pw_uid); 33518549Ssam /* destroy environment unless user has asked to preserve it */ 33618549Ssam if (!pflag) 33718549Ssam environ = envinit; 33818549Ssam 33918549Ssam /* set up environment, this time without destruction */ 34018549Ssam /* copy the environment before setenving */ 34118549Ssam i = 0; 34218549Ssam while (environ[i] != NULL) 34318549Ssam i++; 34418549Ssam envnew = (char **) malloc(sizeof (char *) * (i + 1)); 34518549Ssam for (; i >= 0; i--) 34618549Ssam envnew[i] = environ[i]; 34718549Ssam environ = envnew; 34818549Ssam 34924966Skarels setenv("HOME=", pwd->pw_dir, 1); 35024966Skarels setenv("SHELL=", pwd->pw_shell, 1); 35118549Ssam if (term[0] == '\0') 35218549Ssam strncpy(term, stypeof(tty), sizeof(term)); 35324966Skarels setenv("TERM=", term, 0); 35424966Skarels setenv("USER=", pwd->pw_name, 1); 35524966Skarels setenv("PATH=", ":/usr/ucb:/bin:/usr/bin", 0); 35618549Ssam 3571043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 3581043Sbill namep = pwd->pw_shell; 3591043Sbill else 3601043Sbill namep++; 3611043Sbill strcat(minusnam, namep); 36216453Sroot if (tty[sizeof("tty")-1] == 'd') 36318549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 36418549Ssam if (pwd->pw_uid == 0) 365*25230Smckusick if (utmp.ut_host[0]) 366*25230Smckusick syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", 367*25230Smckusick tty, HMAX, utmp.ut_host); 368*25230Smckusick else 369*25230Smckusick syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); 3706329Swnj if (!quietlog) { 37117664Sserge struct stat st; 37218549Ssam 3732822Swnj showmotd(); 3742822Swnj strcat(maildir, pwd->pw_name); 37517664Sserge if (stat(maildir, &st) == 0 && st.st_size != 0) 37617664Sserge printf("You have %smail.\n", 37718549Ssam (st.st_mtime > st.st_atime) ? "new " : ""); 3782822Swnj } 37912687Ssam signal(SIGALRM, SIG_DFL); 3801043Sbill signal(SIGQUIT, SIG_DFL); 3811043Sbill signal(SIGINT, SIG_DFL); 3823935Sroot signal(SIGTSTP, SIG_IGN); 3831043Sbill execlp(pwd->pw_shell, minusnam, 0); 3842822Swnj perror(pwd->pw_shell); 3851043Sbill printf("No shell\n"); 3861043Sbill exit(0); 3871043Sbill } 3881043Sbill 38912687Ssam getloginname(up) 39012687Ssam register struct utmp *up; 39112687Ssam { 39212687Ssam register char *namep; 39312712Ssam char c; 39412687Ssam 39512687Ssam while (up->ut_name[0] == '\0') { 39614897Sedward namep = up->ut_name; 39712712Ssam printf("login: "); 39812687Ssam while ((c = getchar()) != '\n') { 39912687Ssam if (c == ' ') 40012687Ssam c = '_'; 40112687Ssam if (c == EOF) 40212687Ssam exit(0); 40312687Ssam if (namep < up->ut_name+NMAX) 40412687Ssam *namep++ = c; 40512687Ssam } 40612687Ssam } 40714897Sedward strncpy(lusername, up->ut_name, NMAX); 40814897Sedward lusername[NMAX] = 0; 40914897Sedward if ((pwd = getpwnam(lusername)) == NULL) 41012687Ssam pwd = &nouser; 41112687Ssam } 41212687Ssam 41312687Ssam timedout() 41412687Ssam { 41512687Ssam 41612687Ssam printf("Login timed out after %d seconds\n", timeout); 41712687Ssam exit(0); 41812687Ssam } 41912687Ssam 4201043Sbill int stopmotd; 4211043Sbill catch() 4221043Sbill { 4236466Swnj 4241043Sbill signal(SIGINT, SIG_IGN); 4251043Sbill stopmotd++; 4261043Sbill } 4271043Sbill 4282822Swnj rootterm(tty) 4296466Swnj char *tty; 4302822Swnj { 43116453Sroot register struct ttyent *t; 4322822Swnj 43316453Sroot if ((t = getttynam(tty)) != NULL) { 43416453Sroot if (t->ty_status & TTY_SECURE) 43516453Sroot return (1); 4362822Swnj } 43716453Sroot return (0); 4382822Swnj } 4392822Swnj 4401043Sbill showmotd() 4411043Sbill { 4421043Sbill FILE *mf; 4431043Sbill register c; 4441043Sbill 4451043Sbill signal(SIGINT, catch); 44616453Sroot if ((mf = fopen("/etc/motd", "r")) != NULL) { 4472822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 4481043Sbill putchar(c); 4491043Sbill fclose(mf); 4501043Sbill } 4511043Sbill signal(SIGINT, SIG_IGN); 4521043Sbill } 4531043Sbill 4542822Swnj #undef UNKNOWN 4551043Sbill #define UNKNOWN "su" 4561043Sbill 4571043Sbill char * 4581043Sbill stypeof(ttyid) 45912687Ssam char *ttyid; 4601043Sbill { 46116453Sroot register struct ttyent *t; 4621043Sbill 46316453Sroot if (ttyid == NULL || (t = getttynam(ttyid)) == NULL) 4641043Sbill return (UNKNOWN); 46516453Sroot return (t->ty_type); 4661043Sbill } 4676005Swnj 46812687Ssam doremotelogin(host) 46912687Ssam char *host; 47012687Ssam { 47112687Ssam getstr(rusername, sizeof (rusername), "remuser"); 47212687Ssam getstr(lusername, sizeof (lusername), "locuser"); 47318549Ssam getstr(term, sizeof(term), "Terminal type"); 47413470Ssam if (getuid()) { 47513470Ssam pwd = &nouser; 47624712Sbloom return(-1); 47713470Ssam } 47812687Ssam pwd = getpwnam(lusername); 47913470Ssam if (pwd == NULL) { 48013470Ssam pwd = &nouser; 48124712Sbloom return(-1); 48213470Ssam } 48324712Sbloom return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername)); 48412687Ssam } 48512687Ssam 4866005Swnj getstr(buf, cnt, err) 4876005Swnj char *buf; 4886005Swnj int cnt; 4896005Swnj char *err; 4906005Swnj { 4916005Swnj char c; 4926005Swnj 4936005Swnj do { 4946005Swnj if (read(0, &c, 1) != 1) 4956005Swnj exit(1); 4966005Swnj if (--cnt < 0) { 4976005Swnj printf("%s too long\r\n", err); 4986005Swnj exit(1); 4996005Swnj } 5006005Swnj *buf++ = c; 5016005Swnj } while (c != 0); 5026005Swnj } 5036329Swnj 50412687Ssam char *speeds[] = 50512687Ssam { "0", "50", "75", "110", "134", "150", "200", "300", 50612687Ssam "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 50712687Ssam #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 50812687Ssam 50912687Ssam doremoteterm(term, tp) 51012687Ssam char *term; 51112687Ssam struct sgttyb *tp; 51212687Ssam { 51318549Ssam register char *cp = index(term, '/'), **cpp; 51418549Ssam char *speed; 51512687Ssam 51612687Ssam if (cp) { 51718549Ssam *cp++ = '\0'; 51818549Ssam speed = cp; 51918549Ssam cp = index(speed, '/'); 52018549Ssam if (cp) 52118549Ssam *cp++ = '\0'; 52218549Ssam for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) 52318549Ssam if (strcmp(*cpp, speed) == 0) { 52418549Ssam tp->sg_ispeed = tp->sg_ospeed = cpp-speeds; 52512687Ssam break; 52612687Ssam } 52724849Smckusick compatsiz(cp); 52812687Ssam } 52912687Ssam tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; 53012687Ssam } 53118549Ssam 53224849Smckusick /* BEGIN TRASH 53324849Smckusick * 53424849Smckusick * This is here only long enough to get us by to the revised rlogin 53524849Smckusick */ 53624849Smckusick compatsiz(cp) 53724849Smckusick char *cp; 53824849Smckusick { 53924849Smckusick struct winsize ws; 54024849Smckusick 54124849Smckusick ws.ws_row = ws.ws_col = -1; 54224849Smckusick ws.ws_xpixel = ws.ws_ypixel = -1; 54324849Smckusick if (cp) { 54424849Smckusick ws.ws_row = atoi(cp); 54524849Smckusick cp = index(cp, ','); 54624849Smckusick if (cp == 0) 54724849Smckusick goto done; 54824849Smckusick ws.ws_col = atoi(++cp); 54924849Smckusick cp = index(cp, ','); 55024849Smckusick if (cp == 0) 55124849Smckusick goto done; 55224849Smckusick ws.ws_xpixel = atoi(++cp); 55324849Smckusick cp = index(cp, ','); 55424849Smckusick if (cp == 0) 55524849Smckusick goto done; 55624849Smckusick ws.ws_ypixel = atoi(++cp); 55724849Smckusick } 55824849Smckusick done: 55924849Smckusick if (ws.ws_row != -1 && ws.ws_col != -1 && 56024849Smckusick ws.ws_xpixel != -1 && ws.ws_ypixel != -1) 56124849Smckusick ioctl(0, TIOCSWINSZ, &ws); 56224849Smckusick } 56324849Smckusick /* END TRASH */ 56424849Smckusick 56518549Ssam /* 56618549Ssam * Set the value of var to be arg in the Unix 4.2 BSD environment env. 56718549Ssam * Var should end with '='. 56818549Ssam * (bindings are of the form "var=value") 56918549Ssam * This procedure assumes the memory for the first level of environ 57018549Ssam * was allocated using malloc. 57118549Ssam */ 57224966Skarels setenv(var, value, clobber) 57318549Ssam char *var, *value; 57418549Ssam { 57518549Ssam extern char **environ; 57618549Ssam int index = 0; 57718549Ssam int varlen = strlen(var); 57818549Ssam int vallen = strlen(value); 57918549Ssam 58018549Ssam for (index = 0; environ[index] != NULL; index++) { 58118549Ssam if (strncmp(environ[index], var, varlen) == 0) { 58218549Ssam /* found it */ 58324966Skarels if (!clobber) 58424966Skarels return; 58518549Ssam environ[index] = malloc(varlen + vallen + 1); 58618549Ssam strcpy(environ[index], var); 58718549Ssam strcat(environ[index], value); 58818549Ssam return; 58918549Ssam } 59018549Ssam } 59118549Ssam environ = (char **) realloc(environ, sizeof (char *) * (index + 2)); 59218549Ssam if (environ == NULL) { 59318549Ssam fprintf(stderr, "login: malloc out of memory\n"); 59418549Ssam exit(1); 59518549Ssam } 59618549Ssam environ[index] = malloc(varlen + vallen + 1); 59718549Ssam strcpy(environ[index], var); 59818549Ssam strcat(environ[index], value); 59918549Ssam environ[++index] = NULL; 60018549Ssam } 601