1: /* 2: * login [ name ] 3: * login [ name.group ] 4: */ 5: 6: #define GROUP /* allow login as name.group */ 7: #define SP_SESS /* "special session"-- root logins only */ 8: /* used after autoreboot failures */ 9: 10: #include <whoami.h> 11: #include <sys/types.h> 12: #include <sgtty.h> 13: #include <utmp.h> 14: 15: #include <signal.h> 16: #include <pwd.h> 17: #include <stdio.h> 18: #include <sys/stat.h> 19: #include <lastlog.h> 20: #ifdef GROUP 21: #include <grp.h> 22: #endif 23: 24: #define PATH "PATH=:/bin:/usr/ucb:/usr/bin" /* default path */ 25: #define SHELL "/bin/sh" /* default shell */ 26: #define JCLCSH "/bin/csh" /* job control shell, needs new line disc. */ 27: /* 28: * The umask is a local decision. 077 is very paranoid (everything 29: * is highly secret). 0 is wide open (everything readable and writable 30: * by anyone.) 022 is moderate. 027 is also a possibility. 31: */ 32: #define UMASK 022 33: 34: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 35: #define NMAX sizeof(utmp.ut_name) 36: #define LMAX sizeof(utmp.ut_line) 37: #define CNTL(x) ('x'&037) 38: #define UNDEF '\377' 39: 40: char maildir[30] = "/usr/spool/mail/"; 41: char lastlog[] = "/usr/adm/lastlog"; 42: char nolog[] = "/etc/nologin"; 43: struct passwd nouser = {"", "nope"}; 44: struct sgttyb ttyb; 45: struct utmp utmp; 46: char hostname[32]; 47: char minusnam[16] = "-"; 48: char homedir[64] = "HOME="; 49: char term[64] = "TERM="; 50: char shell[64] = "SHELL="; 51: char user[NMAX+9] = "USER="; 52: 53: 54: char *envinit[] = {homedir, PATH, term, shell, user, 0}; 55: 56: #ifdef MENLO_JCL 57: struct ltchars ltc = 58: { CNTL(z), CNTL(y), CNTL(r), CNTL(o), CNTL(w), CNTL(v) 59: }; 60: #endif 61: struct passwd *pwd; 62: 63: struct passwd *getpwnam(); 64: char *strcat(); 65: int setpwent(); 66: char *ttyname(); 67: char *crypt(); 68: char *getpass(); 69: #ifdef GROUP 70: #define GRLEN 30 /* max length of group name */ 71: struct group *grp, *getgrnam(); 72: #endif 73: #ifdef SP_SESS 74: int sp_sess = 0; 75: #endif 76: char *rindex(), *index(); 77: char *ttyn; 78: extern char **environ; 79: extern char _sobuf[]; 80: 81: main(argc, argv) 82: char **argv; 83: { 84: register char *namep; 85: int t, f, c, wasslash, ldisc; 86: char *cp; 87: FILE *nlfd; 88: #ifdef GROUP 89: char group[GRLEN]; 90: #endif 91: 92: setbuf(stdout, _sobuf); 93: alarm(180); 94: signal(SIGQUIT, SIG_IGN); 95: nice(-100); 96: nice(20); 97: nice(0); 98: 99: #ifdef SP_SESS 100: if (argv[0][0] == 's') 101: sp_sess++; 102: #endif 103: 104: for (t=3; t<20; t++) 105: close(t); 106: ttyn = ttyname(0); 107: if (ttyn==0) 108: ttyn = "/dev/tty??"; 109: 110: t = 0; 111: loop: 112: if (++t >10) { 113: ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 114: close(0); 115: sleep(2); 116: exit(1); 117: } 118: SCPYN(utmp.ut_name, ""); 119: #ifdef GROUP 120: SCPYN(group, ""); 121: if (argc>1) { 122: register char *av = argv[1]; 123: namep = utmp.ut_name; 124: while (namep < utmp.ut_name+NMAX) { 125: if (*av == 0 || *av == '.') 126: break; 127: *namep++ = *av++; 128: } 129: if (*av++ == '.') 130: for (namep=group; namep<group+GRLEN; ) 131: if ((*namep++ = *av++) == 0) 132: break; 133: argc = 0; 134: } 135: #else 136: if (argc>1) { 137: SCPYN(utmp.ut_name, argv[1]); 138: argc = 0; 139: } 140: #endif 141: gethostname(hostname, sizeof (hostname)); 142: while (utmp.ut_name[0] == '\0') { 143: namep = utmp.ut_name; 144: printf("%s login: ", hostname); 145: fflush(stdout); 146: while ((c = getchar()) != '\n') { 147: if(c == ' ') 148: c = '_'; 149: if (c == EOF) 150: exit(0); 151: #ifdef GROUP 152: if (c == '.') 153: break; 154: #endif 155: if (namep < utmp.ut_name+NMAX) 156: *namep++ = c; 157: } 158: #ifdef GROUP 159: if (c == '.') { 160: char *pgrp = group; 161: while ((c = getchar()) != '\n') { 162: if (c == EOF) 163: exit(0); 164: if (pgrp < &group[GRLEN]) 165: *pgrp++ = c; 166: } 167: } 168: #endif 169: } 170: setpwent(); 171: if ((pwd = getpwnam(utmp.ut_name)) == NULL) 172: pwd = &nouser; 173: endpwent(); 174: if (*pwd->pw_passwd != '\0') { 175: namep = crypt(getpass("Password:"),pwd->pw_passwd); 176: if (strcmp(namep, pwd->pw_passwd)) { 177: printf("Login incorrect\n"); 178: goto loop; 179: } 180: } 181: #ifdef GROUP 182: if (group[0]) { 183: register i; 184: grp = getgrnam(group); 185: endgrent(); 186: if(grp == 0) { 187: printf("Login incorrect\n"); 188: goto loop; 189: } 190: for(i=0;grp->gr_mem[i];i++) 191: if(strcmp(grp->gr_mem[i], pwd->pw_name) == 0) 192: break; 193: if(grp->gr_mem[i] == 0) { 194: printf("Login incorrect\n"); 195: goto loop; 196: } 197: 198: if(grp->gr_passwd[0] != '\0' && pwd->pw_passwd[0] == '\0') { 199: if(strcmp(grp->gr_passwd, 200: crypt(getpass("Password:"),grp->gr_passwd)) != 0) { 201: printf("Login incorrect\n"); 202: goto loop; 203: } 204: } 205: pwd->pw_gid = grp->gr_gid; 206: } 207: #endif 208: if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 209: /* logins are disabled except for root */ 210: while ((c = getc(nlfd)) != EOF) 211: putchar(c); 212: fflush(stdout); 213: sleep(5); 214: exit(0); 215: } 216: #ifdef SP_SESS 217: if(sp_sess && pwd->pw_uid != 0) { 218: printf("Sorry. You cannot login at this time.\n"); 219: exit(0); 220: } 221: #endif 222: signal(SIGINT, SIG_IGN); 223: alarm(0); 224: if((f = open(lastlog, 2)) >= 0) { 225: struct lastlog ll; 226: 227: lseek(f, (long) ((unsigned) (pwd->pw_uid) * sizeof (struct lastlog)), 0); 228: if (read(f, (char *) &ll, sizeof ll) == sizeof ll && ll.ll_time != 0) { 229: register char *ep = (char *) ctime(&ll.ll_time); 230: printf("Last login: "); 231: ep[24 - 5] = 0; 232: printf("%s on %.*s\n", ep, LMAX, ll.ll_line); 233: fflush(stdout); /* So user sees the message quickly! */ 234: } 235: lseek(f, (long) ((unsigned) (pwd->pw_uid) * sizeof (struct lastlog)), 0); 236: time(&ll.ll_time); 237: strncpy(ll.ll_line, ttyn+5, LMAX); 238: write(f, (char *) &ll, sizeof ll); 239: close(f); 240: } 241: showfile("/etc/motd"); 242: time(&utmp.ut_time); 243: t = ttyslot(); 244: if (t>0 && (f = open("/etc/utmp", 1)) >= 0) { 245: lseek(f, (long)(t*sizeof(utmp)), 0); 246: SCPYN(utmp.ut_line, rindex(ttyn, '/')+1); 247: write(f, (char *)&utmp, sizeof(utmp)); 248: close(f); 249: } 250: if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { 251: lseek(f, 0L, 2); 252: write(f, (char *)&utmp, sizeof(utmp)); 253: close(f); 254: } 255: getterm(); 256: chown(ttyn, pwd->pw_uid, pwd->pw_gid); 257: chmod(ttyn, 0622); 258: setgid(pwd->pw_gid); 259: #ifdef notyet 260: initgroups(pwd->pw_name, pwd->pw_gid); 261: #endif 262: setuid(pwd->pw_uid); 263: namep = pwd->pw_dir; 264: for (;;) { 265: if (*namep == '\0') 266: break; 267: cp = namep++; 268: for (; *namep != '/' && *namep != '\0'; namep++); 269: wasslash = 0; 270: if (*namep == '/') { 271: *namep = '\0'; 272: wasslash++; 273: } 274: if (chdir(cp)<0) { 275: if (chdir("/") < 0) { 276: printf("No directory!\n"); 277: exit(1); 278: } else { 279: printf("No directory! Logging in with home=/\n"); 280: break; 281: } 282: } 283: showfile(".broadcast"); 284: if (wasslash) 285: *namep++ = '/'; 286: } 287: showfile(".reminder"); 288: 289: if (*pwd->pw_shell == '\0') 290: pwd->pw_shell = SHELL; 291: #ifdef MENLO_JCL 292: if (!strcmp(pwd->pw_shell, JCLCSH)) { 293: ldisc = NTTYDISC; 294: ioctl(0, TIOCSETD, &ldisc); 295: } else { 296: ltc.t_suspc = ltc.t_dsuspc = UNDEF; 297: ioctl(0, TIOCSLTC, <c); 298: } 299: #endif 300: environ = envinit; 301: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 302: strncat(user, pwd->pw_name, sizeof(user)-6); 303: if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 304: namep = pwd->pw_shell; 305: else 306: namep++; 307: strncat(shell, pwd->pw_shell, sizeof(shell)-7); 308: strcat(minusnam, namep); 309: umask(UMASK); 310: strcat(maildir, pwd->pw_name); 311: if(access(maildir,4)==0) { 312: struct stat statb; 313: stat(maildir, &statb); 314: if (statb.st_size) 315: printf("You have mail.\n"); 316: } 317: signal(SIGQUIT, SIG_DFL); 318: signal(SIGINT, SIG_DFL); 319: #ifdef SIGTSTP 320: signal(SIGTSTP, SIG_IGN); 321: #endif 322: fflush(stdout); 323: execlp(pwd->pw_shell, minusnam, 0); 324: printf("No shell\n"); 325: exit(0); 326: } 327: 328: int stopmotd; 329: catch() 330: { 331: signal(SIGINT, SIG_IGN); 332: stopmotd++; 333: printf("\n"); 334: fflush(stdout); /* Immediate-looking response. */ 335: } 336: 337: showfile(name) 338: char *name; 339: { 340: FILE *mf; 341: register c; 342: 343: stopmotd = 0; 344: signal(SIGINT, catch); 345: if((mf = fopen(name,"r")) != NULL) { 346: while((c = getc(mf)) != EOF && stopmotd == 0) 347: putchar(c); 348: fclose(mf); 349: fflush(stdout); 350: } 351: signal(SIGINT, SIG_IGN); 352: } 353: 354: /* 355: * make a reasonable guess as to the kind of terminal the user is on. 356: * We look in /etc/ttytype for this info (format: each line has two 357: * words, first word is a term type, second is a tty name), and default 358: * to "unknown" if we can't find any better. In the case of dialups we get 359: * names like "dialup" which is a lousy guess but tset can 360: * take it from there. 361: */ 362: getterm() 363: { 364: 365: register char *sp, *tname; 366: register int i; 367: register FILE *fdes; 368: char *type, *t; 369: char ttline[64]; 370: 371: if ((fdes = fopen("/etc/ttytype", "r")) == NULL) { 372: unknown: 373: strcat(term, "unknown"); 374: return; 375: } 376: for (tname = ttyn; *tname++; ) 377: ; 378: while (*--tname != '/') 379: ; 380: tname++; 381: while (fgets(ttline, sizeof(ttline), fdes) != NULL) { 382: ttline[strlen(ttline)-1] = 0; /* zap \n on end */ 383: type = ttline; 384: for (t=ttline; *t && *t!=' ' && *t != '\t'; t++) 385: ; 386: *t++ = 0; 387: /* Now have term and type pointing to the right guys */ 388: if (strcmp(t, tname) == 0) { 389: strcat(term, type); 390: fclose(fdes); 391: return; 392: } 393: } 394: fclose(fdes); 395: goto unknown; 396: }