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*26876Smckusick static char sccsid[] = "@(#)login.c 5.14 (Berkeley) 03/13/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 41*26876Smckusick #define WRITENAME "write" /* name of group to own ttys */ 42*26876Smckusick #define WRITEGID(gid) write_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]; 946197Sroot char *rhost; 956005Swnj 961043Sbill main(argc, argv) 9712687Ssam char *argv[]; 981043Sbill { 991043Sbill register char *namep; 10018549Ssam int pflag = 0, hflag = 0, t, f, c; 10112687Ssam int invalid, quietlog; 1022822Swnj FILE *nlfd; 10316453Sroot char *ttyn, *tty; 10418549Ssam int ldisc = 0, zero = 0, i; 10518549Ssam char **envnew; 1061043Sbill 10712687Ssam signal(SIGALRM, timedout); 10812687Ssam alarm(timeout); 1091043Sbill signal(SIGQUIT, SIG_IGN); 1101043Sbill signal(SIGINT, SIG_IGN); 11112687Ssam setpriority(PRIO_PROCESS, 0, 0); 11212678Ssam quota(Q_SETUID, 0, 0, 0); 11312687Ssam /* 11418549Ssam * -p is used by getty to tell login not to destroy the environment 11512687Ssam * -r is used by rlogind to cause the autologin protocol; 11612687Ssam * -h is used by other servers to pass the name of the 11712687Ssam * remote host to login so that it may be placed in utmp and wtmp 11812687Ssam */ 11924712Sbloom while (argc > 1) { 12012687Ssam if (strcmp(argv[1], "-r") == 0) { 12124712Sbloom if (rflag || hflag) { 12224712Sbloom printf("Only one of -r and -h allowed\n"); 12324712Sbloom exit(1); 12424712Sbloom } 12524712Sbloom rflag = 1; 12624712Sbloom usererr = doremotelogin(argv[2]); 12712687Ssam SCPYN(utmp.ut_host, argv[2]); 12824712Sbloom argc -= 2; 12924712Sbloom argv += 2; 13024712Sbloom continue; 1316197Sroot } 13212687Ssam if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { 13324712Sbloom if (rflag || hflag) { 13424712Sbloom printf("Only one of -r and -h allowed\n"); 13524712Sbloom exit(1); 13624712Sbloom } 13718549Ssam hflag = 1; 13812687Ssam SCPYN(utmp.ut_host, argv[2]); 13924712Sbloom argc -= 2; 14024712Sbloom argv += 2; 14124712Sbloom continue; 1426197Sroot } 14318549Ssam if (strcmp(argv[1], "-p") == 0) { 14418549Ssam argc--; 14518549Ssam argv++; 14618549Ssam pflag = 1; 14724712Sbloom continue; 14818549Ssam } 14924712Sbloom break; 1506005Swnj } 15113074Ssam ioctl(0, TIOCLSET, &zero); 1521547Sbill ioctl(0, TIOCNXCL, 0); 1536329Swnj ioctl(0, FIONBIO, &zero); 1546329Swnj ioctl(0, FIOASYNC, &zero); 15513074Ssam ioctl(0, TIOCGETP, &ttyb); 15612687Ssam /* 15712687Ssam * If talking to an rlogin process, 15812687Ssam * propagate the terminal type and 15912687Ssam * baud rate across the network. 16012687Ssam */ 16112687Ssam if (rflag) 16212687Ssam doremoteterm(term, &ttyb); 16326482Skarels ttyb.sg_erase = CERASE; 16426482Skarels ttyb.sg_kill = CKILL; 16513074Ssam ioctl(0, TIOCSLTC, <c); 16613074Ssam ioctl(0, TIOCSETC, &tc); 16713074Ssam ioctl(0, TIOCSETP, &ttyb); 16824849Smckusick for (t = getdtablesize(); t > 2; t--) 1691043Sbill close(t); 1701043Sbill ttyn = ttyname(0); 17125426Sbloom if (ttyn == (char *)0 || *ttyn == '\0') 1721043Sbill ttyn = "/dev/tty??"; 17316453Sroot tty = rindex(ttyn, '/'); 17416453Sroot if (tty == NULL) 17516453Sroot tty = ttyn; 17616453Sroot else 17716453Sroot tty++; 17824852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 17916453Sroot t = 0; 18025163Sbloom invalid = FALSE; 1812822Swnj do { 1822822Swnj ldisc = 0; 1832822Swnj ioctl(0, TIOCSETD, &ldisc); 1842822Swnj SCPYN(utmp.ut_name, ""); 18512687Ssam /* 18612687Ssam * Name specified, take it. 18712687Ssam */ 18812687Ssam if (argc > 1) { 1892822Swnj SCPYN(utmp.ut_name, argv[1]); 1902822Swnj argc = 0; 1911043Sbill } 19212687Ssam /* 19312687Ssam * If remote login take given name, 19412687Ssam * otherwise prompt user for something. 19512687Ssam */ 19625163Sbloom if (rflag && !invalid) 1979867Ssam SCPYN(utmp.ut_name, lusername); 19824883Smckusick else 19912687Ssam getloginname(&utmp); 20025163Sbloom invalid = FALSE; 2012822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 2022822Swnj ldisc = NTTYDISC; 2032822Swnj ioctl(0, TIOCSETD, &ldisc); 2042822Swnj } 20512687Ssam /* 20612687Ssam * If no remote login authentication and 20712687Ssam * a password exists for this user, prompt 20812687Ssam * for one and verify it. 20912687Ssam */ 21024712Sbloom if (usererr == -1 && *pwd->pw_passwd != '\0') { 21112687Ssam char *pp; 21212687Ssam 21312687Ssam setpriority(PRIO_PROCESS, 0, -4); 21412687Ssam pp = getpass("Password:"); 21512687Ssam namep = crypt(pp, pwd->pw_passwd); 21612687Ssam setpriority(PRIO_PROCESS, 0, 0); 21712687Ssam if (strcmp(namep, pwd->pw_passwd)) 21812687Ssam invalid = TRUE; 2192822Swnj } 22012687Ssam /* 22112687Ssam * If user not super-user, check for logins disabled. 22212687Ssam */ 2232822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 2242822Swnj while ((c = getc(nlfd)) != EOF) 2252822Swnj putchar(c); 2262822Swnj fflush(stdout); 2272822Swnj sleep(5); 2282822Swnj exit(0); 2292822Swnj } 23012687Ssam /* 23112687Ssam * If valid so far and root is logging in, 23212687Ssam * see if root logins on this terminal are permitted. 23312687Ssam */ 23416453Sroot if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { 23525230Smckusick if (utmp.ut_host[0]) 23625230Smckusick syslog(LOG_CRIT, 23725230Smckusick "ROOT LOGIN REFUSED ON %s FROM %.*s", 23825230Smckusick tty, HMAX, utmp.ut_host); 23925230Smckusick else 24025230Smckusick syslog(LOG_CRIT, 24125230Smckusick "ROOT LOGIN REFUSED ON %s", tty); 2422822Swnj invalid = TRUE; 2432822Swnj } 2442822Swnj if (invalid) { 2451043Sbill printf("Login incorrect\n"); 24616453Sroot if (++t >= 5) { 24725230Smckusick if (utmp.ut_host[0]) 24825230Smckusick syslog(LOG_CRIT, 24925230Smckusick "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s", 25025230Smckusick tty, HMAX, utmp.ut_host, 25125230Smckusick NMAX, utmp.ut_name); 25225230Smckusick else 25325230Smckusick syslog(LOG_CRIT, 25425230Smckusick "REPEATED LOGIN FAILURES ON %s, %.*s", 25525230Smckusick tty, NMAX, utmp.ut_name); 25616453Sroot ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 25718549Ssam close(0), close(1), close(2); 25816453Sroot sleep(10); 25916453Sroot exit(1); 26016453Sroot } 2611043Sbill } 2622822Swnj if (*pwd->pw_shell == '\0') 2632822Swnj pwd->pw_shell = "/bin/sh"; 2642822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 2652822Swnj if (chdir("/") < 0) { 2662822Swnj printf("No directory!\n"); 2672822Swnj invalid = TRUE; 2682822Swnj } else { 26912687Ssam printf("No directory! %s\n", 27012687Ssam "Logging in with home=/"); 2712822Swnj pwd->pw_dir = "/"; 2722822Swnj } 2731043Sbill } 27412687Ssam /* 27512687Ssam * Remote login invalid must have been because 27612687Ssam * of a restriction of some sort, no extra chances. 27712687Ssam */ 27824712Sbloom if (!usererr && invalid) 2796005Swnj exit(1); 2802822Swnj } while (invalid); 28112687Ssam /* committed to login turn off timeout */ 28212687Ssam alarm(0); 2831043Sbill 28421083Smckusick if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 28512678Ssam if (errno == EUSERS) 28612678Ssam printf("%s.\n%s.\n", 28712678Ssam "Too many users logged on already", 28812678Ssam "Try again later"); 28912678Ssam else if (errno == EPROCLIM) 29012678Ssam printf("You have too many processes running.\n"); 29112678Ssam else 29217664Sserge perror("quota (Q_SETUID)"); 29312678Ssam sleep(5); 29412678Ssam exit(0); 29512678Ssam } 2961043Sbill time(&utmp.ut_time); 2971043Sbill t = ttyslot(); 29816453Sroot if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { 2991043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 30016453Sroot SCPYN(utmp.ut_line, tty); 3011043Sbill write(f, (char *)&utmp, sizeof(utmp)); 3021043Sbill close(f); 3031043Sbill } 30416453Sroot if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { 3051043Sbill write(f, (char *)&utmp, sizeof(utmp)); 3061043Sbill close(f); 3071043Sbill } 30816453Sroot quietlog = access(qlog, F_OK) == 0; 30916453Sroot if ((f = open(lastlog, O_RDWR)) >= 0) { 3102822Swnj struct lastlog ll; 3112822Swnj 3122822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3132822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 31412687Ssam ll.ll_time != 0 && !quietlog) { 31512687Ssam printf("Last login: %.*s ", 31612687Ssam 24-5, (char *)ctime(&ll.ll_time)); 31712687Ssam if (*ll.ll_host != '\0') 31812687Ssam printf("from %.*s\n", 31912687Ssam sizeof (ll.ll_host), ll.ll_host); 32012687Ssam else 32112687Ssam printf("on %.*s\n", 32212687Ssam sizeof (ll.ll_line), ll.ll_line); 3232822Swnj } 3242822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3252822Swnj time(&ll.ll_time); 32616453Sroot SCPYN(ll.ll_line, tty); 32712687Ssam SCPYN(ll.ll_host, utmp.ut_host); 3282822Swnj write(f, (char *) &ll, sizeof ll); 3292822Swnj close(f); 3302822Swnj } 331*26876Smckusick chown(ttyn, pwd->pw_uid, WRITEGID(pwd->pw_gid)); 33224849Smckusick if (!hflag && !rflag) /* XXX */ 33318549Ssam ioctl(0, TIOCSWINSZ, &win); 33426862Smckusick chmod(ttyn, 0620); 3351043Sbill setgid(pwd->pw_gid); 3366878Smckusick strncpy(name, utmp.ut_name, NMAX); 3376878Smckusick name[NMAX] = '\0'; 3389224Ssam initgroups(name, pwd->pw_gid); 33912678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 3401043Sbill setuid(pwd->pw_uid); 34118549Ssam /* destroy environment unless user has asked to preserve it */ 34218549Ssam if (!pflag) 34318549Ssam environ = envinit; 34418549Ssam 34518549Ssam /* set up environment, this time without destruction */ 34618549Ssam /* copy the environment before setenving */ 34718549Ssam i = 0; 34818549Ssam while (environ[i] != NULL) 34918549Ssam i++; 35018549Ssam envnew = (char **) malloc(sizeof (char *) * (i + 1)); 35118549Ssam for (; i >= 0; i--) 35218549Ssam envnew[i] = environ[i]; 35318549Ssam environ = envnew; 35418549Ssam 35524966Skarels setenv("HOME=", pwd->pw_dir, 1); 35624966Skarels setenv("SHELL=", pwd->pw_shell, 1); 35718549Ssam if (term[0] == '\0') 35818549Ssam strncpy(term, stypeof(tty), sizeof(term)); 35924966Skarels setenv("TERM=", term, 0); 36024966Skarels setenv("USER=", pwd->pw_name, 1); 36124966Skarels setenv("PATH=", ":/usr/ucb:/bin:/usr/bin", 0); 36218549Ssam 3631043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 3641043Sbill namep = pwd->pw_shell; 3651043Sbill else 3661043Sbill namep++; 3671043Sbill strcat(minusnam, namep); 36816453Sroot if (tty[sizeof("tty")-1] == 'd') 36918549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 37018549Ssam if (pwd->pw_uid == 0) 37125230Smckusick if (utmp.ut_host[0]) 37225230Smckusick syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", 37325230Smckusick tty, HMAX, utmp.ut_host); 37425230Smckusick else 37525230Smckusick syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); 3766329Swnj if (!quietlog) { 37717664Sserge struct stat st; 37818549Ssam 3792822Swnj showmotd(); 3802822Swnj strcat(maildir, pwd->pw_name); 38117664Sserge if (stat(maildir, &st) == 0 && st.st_size != 0) 38217664Sserge printf("You have %smail.\n", 38318549Ssam (st.st_mtime > st.st_atime) ? "new " : ""); 3842822Swnj } 38512687Ssam signal(SIGALRM, SIG_DFL); 3861043Sbill signal(SIGQUIT, SIG_DFL); 3871043Sbill signal(SIGINT, SIG_DFL); 3883935Sroot signal(SIGTSTP, SIG_IGN); 3891043Sbill execlp(pwd->pw_shell, minusnam, 0); 3902822Swnj perror(pwd->pw_shell); 3911043Sbill printf("No shell\n"); 3921043Sbill exit(0); 3931043Sbill } 3941043Sbill 39512687Ssam getloginname(up) 39612687Ssam register struct utmp *up; 39712687Ssam { 39812687Ssam register char *namep; 39912712Ssam char c; 40012687Ssam 40112687Ssam while (up->ut_name[0] == '\0') { 40214897Sedward namep = up->ut_name; 40312712Ssam printf("login: "); 40412687Ssam while ((c = getchar()) != '\n') { 40512687Ssam if (c == ' ') 40612687Ssam c = '_'; 40712687Ssam if (c == EOF) 40812687Ssam exit(0); 40912687Ssam if (namep < up->ut_name+NMAX) 41012687Ssam *namep++ = c; 41112687Ssam } 41212687Ssam } 41314897Sedward strncpy(lusername, up->ut_name, NMAX); 41414897Sedward lusername[NMAX] = 0; 41514897Sedward if ((pwd = getpwnam(lusername)) == NULL) 41612687Ssam pwd = &nouser; 41712687Ssam } 41812687Ssam 41912687Ssam timedout() 42012687Ssam { 42112687Ssam 42212687Ssam printf("Login timed out after %d seconds\n", timeout); 42312687Ssam exit(0); 42412687Ssam } 42512687Ssam 4261043Sbill int stopmotd; 4271043Sbill catch() 4281043Sbill { 4296466Swnj 4301043Sbill signal(SIGINT, SIG_IGN); 4311043Sbill stopmotd++; 4321043Sbill } 4331043Sbill 4342822Swnj rootterm(tty) 4356466Swnj char *tty; 4362822Swnj { 43716453Sroot register struct ttyent *t; 4382822Swnj 43916453Sroot if ((t = getttynam(tty)) != NULL) { 44016453Sroot if (t->ty_status & TTY_SECURE) 44116453Sroot return (1); 4422822Swnj } 44316453Sroot return (0); 4442822Swnj } 4452822Swnj 4461043Sbill showmotd() 4471043Sbill { 4481043Sbill FILE *mf; 4491043Sbill register c; 4501043Sbill 4511043Sbill signal(SIGINT, catch); 45216453Sroot if ((mf = fopen("/etc/motd", "r")) != NULL) { 4532822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 4541043Sbill putchar(c); 4551043Sbill fclose(mf); 4561043Sbill } 4571043Sbill signal(SIGINT, SIG_IGN); 4581043Sbill } 4591043Sbill 4602822Swnj #undef UNKNOWN 4611043Sbill #define UNKNOWN "su" 4621043Sbill 4631043Sbill char * 4641043Sbill stypeof(ttyid) 46512687Ssam char *ttyid; 4661043Sbill { 46716453Sroot register struct ttyent *t; 4681043Sbill 46916453Sroot if (ttyid == NULL || (t = getttynam(ttyid)) == NULL) 4701043Sbill return (UNKNOWN); 47116453Sroot return (t->ty_type); 4721043Sbill } 4736005Swnj 47412687Ssam doremotelogin(host) 47512687Ssam char *host; 47612687Ssam { 47712687Ssam getstr(rusername, sizeof (rusername), "remuser"); 47812687Ssam getstr(lusername, sizeof (lusername), "locuser"); 47918549Ssam getstr(term, sizeof(term), "Terminal type"); 48013470Ssam if (getuid()) { 48113470Ssam pwd = &nouser; 48224712Sbloom return(-1); 48313470Ssam } 48412687Ssam pwd = getpwnam(lusername); 48513470Ssam if (pwd == NULL) { 48613470Ssam pwd = &nouser; 48724712Sbloom return(-1); 48813470Ssam } 48924712Sbloom return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername)); 49012687Ssam } 49112687Ssam 4926005Swnj getstr(buf, cnt, err) 4936005Swnj char *buf; 4946005Swnj int cnt; 4956005Swnj char *err; 4966005Swnj { 4976005Swnj char c; 4986005Swnj 4996005Swnj do { 5006005Swnj if (read(0, &c, 1) != 1) 5016005Swnj exit(1); 5026005Swnj if (--cnt < 0) { 5036005Swnj printf("%s too long\r\n", err); 5046005Swnj exit(1); 5056005Swnj } 5066005Swnj *buf++ = c; 5076005Swnj } while (c != 0); 5086005Swnj } 5096329Swnj 51012687Ssam char *speeds[] = 51112687Ssam { "0", "50", "75", "110", "134", "150", "200", "300", 51212687Ssam "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 51312687Ssam #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 51412687Ssam 51512687Ssam doremoteterm(term, tp) 51612687Ssam char *term; 51712687Ssam struct sgttyb *tp; 51812687Ssam { 51918549Ssam register char *cp = index(term, '/'), **cpp; 52018549Ssam char *speed; 52112687Ssam 52212687Ssam if (cp) { 52318549Ssam *cp++ = '\0'; 52418549Ssam speed = cp; 52518549Ssam cp = index(speed, '/'); 52618549Ssam if (cp) 52718549Ssam *cp++ = '\0'; 52818549Ssam for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) 52918549Ssam if (strcmp(*cpp, speed) == 0) { 53018549Ssam tp->sg_ispeed = tp->sg_ospeed = cpp-speeds; 53112687Ssam break; 53212687Ssam } 53312687Ssam } 53412687Ssam tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; 53512687Ssam } 53618549Ssam 53718549Ssam /* 53818549Ssam * Set the value of var to be arg in the Unix 4.2 BSD environment env. 53918549Ssam * Var should end with '='. 54018549Ssam * (bindings are of the form "var=value") 54118549Ssam * This procedure assumes the memory for the first level of environ 54218549Ssam * was allocated using malloc. 54318549Ssam */ 54424966Skarels setenv(var, value, clobber) 54518549Ssam char *var, *value; 54618549Ssam { 54718549Ssam extern char **environ; 54818549Ssam int index = 0; 54918549Ssam int varlen = strlen(var); 55018549Ssam int vallen = strlen(value); 55118549Ssam 55218549Ssam for (index = 0; environ[index] != NULL; index++) { 55318549Ssam if (strncmp(environ[index], var, varlen) == 0) { 55418549Ssam /* found it */ 55524966Skarels if (!clobber) 55624966Skarels return; 55718549Ssam environ[index] = malloc(varlen + vallen + 1); 55818549Ssam strcpy(environ[index], var); 55918549Ssam strcat(environ[index], value); 56018549Ssam return; 56118549Ssam } 56218549Ssam } 56318549Ssam environ = (char **) realloc(environ, sizeof (char *) * (index + 2)); 56418549Ssam if (environ == NULL) { 56518549Ssam fprintf(stderr, "login: malloc out of memory\n"); 56618549Ssam exit(1); 56718549Ssam } 56818549Ssam environ[index] = malloc(varlen + vallen + 1); 56918549Ssam strcpy(environ[index], var); 57018549Ssam strcat(environ[index], value); 57118549Ssam environ[++index] = NULL; 57218549Ssam } 57326862Smckusick 574*26876Smckusick write_gid(default_gid) 575*26876Smckusick int default_gid; 57626862Smckusick { 57726862Smckusick struct group *getgrnam(), *gr; 578*26876Smckusick int gid = default_gid; 57926862Smckusick 58026862Smckusick gr = getgrnam(WRITENAME); 58126862Smckusick if (gr != (struct group *) 0) 58226862Smckusick gid = gr->gr_gid; 58326862Smckusick 58426862Smckusick endgrent(); 58526862Smckusick 586*26876Smckusick return (gid); 58726862Smckusick } 588