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, &ltc);
 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: }

Defined functions

catch defined in line 329; used 1 times
getterm defined in line 362; used 1 times
main defined in line 81; never used
showfile defined in line 337; used 3 times

Defined variables

envinit defined in line 54; used 1 times
grp defined in line 71; used 9 times
homedir defined in line 48; used 3 times
hostname defined in line 46; used 3 times
lastlog defined in line 41; used 1 times
ltc defined in line 57; used 3 times
maildir defined in line 40; used 3 times
minusnam defined in line 47; used 2 times
nolog defined in line 42; used 1 times
nouser defined in line 43; used 1 times
pwd defined in line 61; used 29 times
shell defined in line 50; used 3 times
sp_sess defined in line 74; used 2 times
stopmotd defined in line 328; used 3 times
term defined in line 49; used 3 times
ttyb defined in line 44; never used
ttyn defined in line 77; used 8 times
user defined in line 51; used 3 times
utmp defined in line 45; used 17 times

Defined macros

CNTL defined in line 37; used 6 times
  • in line 58(6)
GRLEN defined in line 70; used 3 times
GROUP defined in line 6; used 7 times
JCLCSH defined in line 26; used 1 times
LMAX defined in line 36; used 2 times
NMAX defined in line 35; used 3 times
PATH defined in line 24; used 1 times
  • in line 54
SCPYN defined in line 34; used 4 times
SHELL defined in line 25; used 1 times
SP_SESS defined in line 7; used 3 times
UMASK defined in line 32; used 1 times
UNDEF defined in line 38; used 1 times
Last modified: 1983-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1214
Valid CSS Valid XHTML 1.0 Strict