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*25163Sbloom static char sccsid[] = "@(#)login.c 5.8 (Berkeley) 10/10/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) 441043Sbill 452822Swnj #define FALSE 0 462822Swnj #define TRUE -1 472822Swnj 482822Swnj char nolog[] = "/etc/nologin"; 492822Swnj char qlog[] = ".hushlogin"; 501043Sbill char maildir[30] = "/usr/spool/mail/"; 511043Sbill char lastlog[] = "/usr/adm/lastlog"; 529867Ssam struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; 531043Sbill struct sgttyb ttyb; 541043Sbill struct utmp utmp; 551043Sbill char minusnam[16] = "-"; 5618549Ssam char *envinit[] = { 0 }; /* now set by setenv calls */ 5712687Ssam /* 5812687Ssam * This bounds the time given to login. We initialize it here 5912687Ssam * so it can be patched on machines where it's too small. 6012687Ssam */ 6112687Ssam int timeout = 60; 626005Swnj 6318549Ssam char term[64]; 646005Swnj 651043Sbill struct passwd *pwd; 6618549Ssam char *strcat(), *rindex(), *index(), *malloc(), *realloc(); 6712687Ssam int timedout(); 681043Sbill char *ttyname(); 691043Sbill char *crypt(); 701043Sbill char *getpass(); 711043Sbill char *stypeof(); 721043Sbill extern char **environ; 7312678Ssam extern int errno; 741043Sbill 7513074Ssam struct tchars tc = { 7613074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 771365Sbill }; 7813074Ssam struct ltchars ltc = { 7913074Ssam CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 8013074Ssam }; 811365Sbill 8218549Ssam struct winsize win = { 0, 0, 0, 0 }; 8318549Ssam 846005Swnj int rflag; 8524712Sbloom int usererr = -1; 866197Sroot char rusername[NMAX+1], lusername[NMAX+1]; 876005Swnj char rpassword[NMAX+1]; 886878Smckusick char name[NMAX+1]; 896197Sroot char *rhost; 906005Swnj 911043Sbill main(argc, argv) 9212687Ssam char *argv[]; 931043Sbill { 941043Sbill register char *namep; 9518549Ssam int pflag = 0, hflag = 0, t, f, c; 9612687Ssam int invalid, quietlog; 972822Swnj FILE *nlfd; 9816453Sroot char *ttyn, *tty; 9918549Ssam int ldisc = 0, zero = 0, i; 10018549Ssam char **envnew; 1011043Sbill 10212687Ssam signal(SIGALRM, timedout); 10312687Ssam alarm(timeout); 1041043Sbill signal(SIGQUIT, SIG_IGN); 1051043Sbill signal(SIGINT, SIG_IGN); 10612687Ssam setpriority(PRIO_PROCESS, 0, 0); 10712678Ssam quota(Q_SETUID, 0, 0, 0); 10812687Ssam /* 10918549Ssam * -p is used by getty to tell login not to destroy the environment 11012687Ssam * -r is used by rlogind to cause the autologin protocol; 11112687Ssam * -h is used by other servers to pass the name of the 11212687Ssam * remote host to login so that it may be placed in utmp and wtmp 11312687Ssam */ 11424712Sbloom while (argc > 1) { 11512687Ssam if (strcmp(argv[1], "-r") == 0) { 11624712Sbloom if (rflag || hflag) { 11724712Sbloom printf("Only one of -r and -h allowed\n"); 11824712Sbloom exit(1); 11924712Sbloom } 12024712Sbloom rflag = 1; 12124712Sbloom usererr = doremotelogin(argv[2]); 12212687Ssam SCPYN(utmp.ut_host, argv[2]); 12324712Sbloom argc -= 2; 12424712Sbloom argv += 2; 12524712Sbloom continue; 1266197Sroot } 12712687Ssam if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { 12824712Sbloom if (rflag || hflag) { 12924712Sbloom printf("Only one of -r and -h allowed\n"); 13024712Sbloom exit(1); 13124712Sbloom } 13218549Ssam hflag = 1; 13312687Ssam SCPYN(utmp.ut_host, argv[2]); 13424712Sbloom argc -= 2; 13524712Sbloom argv += 2; 13624712Sbloom continue; 1376197Sroot } 13818549Ssam if (strcmp(argv[1], "-p") == 0) { 13918549Ssam argc--; 14018549Ssam argv++; 14118549Ssam pflag = 1; 14224712Sbloom continue; 14318549Ssam } 14424712Sbloom break; 1456005Swnj } 14613074Ssam ioctl(0, TIOCLSET, &zero); 1471547Sbill ioctl(0, TIOCNXCL, 0); 1486329Swnj ioctl(0, FIONBIO, &zero); 1496329Swnj ioctl(0, FIOASYNC, &zero); 15013074Ssam ioctl(0, TIOCGETP, &ttyb); 15112687Ssam /* 15212687Ssam * If talking to an rlogin process, 15312687Ssam * propagate the terminal type and 15412687Ssam * baud rate across the network. 15512687Ssam */ 15612687Ssam if (rflag) 15712687Ssam doremoteterm(term, &ttyb); 15813074Ssam ioctl(0, TIOCSLTC, <c); 15913074Ssam ioctl(0, TIOCSETC, &tc); 16013074Ssam ioctl(0, TIOCSETP, &ttyb); 16124849Smckusick for (t = getdtablesize(); t > 2; t--) 1621043Sbill close(t); 1631043Sbill ttyn = ttyname(0); 16416453Sroot if (ttyn == (char *)0) 1651043Sbill ttyn = "/dev/tty??"; 16616453Sroot tty = rindex(ttyn, '/'); 16716453Sroot if (tty == NULL) 16816453Sroot tty = ttyn; 16916453Sroot else 17016453Sroot tty++; 17124852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 17216453Sroot t = 0; 173*25163Sbloom invalid = FALSE; 1742822Swnj do { 1752822Swnj ldisc = 0; 1762822Swnj ioctl(0, TIOCSETD, &ldisc); 1772822Swnj SCPYN(utmp.ut_name, ""); 17812687Ssam /* 17912687Ssam * Name specified, take it. 18012687Ssam */ 18112687Ssam if (argc > 1) { 1822822Swnj SCPYN(utmp.ut_name, argv[1]); 1832822Swnj argc = 0; 1841043Sbill } 18512687Ssam /* 18612687Ssam * If remote login take given name, 18712687Ssam * otherwise prompt user for something. 18812687Ssam */ 189*25163Sbloom if (rflag && !invalid) 1909867Ssam SCPYN(utmp.ut_name, lusername); 19124883Smckusick else 19212687Ssam getloginname(&utmp); 193*25163Sbloom invalid = FALSE; 1942822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 1952822Swnj ldisc = NTTYDISC; 1962822Swnj ioctl(0, TIOCSETD, &ldisc); 1972822Swnj } 19812687Ssam /* 19912687Ssam * If no remote login authentication and 20012687Ssam * a password exists for this user, prompt 20112687Ssam * for one and verify it. 20212687Ssam */ 20324712Sbloom if (usererr == -1 && *pwd->pw_passwd != '\0') { 20412687Ssam char *pp; 20512687Ssam 20612687Ssam setpriority(PRIO_PROCESS, 0, -4); 20712687Ssam pp = getpass("Password:"); 20812687Ssam namep = crypt(pp, pwd->pw_passwd); 20912687Ssam setpriority(PRIO_PROCESS, 0, 0); 21012687Ssam if (strcmp(namep, pwd->pw_passwd)) 21112687Ssam invalid = TRUE; 2122822Swnj } 21312687Ssam /* 21412687Ssam * If user not super-user, check for logins disabled. 21512687Ssam */ 2162822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 2172822Swnj while ((c = getc(nlfd)) != EOF) 2182822Swnj putchar(c); 2192822Swnj fflush(stdout); 2202822Swnj sleep(5); 2212822Swnj exit(0); 2222822Swnj } 22312687Ssam /* 22412687Ssam * If valid so far and root is logging in, 22512687Ssam * see if root logins on this terminal are permitted. 22612687Ssam */ 22716453Sroot if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { 22824852Seric syslog(LOG_CRIT, "ROOT LOGIN REFUSED %s", tty); 2292822Swnj invalid = TRUE; 2302822Swnj } 2312822Swnj if (invalid) { 2321043Sbill printf("Login incorrect\n"); 23316453Sroot if (++t >= 5) { 23424852Seric syslog(LOG_CRIT, 23516453Sroot "REPEATED LOGIN FAILURES %s, %s", 23616453Sroot tty, utmp.ut_name); 23716453Sroot ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 23818549Ssam close(0), close(1), close(2); 23916453Sroot sleep(10); 24016453Sroot exit(1); 24116453Sroot } 2421043Sbill } 2432822Swnj if (*pwd->pw_shell == '\0') 2442822Swnj pwd->pw_shell = "/bin/sh"; 2452822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 2462822Swnj if (chdir("/") < 0) { 2472822Swnj printf("No directory!\n"); 2482822Swnj invalid = TRUE; 2492822Swnj } else { 25012687Ssam printf("No directory! %s\n", 25112687Ssam "Logging in with home=/"); 2522822Swnj pwd->pw_dir = "/"; 2532822Swnj } 2541043Sbill } 25512687Ssam /* 25612687Ssam * Remote login invalid must have been because 25712687Ssam * of a restriction of some sort, no extra chances. 25812687Ssam */ 25924712Sbloom if (!usererr && invalid) 2606005Swnj exit(1); 2612822Swnj } while (invalid); 26212687Ssam /* committed to login turn off timeout */ 26312687Ssam alarm(0); 2641043Sbill 26521083Smckusick if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 26612678Ssam if (errno == EUSERS) 26712678Ssam printf("%s.\n%s.\n", 26812678Ssam "Too many users logged on already", 26912678Ssam "Try again later"); 27012678Ssam else if (errno == EPROCLIM) 27112678Ssam printf("You have too many processes running.\n"); 27212678Ssam else 27317664Sserge perror("quota (Q_SETUID)"); 27412678Ssam sleep(5); 27512678Ssam exit(0); 27612678Ssam } 2771043Sbill time(&utmp.ut_time); 2781043Sbill t = ttyslot(); 27916453Sroot if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { 2801043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 28116453Sroot SCPYN(utmp.ut_line, tty); 2821043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2831043Sbill close(f); 2841043Sbill } 28516453Sroot if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { 2861043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2871043Sbill close(f); 2881043Sbill } 28916453Sroot quietlog = access(qlog, F_OK) == 0; 29016453Sroot if ((f = open(lastlog, O_RDWR)) >= 0) { 2912822Swnj struct lastlog ll; 2922822Swnj 2932822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 2942822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 29512687Ssam ll.ll_time != 0 && !quietlog) { 29612687Ssam printf("Last login: %.*s ", 29712687Ssam 24-5, (char *)ctime(&ll.ll_time)); 29812687Ssam if (*ll.ll_host != '\0') 29912687Ssam printf("from %.*s\n", 30012687Ssam sizeof (ll.ll_host), ll.ll_host); 30112687Ssam else 30212687Ssam printf("on %.*s\n", 30312687Ssam sizeof (ll.ll_line), ll.ll_line); 3042822Swnj } 3052822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3062822Swnj time(&ll.ll_time); 30716453Sroot SCPYN(ll.ll_line, tty); 30812687Ssam SCPYN(ll.ll_host, utmp.ut_host); 3092822Swnj write(f, (char *) &ll, sizeof ll); 3102822Swnj close(f); 3112822Swnj } 3121043Sbill chown(ttyn, pwd->pw_uid, pwd->pw_gid); 31324849Smckusick if (!hflag && !rflag) /* XXX */ 31418549Ssam ioctl(0, TIOCSWINSZ, &win); 3159867Ssam chmod(ttyn, 0622); 3161043Sbill setgid(pwd->pw_gid); 3176878Smckusick strncpy(name, utmp.ut_name, NMAX); 3186878Smckusick name[NMAX] = '\0'; 3199224Ssam initgroups(name, pwd->pw_gid); 32012678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 3211043Sbill setuid(pwd->pw_uid); 32218549Ssam /* destroy environment unless user has asked to preserve it */ 32318549Ssam if (!pflag) 32418549Ssam environ = envinit; 32518549Ssam 32618549Ssam /* set up environment, this time without destruction */ 32718549Ssam /* copy the environment before setenving */ 32818549Ssam i = 0; 32918549Ssam while (environ[i] != NULL) 33018549Ssam i++; 33118549Ssam envnew = (char **) malloc(sizeof (char *) * (i + 1)); 33218549Ssam for (; i >= 0; i--) 33318549Ssam envnew[i] = environ[i]; 33418549Ssam environ = envnew; 33518549Ssam 33624966Skarels setenv("HOME=", pwd->pw_dir, 1); 33724966Skarels setenv("SHELL=", pwd->pw_shell, 1); 33818549Ssam if (term[0] == '\0') 33918549Ssam strncpy(term, stypeof(tty), sizeof(term)); 34024966Skarels setenv("TERM=", term, 0); 34124966Skarels setenv("USER=", pwd->pw_name, 1); 34224966Skarels setenv("PATH=", ":/usr/ucb:/bin:/usr/bin", 0); 34318549Ssam 3441043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 3451043Sbill namep = pwd->pw_shell; 3461043Sbill else 3471043Sbill namep++; 3481043Sbill strcat(minusnam, namep); 34916453Sroot if (tty[sizeof("tty")-1] == 'd') 35018549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 35118549Ssam if (pwd->pw_uid == 0) 35224852Seric syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); 3536329Swnj if (!quietlog) { 35417664Sserge struct stat st; 35518549Ssam 3562822Swnj showmotd(); 3572822Swnj strcat(maildir, pwd->pw_name); 35817664Sserge if (stat(maildir, &st) == 0 && st.st_size != 0) 35917664Sserge printf("You have %smail.\n", 36018549Ssam (st.st_mtime > st.st_atime) ? "new " : ""); 3612822Swnj } 36212687Ssam signal(SIGALRM, SIG_DFL); 3631043Sbill signal(SIGQUIT, SIG_DFL); 3641043Sbill signal(SIGINT, SIG_DFL); 3653935Sroot signal(SIGTSTP, SIG_IGN); 3661043Sbill execlp(pwd->pw_shell, minusnam, 0); 3672822Swnj perror(pwd->pw_shell); 3681043Sbill printf("No shell\n"); 3691043Sbill exit(0); 3701043Sbill } 3711043Sbill 37212687Ssam getloginname(up) 37312687Ssam register struct utmp *up; 37412687Ssam { 37512687Ssam register char *namep; 37612712Ssam char c; 37712687Ssam 37812687Ssam while (up->ut_name[0] == '\0') { 37914897Sedward namep = up->ut_name; 38012712Ssam printf("login: "); 38112687Ssam while ((c = getchar()) != '\n') { 38212687Ssam if (c == ' ') 38312687Ssam c = '_'; 38412687Ssam if (c == EOF) 38512687Ssam exit(0); 38612687Ssam if (namep < up->ut_name+NMAX) 38712687Ssam *namep++ = c; 38812687Ssam } 38912687Ssam } 39014897Sedward strncpy(lusername, up->ut_name, NMAX); 39114897Sedward lusername[NMAX] = 0; 39214897Sedward if ((pwd = getpwnam(lusername)) == NULL) 39312687Ssam pwd = &nouser; 39412687Ssam } 39512687Ssam 39612687Ssam timedout() 39712687Ssam { 39812687Ssam 39912687Ssam printf("Login timed out after %d seconds\n", timeout); 40012687Ssam exit(0); 40112687Ssam } 40212687Ssam 4031043Sbill int stopmotd; 4041043Sbill catch() 4051043Sbill { 4066466Swnj 4071043Sbill signal(SIGINT, SIG_IGN); 4081043Sbill stopmotd++; 4091043Sbill } 4101043Sbill 4112822Swnj rootterm(tty) 4126466Swnj char *tty; 4132822Swnj { 41416453Sroot register struct ttyent *t; 4152822Swnj 41616453Sroot if ((t = getttynam(tty)) != NULL) { 41716453Sroot if (t->ty_status & TTY_SECURE) 41816453Sroot return (1); 4192822Swnj } 42016453Sroot return (0); 4212822Swnj } 4222822Swnj 4231043Sbill showmotd() 4241043Sbill { 4251043Sbill FILE *mf; 4261043Sbill register c; 4271043Sbill 4281043Sbill signal(SIGINT, catch); 42916453Sroot if ((mf = fopen("/etc/motd", "r")) != NULL) { 4302822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 4311043Sbill putchar(c); 4321043Sbill fclose(mf); 4331043Sbill } 4341043Sbill signal(SIGINT, SIG_IGN); 4351043Sbill } 4361043Sbill 4372822Swnj #undef UNKNOWN 4381043Sbill #define UNKNOWN "su" 4391043Sbill 4401043Sbill char * 4411043Sbill stypeof(ttyid) 44212687Ssam char *ttyid; 4431043Sbill { 44416453Sroot register struct ttyent *t; 4451043Sbill 44616453Sroot if (ttyid == NULL || (t = getttynam(ttyid)) == NULL) 4471043Sbill return (UNKNOWN); 44816453Sroot return (t->ty_type); 4491043Sbill } 4506005Swnj 45112687Ssam doremotelogin(host) 45212687Ssam char *host; 45312687Ssam { 45412687Ssam getstr(rusername, sizeof (rusername), "remuser"); 45512687Ssam getstr(lusername, sizeof (lusername), "locuser"); 45618549Ssam getstr(term, sizeof(term), "Terminal type"); 45713470Ssam if (getuid()) { 45813470Ssam pwd = &nouser; 45924712Sbloom return(-1); 46013470Ssam } 46112687Ssam pwd = getpwnam(lusername); 46213470Ssam if (pwd == NULL) { 46313470Ssam pwd = &nouser; 46424712Sbloom return(-1); 46513470Ssam } 46624712Sbloom return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername)); 46712687Ssam } 46812687Ssam 4696005Swnj getstr(buf, cnt, err) 4706005Swnj char *buf; 4716005Swnj int cnt; 4726005Swnj char *err; 4736005Swnj { 4746005Swnj char c; 4756005Swnj 4766005Swnj do { 4776005Swnj if (read(0, &c, 1) != 1) 4786005Swnj exit(1); 4796005Swnj if (--cnt < 0) { 4806005Swnj printf("%s too long\r\n", err); 4816005Swnj exit(1); 4826005Swnj } 4836005Swnj *buf++ = c; 4846005Swnj } while (c != 0); 4856005Swnj } 4866329Swnj 48712687Ssam char *speeds[] = 48812687Ssam { "0", "50", "75", "110", "134", "150", "200", "300", 48912687Ssam "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 49012687Ssam #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 49112687Ssam 49212687Ssam doremoteterm(term, tp) 49312687Ssam char *term; 49412687Ssam struct sgttyb *tp; 49512687Ssam { 49618549Ssam register char *cp = index(term, '/'), **cpp; 49718549Ssam char *speed; 49812687Ssam 49912687Ssam if (cp) { 50018549Ssam *cp++ = '\0'; 50118549Ssam speed = cp; 50218549Ssam cp = index(speed, '/'); 50318549Ssam if (cp) 50418549Ssam *cp++ = '\0'; 50518549Ssam for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) 50618549Ssam if (strcmp(*cpp, speed) == 0) { 50718549Ssam tp->sg_ispeed = tp->sg_ospeed = cpp-speeds; 50812687Ssam break; 50912687Ssam } 51024849Smckusick compatsiz(cp); 51112687Ssam } 51212687Ssam tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; 51312687Ssam } 51418549Ssam 51524849Smckusick /* BEGIN TRASH 51624849Smckusick * 51724849Smckusick * This is here only long enough to get us by to the revised rlogin 51824849Smckusick */ 51924849Smckusick compatsiz(cp) 52024849Smckusick char *cp; 52124849Smckusick { 52224849Smckusick struct winsize ws; 52324849Smckusick 52424849Smckusick ws.ws_row = ws.ws_col = -1; 52524849Smckusick ws.ws_xpixel = ws.ws_ypixel = -1; 52624849Smckusick if (cp) { 52724849Smckusick ws.ws_row = atoi(cp); 52824849Smckusick cp = index(cp, ','); 52924849Smckusick if (cp == 0) 53024849Smckusick goto done; 53124849Smckusick ws.ws_col = atoi(++cp); 53224849Smckusick cp = index(cp, ','); 53324849Smckusick if (cp == 0) 53424849Smckusick goto done; 53524849Smckusick ws.ws_xpixel = atoi(++cp); 53624849Smckusick cp = index(cp, ','); 53724849Smckusick if (cp == 0) 53824849Smckusick goto done; 53924849Smckusick ws.ws_ypixel = atoi(++cp); 54024849Smckusick } 54124849Smckusick done: 54224849Smckusick if (ws.ws_row != -1 && ws.ws_col != -1 && 54324849Smckusick ws.ws_xpixel != -1 && ws.ws_ypixel != -1) 54424849Smckusick ioctl(0, TIOCSWINSZ, &ws); 54524849Smckusick } 54624849Smckusick /* END TRASH */ 54724849Smckusick 54818549Ssam /* 54918549Ssam * Set the value of var to be arg in the Unix 4.2 BSD environment env. 55018549Ssam * Var should end with '='. 55118549Ssam * (bindings are of the form "var=value") 55218549Ssam * This procedure assumes the memory for the first level of environ 55318549Ssam * was allocated using malloc. 55418549Ssam */ 55524966Skarels setenv(var, value, clobber) 55618549Ssam char *var, *value; 55718549Ssam { 55818549Ssam extern char **environ; 55918549Ssam int index = 0; 56018549Ssam int varlen = strlen(var); 56118549Ssam int vallen = strlen(value); 56218549Ssam 56318549Ssam for (index = 0; environ[index] != NULL; index++) { 56418549Ssam if (strncmp(environ[index], var, varlen) == 0) { 56518549Ssam /* found it */ 56624966Skarels if (!clobber) 56724966Skarels return; 56818549Ssam environ[index] = malloc(varlen + vallen + 1); 56918549Ssam strcpy(environ[index], var); 57018549Ssam strcat(environ[index], value); 57118549Ssam return; 57218549Ssam } 57318549Ssam } 57418549Ssam environ = (char **) realloc(environ, sizeof (char *) * (index + 2)); 57518549Ssam if (environ == NULL) { 57618549Ssam fprintf(stderr, "login: malloc out of memory\n"); 57718549Ssam exit(1); 57818549Ssam } 57918549Ssam environ[index] = malloc(varlen + vallen + 1); 58018549Ssam strcpy(environ[index], var); 58118549Ssam strcat(environ[index], value); 58218549Ssam environ[++index] = NULL; 58318549Ssam } 584