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*24852Seric static char sccsid[] = "@(#)login.c 5.5 (Berkeley) 09/17/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++; 171*24852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 17216453Sroot t = 0; 1732822Swnj do { 1742822Swnj ldisc = 0; 1752822Swnj ioctl(0, TIOCSETD, &ldisc); 1762822Swnj invalid = FALSE; 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 */ 1896329Swnj if (rflag) { 1909867Ssam SCPYN(utmp.ut_name, lusername); 19124712Sbloom if (usererr == -1) 1926329Swnj rflag = 0; 19313470Ssam } else 19412687Ssam getloginname(&utmp); 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*24852Seric syslog(LOG_CRIT, "ROOT LOGIN REFUSED %s", tty); 2302822Swnj invalid = TRUE; 2312822Swnj } 2322822Swnj if (invalid) { 2331043Sbill printf("Login incorrect\n"); 23416453Sroot if (++t >= 5) { 235*24852Seric syslog(LOG_CRIT, 23616453Sroot "REPEATED LOGIN FAILURES %s, %s", 23716453Sroot tty, utmp.ut_name); 23816453Sroot ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 23918549Ssam close(0), close(1), close(2); 24016453Sroot sleep(10); 24116453Sroot exit(1); 24216453Sroot } 2431043Sbill } 2442822Swnj if (*pwd->pw_shell == '\0') 2452822Swnj pwd->pw_shell = "/bin/sh"; 2462822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 2472822Swnj if (chdir("/") < 0) { 2482822Swnj printf("No directory!\n"); 2492822Swnj invalid = TRUE; 2502822Swnj } else { 25112687Ssam printf("No directory! %s\n", 25212687Ssam "Logging in with home=/"); 2532822Swnj pwd->pw_dir = "/"; 2542822Swnj } 2551043Sbill } 25612687Ssam /* 25712687Ssam * Remote login invalid must have been because 25812687Ssam * of a restriction of some sort, no extra chances. 25912687Ssam */ 26024712Sbloom if (!usererr && invalid) 2616005Swnj exit(1); 2622822Swnj } while (invalid); 26312687Ssam /* committed to login turn off timeout */ 26412687Ssam alarm(0); 2651043Sbill 26621083Smckusick if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 26712678Ssam if (errno == EUSERS) 26812678Ssam printf("%s.\n%s.\n", 26912678Ssam "Too many users logged on already", 27012678Ssam "Try again later"); 27112678Ssam else if (errno == EPROCLIM) 27212678Ssam printf("You have too many processes running.\n"); 27312678Ssam else 27417664Sserge perror("quota (Q_SETUID)"); 27512678Ssam sleep(5); 27612678Ssam exit(0); 27712678Ssam } 2781043Sbill time(&utmp.ut_time); 2791043Sbill t = ttyslot(); 28016453Sroot if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { 2811043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 28216453Sroot SCPYN(utmp.ut_line, tty); 2831043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2841043Sbill close(f); 2851043Sbill } 28616453Sroot if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { 2871043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2881043Sbill close(f); 2891043Sbill } 29016453Sroot quietlog = access(qlog, F_OK) == 0; 29116453Sroot if ((f = open(lastlog, O_RDWR)) >= 0) { 2922822Swnj struct lastlog ll; 2932822Swnj 2942822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 2952822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 29612687Ssam ll.ll_time != 0 && !quietlog) { 29712687Ssam printf("Last login: %.*s ", 29812687Ssam 24-5, (char *)ctime(&ll.ll_time)); 29912687Ssam if (*ll.ll_host != '\0') 30012687Ssam printf("from %.*s\n", 30112687Ssam sizeof (ll.ll_host), ll.ll_host); 30212687Ssam else 30312687Ssam printf("on %.*s\n", 30412687Ssam sizeof (ll.ll_line), ll.ll_line); 3052822Swnj } 3062822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3072822Swnj time(&ll.ll_time); 30816453Sroot SCPYN(ll.ll_line, tty); 30912687Ssam SCPYN(ll.ll_host, utmp.ut_host); 3102822Swnj write(f, (char *) &ll, sizeof ll); 3112822Swnj close(f); 3122822Swnj } 3131043Sbill chown(ttyn, pwd->pw_uid, pwd->pw_gid); 31424849Smckusick if (!hflag && !rflag) /* XXX */ 31518549Ssam ioctl(0, TIOCSWINSZ, &win); 3169867Ssam chmod(ttyn, 0622); 3171043Sbill setgid(pwd->pw_gid); 3186878Smckusick strncpy(name, utmp.ut_name, NMAX); 3196878Smckusick name[NMAX] = '\0'; 3209224Ssam initgroups(name, pwd->pw_gid); 32112678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 3221043Sbill setuid(pwd->pw_uid); 32318549Ssam /* destroy environment unless user has asked to preserve it */ 32418549Ssam if (!pflag) 32518549Ssam environ = envinit; 32618549Ssam 32718549Ssam /* set up environment, this time without destruction */ 32818549Ssam /* copy the environment before setenving */ 32918549Ssam i = 0; 33018549Ssam while (environ[i] != NULL) 33118549Ssam i++; 33218549Ssam envnew = (char **) malloc(sizeof (char *) * (i + 1)); 33318549Ssam for (; i >= 0; i--) 33418549Ssam envnew[i] = environ[i]; 33518549Ssam environ = envnew; 33618549Ssam 33718549Ssam setenv("HOME=", pwd->pw_dir); 33818549Ssam setenv("SHELL=", pwd->pw_shell); 33918549Ssam if (term[0] == '\0') 34018549Ssam strncpy(term, stypeof(tty), sizeof(term)); 34118549Ssam setenv("TERM=", term); 34218549Ssam setenv("USER=", pwd->pw_name); 34318549Ssam setenv("PATH=", ":/usr/ucb:/bin:/usr/bin"); 34418549Ssam 3451043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 3461043Sbill namep = pwd->pw_shell; 3471043Sbill else 3481043Sbill namep++; 3491043Sbill strcat(minusnam, namep); 35016453Sroot if (tty[sizeof("tty")-1] == 'd') 35118549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 35218549Ssam if (pwd->pw_uid == 0) 353*24852Seric syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); 3546329Swnj if (!quietlog) { 35517664Sserge struct stat st; 35618549Ssam 3572822Swnj showmotd(); 3582822Swnj strcat(maildir, pwd->pw_name); 35917664Sserge if (stat(maildir, &st) == 0 && st.st_size != 0) 36017664Sserge printf("You have %smail.\n", 36118549Ssam (st.st_mtime > st.st_atime) ? "new " : ""); 3622822Swnj } 36312687Ssam signal(SIGALRM, SIG_DFL); 3641043Sbill signal(SIGQUIT, SIG_DFL); 3651043Sbill signal(SIGINT, SIG_DFL); 3663935Sroot signal(SIGTSTP, SIG_IGN); 3671043Sbill execlp(pwd->pw_shell, minusnam, 0); 3682822Swnj perror(pwd->pw_shell); 3691043Sbill printf("No shell\n"); 3701043Sbill exit(0); 3711043Sbill } 3721043Sbill 37312687Ssam getloginname(up) 37412687Ssam register struct utmp *up; 37512687Ssam { 37612687Ssam register char *namep; 37712712Ssam char c; 37812687Ssam 37912687Ssam while (up->ut_name[0] == '\0') { 38014897Sedward namep = up->ut_name; 38112712Ssam printf("login: "); 38212687Ssam while ((c = getchar()) != '\n') { 38312687Ssam if (c == ' ') 38412687Ssam c = '_'; 38512687Ssam if (c == EOF) 38612687Ssam exit(0); 38712687Ssam if (namep < up->ut_name+NMAX) 38812687Ssam *namep++ = c; 38912687Ssam } 39012687Ssam } 39114897Sedward strncpy(lusername, up->ut_name, NMAX); 39214897Sedward lusername[NMAX] = 0; 39314897Sedward if ((pwd = getpwnam(lusername)) == NULL) 39412687Ssam pwd = &nouser; 39512687Ssam } 39612687Ssam 39712687Ssam timedout() 39812687Ssam { 39912687Ssam 40012687Ssam printf("Login timed out after %d seconds\n", timeout); 40112687Ssam exit(0); 40212687Ssam } 40312687Ssam 4041043Sbill int stopmotd; 4051043Sbill catch() 4061043Sbill { 4076466Swnj 4081043Sbill signal(SIGINT, SIG_IGN); 4091043Sbill stopmotd++; 4101043Sbill } 4111043Sbill 4122822Swnj rootterm(tty) 4136466Swnj char *tty; 4142822Swnj { 41516453Sroot register struct ttyent *t; 4162822Swnj 41716453Sroot if ((t = getttynam(tty)) != NULL) { 41816453Sroot if (t->ty_status & TTY_SECURE) 41916453Sroot return (1); 4202822Swnj } 42116453Sroot return (0); 4222822Swnj } 4232822Swnj 4241043Sbill showmotd() 4251043Sbill { 4261043Sbill FILE *mf; 4271043Sbill register c; 4281043Sbill 4291043Sbill signal(SIGINT, catch); 43016453Sroot if ((mf = fopen("/etc/motd", "r")) != NULL) { 4312822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 4321043Sbill putchar(c); 4331043Sbill fclose(mf); 4341043Sbill } 4351043Sbill signal(SIGINT, SIG_IGN); 4361043Sbill } 4371043Sbill 4382822Swnj #undef UNKNOWN 4391043Sbill #define UNKNOWN "su" 4401043Sbill 4411043Sbill char * 4421043Sbill stypeof(ttyid) 44312687Ssam char *ttyid; 4441043Sbill { 44516453Sroot register struct ttyent *t; 4461043Sbill 44716453Sroot if (ttyid == NULL || (t = getttynam(ttyid)) == NULL) 4481043Sbill return (UNKNOWN); 44916453Sroot return (t->ty_type); 4501043Sbill } 4516005Swnj 45212687Ssam doremotelogin(host) 45312687Ssam char *host; 45412687Ssam { 45512687Ssam getstr(rusername, sizeof (rusername), "remuser"); 45612687Ssam getstr(lusername, sizeof (lusername), "locuser"); 45718549Ssam getstr(term, sizeof(term), "Terminal type"); 45813470Ssam if (getuid()) { 45913470Ssam pwd = &nouser; 46024712Sbloom return(-1); 46113470Ssam } 46212687Ssam pwd = getpwnam(lusername); 46313470Ssam if (pwd == NULL) { 46413470Ssam pwd = &nouser; 46524712Sbloom return(-1); 46613470Ssam } 46724712Sbloom return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername)); 46812687Ssam } 46912687Ssam 4706005Swnj getstr(buf, cnt, err) 4716005Swnj char *buf; 4726005Swnj int cnt; 4736005Swnj char *err; 4746005Swnj { 4756005Swnj char c; 4766005Swnj 4776005Swnj do { 4786005Swnj if (read(0, &c, 1) != 1) 4796005Swnj exit(1); 4806005Swnj if (--cnt < 0) { 4816005Swnj printf("%s too long\r\n", err); 4826005Swnj exit(1); 4836005Swnj } 4846005Swnj *buf++ = c; 4856005Swnj } while (c != 0); 4866005Swnj } 4876329Swnj 48812687Ssam char *speeds[] = 48912687Ssam { "0", "50", "75", "110", "134", "150", "200", "300", 49012687Ssam "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 49112687Ssam #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 49212687Ssam 49312687Ssam doremoteterm(term, tp) 49412687Ssam char *term; 49512687Ssam struct sgttyb *tp; 49612687Ssam { 49718549Ssam register char *cp = index(term, '/'), **cpp; 49818549Ssam char *speed; 49912687Ssam 50012687Ssam if (cp) { 50118549Ssam *cp++ = '\0'; 50218549Ssam speed = cp; 50318549Ssam cp = index(speed, '/'); 50418549Ssam if (cp) 50518549Ssam *cp++ = '\0'; 50618549Ssam for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) 50718549Ssam if (strcmp(*cpp, speed) == 0) { 50818549Ssam tp->sg_ispeed = tp->sg_ospeed = cpp-speeds; 50912687Ssam break; 51012687Ssam } 51124849Smckusick compatsiz(cp); 51212687Ssam } 51312687Ssam tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; 51412687Ssam } 51518549Ssam 51624849Smckusick /* BEGIN TRASH 51724849Smckusick * 51824849Smckusick * This is here only long enough to get us by to the revised rlogin 51924849Smckusick */ 52024849Smckusick compatsiz(cp) 52124849Smckusick char *cp; 52224849Smckusick { 52324849Smckusick struct winsize ws; 52424849Smckusick 52524849Smckusick ws.ws_row = ws.ws_col = -1; 52624849Smckusick ws.ws_xpixel = ws.ws_ypixel = -1; 52724849Smckusick if (cp) { 52824849Smckusick ws.ws_row = atoi(cp); 52924849Smckusick cp = index(cp, ','); 53024849Smckusick if (cp == 0) 53124849Smckusick goto done; 53224849Smckusick ws.ws_col = atoi(++cp); 53324849Smckusick cp = index(cp, ','); 53424849Smckusick if (cp == 0) 53524849Smckusick goto done; 53624849Smckusick ws.ws_xpixel = atoi(++cp); 53724849Smckusick cp = index(cp, ','); 53824849Smckusick if (cp == 0) 53924849Smckusick goto done; 54024849Smckusick ws.ws_ypixel = atoi(++cp); 54124849Smckusick } 54224849Smckusick done: 54324849Smckusick if (ws.ws_row != -1 && ws.ws_col != -1 && 54424849Smckusick ws.ws_xpixel != -1 && ws.ws_ypixel != -1) 54524849Smckusick ioctl(0, TIOCSWINSZ, &ws); 54624849Smckusick } 54724849Smckusick /* END TRASH */ 54824849Smckusick 54918549Ssam /* 55018549Ssam * Set the value of var to be arg in the Unix 4.2 BSD environment env. 55118549Ssam * Var should end with '='. 55218549Ssam * (bindings are of the form "var=value") 55318549Ssam * This procedure assumes the memory for the first level of environ 55418549Ssam * was allocated using malloc. 55518549Ssam */ 55618549Ssam setenv(var, value) 55718549Ssam char *var, *value; 55818549Ssam { 55918549Ssam extern char **environ; 56018549Ssam int index = 0; 56118549Ssam int varlen = strlen(var); 56218549Ssam int vallen = strlen(value); 56318549Ssam 56418549Ssam for (index = 0; environ[index] != NULL; index++) { 56518549Ssam if (strncmp(environ[index], var, varlen) == 0) { 56618549Ssam /* found it */ 56718549Ssam environ[index] = malloc(varlen + vallen + 1); 56818549Ssam strcpy(environ[index], var); 56918549Ssam strcat(environ[index], value); 57018549Ssam return; 57118549Ssam } 57218549Ssam } 57318549Ssam environ = (char **) realloc(environ, sizeof (char *) * (index + 2)); 57418549Ssam if (environ == NULL) { 57518549Ssam fprintf(stderr, "login: malloc out of memory\n"); 57618549Ssam exit(1); 57718549Ssam } 57818549Ssam environ[index] = malloc(varlen + vallen + 1); 57918549Ssam strcpy(environ[index], var); 58018549Ssam strcat(environ[index], value); 58118549Ssam environ[++index] = NULL; 58218549Ssam } 583