|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 9952 (0x26e0) Types: TextFile Notes: UNIX file Names: »login.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/login.c«
/* * Rec'd from Luaren Weinstein, 7-16-84. * login [-q] [username] * * This version of login stty's the terminal back to the default sgttyb * and tchars settings unless we were exec'd from getty. * * Compile -s -n -i */ #include <stdio.h> #include <pwd.h> #include <signal.h> #include <utmp.h> #include <dir.h> #include <sys/stat.h> #include <sgtty.h> #include <sys/tty.h> #include <chars.h> #define FALSE 0 #define TRUE 1 #define NNAME 64 #define NPAGE 20 /* Most news to print - really ioctl parm. */ #define TTYMODE (S_IREAD|S_IWRITE|S_IEXEC) #define MAXFAIL 3 /* Maximum permitted failed login attempts */ #define MAXTIME 60 /* Maximum seconds permitted for login */ #define PASSLEN 13 /* Length of encrypted passwords */ #define ACCNAME "remacc" /* Remote access password dummy username */ /* * Default sgtty and tchars settings. */ struct sgttyb sgttyd = { /* Initial sgtty */ B9600, /* input speed */ B9600, /* output speed */ '\b', /* erase */ CTRLU, /* kill */ EVENP|ODDP|CRMOD|ECHO|XTABS|CRT /* flags */ }; struct tchars tchars = { /* Initial tchars */ CTRLC, /* int */ FS, /* quit */ CTRLQ, /* start */ CTRLS, /* stop */ CTRLD, /* eof */ -1 /* brkc */ }; int fflag; int iflag; int qflag; int nline; /* Lines output */ char nb[NNAME]; char logcount = 0; /* Login attempt count */ char remote = FALSE; /* Assume not remote tty line */ struct stat sb; struct sgttyb sgp; /* tty structure */ int timeout(); char *env[] = { "PATH=:/bin", "PS1=% ", 0, 0 }; struct news { size_t n_seek; time_t n_time; } news; char longnews[] = "[Too much opening news -- please see \"%s\" at your leisure]\n"; char mailname[50] = "/usr/spool/mail/"; char newslog[] = "/etc/newslog"; char motdf[] = "/etc/motd"; char newsf[] = "/etc/news"; char faillog[] = "/usr/adm/failed"; /* failed login attempt log */ char goodlog[] = "/usr/adm/wtmp"; /* successful login log */ char pass1[] = "Password: "; /* password msg 1 */ char pass2[] = "Remote access password: "; /* password msg 2 */ main(argc, argv) char *argv[]; { register char *cp, *np; register struct passwd *pwp; int c, i, oldtime; char passcount = 0; char *tp, failed; char *crypt(), *getpass(), *ttyname(); char s_name[NNAME]; /* saved name */ int s_uid; /* saved uid */ int s_gid; /* saved gid */ char s_dir[128]; /* saved dir */ char s_shell[128]; /* saved shell */ char shellbuff[128] = "exec "; /* shell exec line buffer */ resetsigs(); /* * Called from /etc/getty? */ if (argc!=0 && argv[0][0]=='-') fflag = 1; else if (argc == 1) slexit(0); if ((tp = ttyname(2)) == NULL) { fprintf(stderr, "Sorry. Cannot figure out terminal name!\n"); slexit(1); } if (settty(2)) { perror(tp); slexit(1); } gtty(1, &sgp); /* get tty status */ if (isremote(tp)) /* Isolate remote determination */ { remote = TRUE; signal(SIGALRM, &timeout); /* catch login timeout */ alarm(MAXTIME); /* set timeout alarm */ } again: failed = TRUE; /* assume attempt will fail */ if (remote && (++logcount > MAXFAIL)) /* count remote attempts */ slexit(1); /* exit (and try force hangup) if too many attempts */ i = 1; while (i<argc && argv[i][0]=='-') { cp = &argv[i++][1]; while (c = *cp++) { switch (c) { case 'q': ++qflag; break; default: usage(); } } } if (passcount == 0) /* first pass? */ { if (i < argc) { np = argv[i]; argc = 0; fflag = 0; } else { np = nb; do { printf("Name: "); if (fgets(nb, NNAME-1, stdin) == NULL) { putchar('\n'); slexit(1); } } while (nb[0] == '\n' && nb[1] == 0); nb[strlen(nb)-1] = 0; /* null terminate over newline */ } setpwent(); /* make sure password file is rewound */ pwp = getpwnam(np); /* get name entry from password file */ if (pwp != NULL) /* if entry found */ { strcpy(s_name, pwp->pw_name); /* save name */ s_uid = pwp->pw_uid; /* save uid */ s_gid = pwp->pw_gid; /* save gid */ strcpy(s_dir, pwp->pw_dir); /* save working dir */ strcpy(s_shell, pwp->pw_shell); /* save shell */ } } else { setpwent(); /* rewind password file */ pwp = getpwnam(ACCNAME); /* check for remote access entry */ if (pwp == NULL || pwp->pw_passwd[0] == 0) /* no access pass? */ goto ok; /* all done */ } if (pwp == NULL || pwp->pw_passwd[0] != 0) { if ((cp = getpass(passcount == 0 ? pass1 : pass2)) != NULL && cp[0] != '\0') { cp = crypt(cp, pwp==NULL ? "xx" : pwp->pw_passwd); if (pwp != NULL && (strcmp(cp, pwp->pw_passwd) == 0) && strcmp(s_name, ACCNAME) && (strlen(pwp->pw_passwd) == PASSLEN)) failed = FALSE; /* success */ } if (failed) /* failed attempt? */ { oldtime = alarm(0); /* turn off alarm */ passcount = 0; /* reset pass count */ setutmp(tp, np, faillog, FALSE); /* failed attempt */ alarm(oldtime); /* continue timeout */ printf("Login incorrect\n"); /* incorrect */ goto again; } } if (remote && passcount++ == 0) /* need another pass? */ { logcount--; /* don't count as login attempt */ goto again; /* yes */ } ok: alarm(0); /* turn off login alarm timeout */ endpwent(); /* close password file */ if (chdir(s_dir) < 0) { perror(s_dir); slexit(1); } setutmp(tp, np, goodlog, TRUE); /* successful login */ chown(tp, s_uid, s_gid); chmod(tp, TTYMODE); information(s_uid, s_name); sprintf(nb, "HOME=%s", s_dir); env[1] = nb; if (s_uid == 0) env[2] = "PS1=# "; setgid(s_gid); setuid(s_uid); for (i=3; close(i)>=0; i++); if (s_shell[0] != '\0') { strcat(shellbuff, s_shell); /* build shell command line */ execle("/bin/sh", "-sh", "-c", shellbuff, NULL, env); fprintf(stderr, "%s: cannot execute.\n", s_shell); } execle("/bin/sh", "-sh", NULL, env); fprintf(stderr, "No shell.\n"); slexit(1); } /* * Reset all signals to their default * state so all commands get invoked * with a known signal state. */ resetsigs() { register int i; for (i=1; i<=NSIG; i++) signal(i, SIG_DFL); } /* * Determine remoteness of login. * Remote logins will require some password, * either the user's own password, or the 'remacc' pseudo * user's password. */ isremote(tp) char *tp; /* ttyname result */ { #ifdef IAPX86 unsigned ttyflags; ioctl(1, TIOCGETTF, &ttyflags); /* get tty flags */ return (ttyflags & T_HPCL); /* assume remote line if HUPCLS */ #endif #ifdef PDP11 register int i; static char *rttys[] = { /* Quick and dirty */ "/dev/tty30", "/dev/tty31", "/dev/tty32", "" }; for (i = 0; rttys[i][0] != 0; i += 1) if (strcmp(rttys[i], tp) == 0) return (1); return (0); #endif } /* * Read the news and message of the day file. * Only print new information. * Also print `You have mail.' message if * applicable. */ information(uid, uname) short uid; char *uname; { register int fd = -1; int (*oifunc)(); int setflag(); size_t prseek(); time_t time(); if (qflag) return; if ((fd = open(newslog, 2)) >= 0) { lseek(fd, (size_t)uid*sizeof news, 0); if (read(fd, &news, sizeof news) != sizeof news) news.n_time = news.n_seek = 0; } oifunc = signal(SIGINT, setflag); iflag = 0; if (stat(motdf, &sb)>=0 && sb.st_mtime>news.n_time) prseek(motdf, (size_t)0); news.n_seek = prseek(newsf, news.n_seek); news.n_time = time((time_t)0); signal(SIGINT, oifunc); if (fd >= 0) { lseek(fd, (size_t)uid*sizeof news, 0); write(fd, &news, sizeof news); close(fd); } strcat(mailname, uname); if (stat(mailname, &sb)>=0 && sb.st_size!=0) printf("You have mail.\n"); } /* * Print a file, starting at position `seek', * watching for interrupts. */ size_t prseek(fn, seek) char *fn; size_t seek; { register FILE *fp; register int c; if ((fp = fopen(fn, "r"))!=NULL) { fseek(fp, seek, 0); while ((c=getc(fp)) != EOF) { if (nline < NPAGE) putchar(c); if (c == '\n') { if (iflag) break; if (nline++ == NPAGE) fprintf(stderr, longnews, fn); } } seek = ftell(fp); fclose(fp); } return (seek); } /* * Write out an accounting entry for * `tty' and `username' into filename pointed to by "filep". * If "success" is TRUE (indicating a good login) also write 'utmp' entry. */ setutmp(tty, username, filep, success) char *tty, *username, *filep; { time_t time(); struct utmp utmp; struct utmp spare; size_t freeslot = -1, slot = 0; register ufd; utmp.ut_time = time((time_t)0); strncpy(utmp.ut_line, tty+5, 8); strncpy(utmp.ut_name, username, DIRSIZ); if ((ufd = open(filep, 1)) >= 0) { lseek(ufd, 0L, 2); write(ufd, &utmp, sizeof (utmp)); close(ufd); } if (!success) /* failed login attempt? */ return; /* all done */ if ((ufd = open("/etc/utmp", 2)) >= 0) { while (read(ufd, &spare, sizeof (spare)) == sizeof (spare)) { if (spare.ut_line[0] == '\0') freeslot = slot; else if (strncmp(spare.ut_line, utmp.ut_line, 8) == 0) { freeslot = slot; break; } slot += sizeof (utmp); } if (freeslot >= 0) lseek(ufd, freeslot, 0); write(ufd, &utmp, sizeof (utmp)); close (ufd); } } setflag() { ++iflag; } usage() { fprintf(stderr, "Usage: login [-q] [username]\n"); slexit(1); } /* login alarm timeout routine */ timeout() { printf("\n"); /* neatness */ slexit(1); /* exit (and try force hangup for remote line) */ } /* * Set the characters for the terminal to the defaults. * Return non-zero on error. */ settty(fd) { if (fflag) return(0); if (ioctl(fd, TIOCSETN, &sgttyd) < 0) return(1); if (ioctl(fd, TIOCSETC, &tchars) < 0) return(1); return(0); } /* sleep for 2 seconds to make sure output has flushed, then exit */ slexit(status) { sleep(2); exit(status); }