112678Ssam #ifndef lint 2*18549Ssam static char *sccsid = "@(#)login.c 4.36 (Berkeley) 85/04/01"; 312678Ssam #endif 412678Ssam 51043Sbill /* 61043Sbill * login [ name ] 712687Ssam * login -r hostname (for rlogind) 812687Ssam * login -h hostname (for telnetd, etc.) 91043Sbill */ 101043Sbill 1112984Ssam #include <sys/param.h> 1212687Ssam #include <sys/quota.h> 1312687Ssam #include <sys/stat.h> 1412687Ssam #include <sys/time.h> 1512687Ssam #include <sys/resource.h> 1616453Sroot #include <sys/file.h> 1712687Ssam 181043Sbill #include <sgtty.h> 191043Sbill #include <utmp.h> 201043Sbill #include <signal.h> 211043Sbill #include <pwd.h> 221043Sbill #include <stdio.h> 231043Sbill #include <lastlog.h> 2412678Ssam #include <errno.h> 2516453Sroot #include <ttyent.h> 2616453Sroot #include <syslog.h> 271043Sbill 2816453Sroot #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 292822Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 302822Swnj 316197Sroot #define NMAX sizeof(utmp.ut_name) 321043Sbill 332822Swnj #define FALSE 0 342822Swnj #define TRUE -1 352822Swnj 362822Swnj char nolog[] = "/etc/nologin"; 372822Swnj char qlog[] = ".hushlogin"; 381043Sbill char maildir[30] = "/usr/spool/mail/"; 391043Sbill char lastlog[] = "/usr/adm/lastlog"; 409867Ssam struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; 411043Sbill struct sgttyb ttyb; 421043Sbill struct utmp utmp; 431043Sbill char minusnam[16] = "-"; 44*18549Ssam char *envinit[] = { 0 }; /* now set by setenv calls */ 4512687Ssam /* 4612687Ssam * This bounds the time given to login. We initialize it here 4712687Ssam * so it can be patched on machines where it's too small. 4812687Ssam */ 4912687Ssam int timeout = 60; 506005Swnj 51*18549Ssam char term[64]; 526005Swnj 531043Sbill struct passwd *pwd; 54*18549Ssam char *strcat(), *rindex(), *index(), *malloc(), *realloc(); 5512687Ssam int timedout(); 561043Sbill char *ttyname(); 571043Sbill char *crypt(); 581043Sbill char *getpass(); 591043Sbill char *stypeof(); 601043Sbill extern char **environ; 6112678Ssam extern int errno; 621043Sbill 6313074Ssam struct tchars tc = { 6413074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 651365Sbill }; 6613074Ssam struct ltchars ltc = { 6713074Ssam CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 6813074Ssam }; 691365Sbill 70*18549Ssam struct winsize win = { 0, 0, 0, 0 }; 71*18549Ssam 726005Swnj int rflag; 736197Sroot char rusername[NMAX+1], lusername[NMAX+1]; 746005Swnj char rpassword[NMAX+1]; 756878Smckusick char name[NMAX+1]; 766197Sroot char *rhost; 776005Swnj 781043Sbill main(argc, argv) 7912687Ssam char *argv[]; 801043Sbill { 811043Sbill register char *namep; 82*18549Ssam int pflag = 0, hflag = 0, t, f, c; 8312687Ssam int invalid, quietlog; 842822Swnj FILE *nlfd; 8516453Sroot char *ttyn, *tty; 86*18549Ssam int ldisc = 0, zero = 0, i; 87*18549Ssam char **envnew; 881043Sbill 8912687Ssam signal(SIGALRM, timedout); 9012687Ssam alarm(timeout); 911043Sbill signal(SIGQUIT, SIG_IGN); 921043Sbill signal(SIGINT, SIG_IGN); 9312687Ssam setpriority(PRIO_PROCESS, 0, 0); 9412678Ssam quota(Q_SETUID, 0, 0, 0); 9512687Ssam /* 96*18549Ssam * -p is used by getty to tell login not to destroy the environment 9712687Ssam * -r is used by rlogind to cause the autologin protocol; 9812687Ssam * -h is used by other servers to pass the name of the 9912687Ssam * remote host to login so that it may be placed in utmp and wtmp 10012687Ssam */ 10112687Ssam if (argc > 1) { 10212687Ssam if (strcmp(argv[1], "-r") == 0) { 10312687Ssam rflag = doremotelogin(argv[2]); 10412687Ssam SCPYN(utmp.ut_host, argv[2]); 10512687Ssam argc = 0; 1066197Sroot } 10712687Ssam if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { 108*18549Ssam hflag = 1; 10912687Ssam SCPYN(utmp.ut_host, argv[2]); 11012687Ssam argc = 0; 1116197Sroot } 112*18549Ssam if (strcmp(argv[1], "-p") == 0) { 113*18549Ssam argc--; 114*18549Ssam argv++; 115*18549Ssam pflag = 1; 116*18549Ssam } 1176005Swnj } 11813074Ssam ioctl(0, TIOCLSET, &zero); 1191547Sbill ioctl(0, TIOCNXCL, 0); 1206329Swnj ioctl(0, FIONBIO, &zero); 1216329Swnj ioctl(0, FIOASYNC, &zero); 12213074Ssam ioctl(0, TIOCGETP, &ttyb); 12312687Ssam /* 12412687Ssam * If talking to an rlogin process, 12512687Ssam * propagate the terminal type and 12612687Ssam * baud rate across the network. 12712687Ssam */ 12812687Ssam if (rflag) 12912687Ssam doremoteterm(term, &ttyb); 13013074Ssam ioctl(0, TIOCSLTC, <c); 13113074Ssam ioctl(0, TIOCSETC, &tc); 13213074Ssam ioctl(0, TIOCSETP, &ttyb); 13312687Ssam for (t = getdtablesize(); t > 3; t--) 1341043Sbill close(t); 1351043Sbill ttyn = ttyname(0); 13616453Sroot if (ttyn == (char *)0) 1371043Sbill ttyn = "/dev/tty??"; 13816453Sroot tty = rindex(ttyn, '/'); 13916453Sroot if (tty == NULL) 14016453Sroot tty = ttyn; 14116453Sroot else 14216453Sroot tty++; 143*18549Ssam openlog("login", LOG_ODELAY, 0); 14416453Sroot t = 0; 1452822Swnj do { 1462822Swnj ldisc = 0; 1472822Swnj ioctl(0, TIOCSETD, &ldisc); 1482822Swnj invalid = FALSE; 1492822Swnj SCPYN(utmp.ut_name, ""); 15012687Ssam /* 15112687Ssam * Name specified, take it. 15212687Ssam */ 15312687Ssam if (argc > 1) { 1542822Swnj SCPYN(utmp.ut_name, argv[1]); 1552822Swnj argc = 0; 1561043Sbill } 15712687Ssam /* 15812687Ssam * If remote login take given name, 15912687Ssam * otherwise prompt user for something. 16012687Ssam */ 1616329Swnj if (rflag) { 1629867Ssam SCPYN(utmp.ut_name, lusername); 16312687Ssam /* autologin failed, prompt for passwd */ 1646329Swnj if (rflag == -1) 1656329Swnj rflag = 0; 16613470Ssam } else 16712687Ssam getloginname(&utmp); 1682822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 1692822Swnj ldisc = NTTYDISC; 1702822Swnj ioctl(0, TIOCSETD, &ldisc); 1712822Swnj } 17212687Ssam /* 17312687Ssam * If no remote login authentication and 17412687Ssam * a password exists for this user, prompt 17512687Ssam * for one and verify it. 17612687Ssam */ 17712687Ssam if (!rflag && *pwd->pw_passwd != '\0') { 17812687Ssam char *pp; 17912687Ssam 18012687Ssam setpriority(PRIO_PROCESS, 0, -4); 18112687Ssam pp = getpass("Password:"); 18212687Ssam namep = crypt(pp, pwd->pw_passwd); 18312687Ssam setpriority(PRIO_PROCESS, 0, 0); 18412687Ssam if (strcmp(namep, pwd->pw_passwd)) 18512687Ssam invalid = TRUE; 1862822Swnj } 18712687Ssam /* 18812687Ssam * If user not super-user, check for logins disabled. 18912687Ssam */ 1902822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 1912822Swnj while ((c = getc(nlfd)) != EOF) 1922822Swnj putchar(c); 1932822Swnj fflush(stdout); 1942822Swnj sleep(5); 1952822Swnj exit(0); 1962822Swnj } 19712687Ssam /* 19812687Ssam * If valid so far and root is logging in, 19912687Ssam * see if root logins on this terminal are permitted. 20012687Ssam */ 20116453Sroot if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { 202*18549Ssam syslog(LOG_SECURITY, "ROOT LOGIN REFUSED %s", tty); 2032822Swnj invalid = TRUE; 2042822Swnj } 2052822Swnj if (invalid) { 2061043Sbill printf("Login incorrect\n"); 20716453Sroot if (++t >= 5) { 208*18549Ssam syslog(LOG_SECURITY, 20916453Sroot "REPEATED LOGIN FAILURES %s, %s", 21016453Sroot tty, utmp.ut_name); 21116453Sroot ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 212*18549Ssam close(0), close(1), close(2); 21316453Sroot sleep(10); 21416453Sroot exit(1); 21516453Sroot } 2161043Sbill } 2172822Swnj if (*pwd->pw_shell == '\0') 2182822Swnj pwd->pw_shell = "/bin/sh"; 2192822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 2202822Swnj if (chdir("/") < 0) { 2212822Swnj printf("No directory!\n"); 2222822Swnj invalid = TRUE; 2232822Swnj } else { 22412687Ssam printf("No directory! %s\n", 22512687Ssam "Logging in with home=/"); 2262822Swnj pwd->pw_dir = "/"; 2272822Swnj } 2281043Sbill } 22912687Ssam /* 23012687Ssam * Remote login invalid must have been because 23112687Ssam * of a restriction of some sort, no extra chances. 23212687Ssam */ 2336005Swnj if (rflag && invalid) 2346005Swnj exit(1); 2352822Swnj } while (invalid); 23612687Ssam /* committed to login turn off timeout */ 23712687Ssam alarm(0); 2381043Sbill 23912678Ssam if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0) { 24012678Ssam if (errno == EUSERS) 24112678Ssam printf("%s.\n%s.\n", 24212678Ssam "Too many users logged on already", 24312678Ssam "Try again later"); 24412678Ssam else if (errno == EPROCLIM) 24512678Ssam printf("You have too many processes running.\n"); 24612678Ssam else 24717664Sserge perror("quota (Q_SETUID)"); 24812678Ssam sleep(5); 24912678Ssam exit(0); 25012678Ssam } 2511043Sbill time(&utmp.ut_time); 2521043Sbill t = ttyslot(); 25316453Sroot if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { 2541043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 25516453Sroot SCPYN(utmp.ut_line, tty); 2561043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2571043Sbill close(f); 2581043Sbill } 25916453Sroot if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { 2601043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2611043Sbill close(f); 2621043Sbill } 26316453Sroot quietlog = access(qlog, F_OK) == 0; 26416453Sroot if ((f = open(lastlog, O_RDWR)) >= 0) { 2652822Swnj struct lastlog ll; 2662822Swnj 2672822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 2682822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 26912687Ssam ll.ll_time != 0 && !quietlog) { 27012687Ssam printf("Last login: %.*s ", 27112687Ssam 24-5, (char *)ctime(&ll.ll_time)); 27212687Ssam if (*ll.ll_host != '\0') 27312687Ssam printf("from %.*s\n", 27412687Ssam sizeof (ll.ll_host), ll.ll_host); 27512687Ssam else 27612687Ssam printf("on %.*s\n", 27712687Ssam sizeof (ll.ll_line), ll.ll_line); 2782822Swnj } 2792822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 2802822Swnj time(&ll.ll_time); 28116453Sroot SCPYN(ll.ll_line, tty); 28212687Ssam SCPYN(ll.ll_host, utmp.ut_host); 2832822Swnj write(f, (char *) &ll, sizeof ll); 2842822Swnj close(f); 2852822Swnj } 2861043Sbill chown(ttyn, pwd->pw_uid, pwd->pw_gid); 287*18549Ssam if (!hflag) /* XXX */ 288*18549Ssam ioctl(0, TIOCSWINSZ, &win); 2899867Ssam chmod(ttyn, 0622); 2901043Sbill setgid(pwd->pw_gid); 2916878Smckusick strncpy(name, utmp.ut_name, NMAX); 2926878Smckusick name[NMAX] = '\0'; 2939224Ssam initgroups(name, pwd->pw_gid); 29412678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 2951043Sbill setuid(pwd->pw_uid); 296*18549Ssam /* destroy environment unless user has asked to preserve it */ 297*18549Ssam if (!pflag) 298*18549Ssam environ = envinit; 299*18549Ssam 300*18549Ssam /* set up environment, this time without destruction */ 301*18549Ssam /* copy the environment before setenving */ 302*18549Ssam i = 0; 303*18549Ssam while (environ[i] != NULL) 304*18549Ssam i++; 305*18549Ssam envnew = (char **) malloc(sizeof (char *) * (i + 1)); 306*18549Ssam for (; i >= 0; i--) 307*18549Ssam envnew[i] = environ[i]; 308*18549Ssam environ = envnew; 309*18549Ssam 310*18549Ssam setenv("HOME=", pwd->pw_dir); 311*18549Ssam setenv("SHELL=", pwd->pw_shell); 312*18549Ssam if (term[0] == '\0') 313*18549Ssam strncpy(term, stypeof(tty), sizeof(term)); 314*18549Ssam setenv("TERM=", term); 315*18549Ssam setenv("USER=", pwd->pw_name); 316*18549Ssam setenv("PATH=", ":/usr/ucb:/bin:/usr/bin"); 317*18549Ssam 3181043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 3191043Sbill namep = pwd->pw_shell; 3201043Sbill else 3211043Sbill namep++; 3221043Sbill strcat(minusnam, namep); 32316453Sroot if (tty[sizeof("tty")-1] == 'd') 324*18549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 325*18549Ssam if (pwd->pw_uid == 0) 326*18549Ssam syslog(LOG_SECURITY, "ROOT LOGIN %s", tty); 3276329Swnj if (!quietlog) { 32817664Sserge struct stat st; 329*18549Ssam 3302822Swnj showmotd(); 3312822Swnj strcat(maildir, pwd->pw_name); 33217664Sserge if (stat(maildir, &st) == 0 && st.st_size != 0) 33317664Sserge printf("You have %smail.\n", 334*18549Ssam (st.st_mtime > st.st_atime) ? "new " : ""); 3352822Swnj } 33612687Ssam signal(SIGALRM, SIG_DFL); 3371043Sbill signal(SIGQUIT, SIG_DFL); 3381043Sbill signal(SIGINT, SIG_DFL); 3393935Sroot signal(SIGTSTP, SIG_IGN); 3401043Sbill execlp(pwd->pw_shell, minusnam, 0); 3412822Swnj perror(pwd->pw_shell); 3421043Sbill printf("No shell\n"); 3431043Sbill exit(0); 3441043Sbill } 3451043Sbill 34612687Ssam getloginname(up) 34712687Ssam register struct utmp *up; 34812687Ssam { 34912687Ssam register char *namep; 35012712Ssam char c; 35112687Ssam 35212687Ssam while (up->ut_name[0] == '\0') { 35314897Sedward namep = up->ut_name; 35412712Ssam printf("login: "); 35512687Ssam while ((c = getchar()) != '\n') { 35612687Ssam if (c == ' ') 35712687Ssam c = '_'; 35812687Ssam if (c == EOF) 35912687Ssam exit(0); 36012687Ssam if (namep < up->ut_name+NMAX) 36112687Ssam *namep++ = c; 36212687Ssam } 36312687Ssam } 36414897Sedward strncpy(lusername, up->ut_name, NMAX); 36514897Sedward lusername[NMAX] = 0; 36614897Sedward if ((pwd = getpwnam(lusername)) == NULL) 36712687Ssam pwd = &nouser; 36812687Ssam } 36912687Ssam 37012687Ssam timedout() 37112687Ssam { 37212687Ssam 37312687Ssam printf("Login timed out after %d seconds\n", timeout); 37412687Ssam exit(0); 37512687Ssam } 37612687Ssam 3771043Sbill int stopmotd; 3781043Sbill catch() 3791043Sbill { 3806466Swnj 3811043Sbill signal(SIGINT, SIG_IGN); 3821043Sbill stopmotd++; 3831043Sbill } 3841043Sbill 3852822Swnj rootterm(tty) 3866466Swnj char *tty; 3872822Swnj { 38816453Sroot register struct ttyent *t; 3892822Swnj 39016453Sroot if ((t = getttynam(tty)) != NULL) { 39116453Sroot if (t->ty_status & TTY_SECURE) 39216453Sroot return (1); 3932822Swnj } 39416453Sroot return (0); 3952822Swnj } 3962822Swnj 3971043Sbill showmotd() 3981043Sbill { 3991043Sbill FILE *mf; 4001043Sbill register c; 4011043Sbill 4021043Sbill signal(SIGINT, catch); 40316453Sroot if ((mf = fopen("/etc/motd", "r")) != NULL) { 4042822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 4051043Sbill putchar(c); 4061043Sbill fclose(mf); 4071043Sbill } 4081043Sbill signal(SIGINT, SIG_IGN); 4091043Sbill } 4101043Sbill 4112822Swnj #undef UNKNOWN 4121043Sbill #define UNKNOWN "su" 4131043Sbill 4141043Sbill char * 4151043Sbill stypeof(ttyid) 41612687Ssam char *ttyid; 4171043Sbill { 41816453Sroot register struct ttyent *t; 4191043Sbill 42016453Sroot if (ttyid == NULL || (t = getttynam(ttyid)) == NULL) 4211043Sbill return (UNKNOWN); 42216453Sroot return (t->ty_type); 4231043Sbill } 4246005Swnj 42512687Ssam doremotelogin(host) 42612687Ssam char *host; 42712687Ssam { 42812687Ssam FILE *hostf; 42912687Ssam int first = 1; 43012687Ssam 43112687Ssam getstr(rusername, sizeof (rusername), "remuser"); 43212687Ssam getstr(lusername, sizeof (lusername), "locuser"); 433*18549Ssam getstr(term, sizeof(term), "Terminal type"); 43413470Ssam if (getuid()) { 43513470Ssam pwd = &nouser; 43612687Ssam goto bad; 43713470Ssam } 43812687Ssam pwd = getpwnam(lusername); 43913470Ssam if (pwd == NULL) { 44013470Ssam pwd = &nouser; 44112687Ssam goto bad; 44213470Ssam } 44312687Ssam hostf = pwd->pw_uid ? fopen("/etc/hosts.equiv", "r") : 0; 44412687Ssam again: 44512687Ssam if (hostf) { 44612687Ssam char ahost[32]; 44712687Ssam 44812687Ssam while (fgets(ahost, sizeof (ahost), hostf)) { 449*18549Ssam register char *p; 45012687Ssam char *user; 45112687Ssam 452*18549Ssam p = ahost; 453*18549Ssam while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 454*18549Ssam p++; 455*18549Ssam if (*p == ' ' || *p == '\t') { 456*18549Ssam *p++ = '\0'; 457*18549Ssam while (*p == ' ' || *p == '\t') 458*18549Ssam p++; 459*18549Ssam user = p; 460*18549Ssam while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 461*18549Ssam p++; 462*18549Ssam } else 463*18549Ssam user = p; 464*18549Ssam *p = '\0'; 46512687Ssam if (!strcmp(host, ahost) && 466*18549Ssam !strcmp(rusername, *user ? user : lusername)) { 46712687Ssam fclose(hostf); 46812687Ssam return (1); 46912687Ssam } 47012687Ssam } 47112687Ssam fclose(hostf); 47212687Ssam } 47312687Ssam if (first == 1) { 47412687Ssam char *rhosts = ".rhosts"; 47512687Ssam struct stat sbuf; 47612687Ssam 47712687Ssam first = 0; 47812687Ssam if (chdir(pwd->pw_dir) < 0) 47912687Ssam goto again; 48012687Ssam if (lstat(rhosts, &sbuf) < 0) 48112687Ssam goto again; 48212687Ssam if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { 48312687Ssam printf("login: .rhosts is a soft link.\r\n"); 48412687Ssam goto bad; 48512687Ssam } 48612687Ssam hostf = fopen(rhosts, "r"); 48712687Ssam fstat(fileno(hostf), &sbuf); 48812687Ssam if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 48912687Ssam printf("login: Bad .rhosts ownership.\r\n"); 49012687Ssam fclose(hostf); 49112687Ssam goto bad; 49212687Ssam } 49312687Ssam goto again; 49412687Ssam } 49512687Ssam bad: 49612687Ssam return (-1); 49712687Ssam } 49812687Ssam 4996005Swnj getstr(buf, cnt, err) 5006005Swnj char *buf; 5016005Swnj int cnt; 5026005Swnj char *err; 5036005Swnj { 5046005Swnj char c; 5056005Swnj 5066005Swnj do { 5076005Swnj if (read(0, &c, 1) != 1) 5086005Swnj exit(1); 5096005Swnj if (--cnt < 0) { 5106005Swnj printf("%s too long\r\n", err); 5116005Swnj exit(1); 5126005Swnj } 5136005Swnj *buf++ = c; 5146005Swnj } while (c != 0); 5156005Swnj } 5166329Swnj 51712687Ssam char *speeds[] = 51812687Ssam { "0", "50", "75", "110", "134", "150", "200", "300", 51912687Ssam "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 52012687Ssam #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 52112687Ssam 52212687Ssam doremoteterm(term, tp) 52312687Ssam char *term; 52412687Ssam struct sgttyb *tp; 52512687Ssam { 526*18549Ssam register char *cp = index(term, '/'), **cpp; 527*18549Ssam char *speed; 528*18549Ssam struct winsize ws; 52912687Ssam 53012687Ssam if (cp) { 531*18549Ssam *cp++ = '\0'; 532*18549Ssam speed = cp; 533*18549Ssam cp = index(speed, '/'); 534*18549Ssam if (cp) 535*18549Ssam *cp++ = '\0'; 536*18549Ssam for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) 537*18549Ssam if (strcmp(*cpp, speed) == 0) { 538*18549Ssam tp->sg_ispeed = tp->sg_ospeed = cpp-speeds; 53912687Ssam break; 54012687Ssam } 541*18549Ssam ws.ws_row = ws.ws_col = -1; 542*18549Ssam ws.ws_xpixel = ws.ws_ypixel = -1; 543*18549Ssam if (cp) { 544*18549Ssam ws.ws_row = atoi(++cp); 545*18549Ssam cp = index(cp, ','); 546*18549Ssam if (cp == 0) 547*18549Ssam goto done; 548*18549Ssam ws.ws_col = atoi(++cp); 549*18549Ssam cp = index(cp, ','); 550*18549Ssam if (cp == 0) 551*18549Ssam goto done; 552*18549Ssam ws.ws_xpixel = atoi(++cp); 553*18549Ssam cp = index(cp, ','); 554*18549Ssam if (cp == 0) 555*18549Ssam goto done; 556*18549Ssam ws.ws_ypixel = atoi(++cp); 557*18549Ssam } 558*18549Ssam done: 559*18549Ssam if (ws.ws_row != -1 && ws.ws_col != -1 && 560*18549Ssam ws.ws_xpixel != -1 && ws.ws_ypixel != -1) 561*18549Ssam win = ws; 56212687Ssam } 56312687Ssam tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; 56412687Ssam } 565*18549Ssam 566*18549Ssam /* 567*18549Ssam * Set the value of var to be arg in the Unix 4.2 BSD environment env. 568*18549Ssam * Var should end with '='. 569*18549Ssam * (bindings are of the form "var=value") 570*18549Ssam * This procedure assumes the memory for the first level of environ 571*18549Ssam * was allocated using malloc. 572*18549Ssam */ 573*18549Ssam setenv(var, value) 574*18549Ssam char *var, *value; 575*18549Ssam { 576*18549Ssam extern char **environ; 577*18549Ssam int index = 0; 578*18549Ssam int varlen = strlen(var); 579*18549Ssam int vallen = strlen(value); 580*18549Ssam 581*18549Ssam for (index = 0; environ[index] != NULL; index++) { 582*18549Ssam if (strncmp(environ[index], var, varlen) == 0) { 583*18549Ssam /* found it */ 584*18549Ssam environ[index] = malloc(varlen + vallen + 1); 585*18549Ssam strcpy(environ[index], var); 586*18549Ssam strcat(environ[index], value); 587*18549Ssam return; 588*18549Ssam } 589*18549Ssam } 590*18549Ssam environ = (char **) realloc(environ, sizeof (char *) * (index + 2)); 591*18549Ssam if (environ == NULL) { 592*18549Ssam fprintf(stderr, "login: malloc out of memory\n"); 593*18549Ssam exit(1); 594*18549Ssam } 595*18549Ssam environ[index] = malloc(varlen + vallen + 1); 596*18549Ssam strcpy(environ[index], var); 597*18549Ssam strcat(environ[index], value); 598*18549Ssam environ[++index] = NULL; 599*18549Ssam } 600