xref: /original-bsd/usr.bin/login/login.c (revision 4c0d4567)
1 static char *sccsid = "@(#)login.c	4.1 (Berkeley) 10/01/80";
2 /*
3  * login [ name ]
4  */
5 
6 #include <sys/types.h>
7 #include <sgtty.h>
8 #include <utmp.h>
9 #include <signal.h>
10 #include <pwd.h>
11 #include <stdio.h>
12 #include <sys/stat.h>
13 #include <lastlog.h>
14 #define SCPYN(a, b)	strncpy(a, b, sizeof(a))
15 
16 #define NMAX sizeof(utmp.ut_name)
17 #define LMAX sizeof(utmp.ut_line)
18 
19 char	user[20];
20 char	maildir[30] =	"/usr/spool/mail/";
21 char	lastlog[] =	"/usr/adm/lastlog";
22 struct	passwd nouser = {"", "nope"};
23 struct	sgttyb ttyb;
24 struct	utmp utmp;
25 char	minusnam[16] = "-";
26 char	homedir[64] = "HOME=";
27 char	shell[64] = "SHELL=";
28 char	term[64] = "TERM=";
29 char	*envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user,0};
30 struct	passwd *pwd;
31 
32 struct	passwd *getpwnam();
33 char	*strcat();
34 int	setpwent();
35 char	*ttyname();
36 char	*crypt();
37 char	*getpass();
38 char	*rindex();
39 char	*stypeof();
40 extern	char **environ;
41 
42 main(argc, argv)
43 char **argv;
44 {
45 	register char *namep;
46 	int t, f, c;
47 	char *ttyn;
48 	int ldisc = 0;
49 
50 	alarm(60);
51 	signal(SIGQUIT, SIG_IGN);
52 	signal(SIGINT, SIG_IGN);
53 	nice(-100);
54 	nice(20);
55 	nice(0);
56 	ioctl(0, TIOCLSET, 0);
57 	ioctl(0, TIOCNXCL, 0);
58 	gtty(0, &ttyb);
59 	ttyb.sg_erase = '#';
60 	ttyb.sg_kill = '@';
61 	stty(0, &ttyb);
62 	for (t=3; t<20; t++)
63 		close(t);
64 	ttyn = ttyname(0);
65 	if (ttyn==0)
66 		ttyn = "/dev/tty??";
67 
68     loop:
69 	ldisc = 0;
70 	ioctl(0, TIOCSETD, &ldisc);
71 	SCPYN(utmp.ut_name, "");
72 	if (argc>1) {
73 		SCPYN(utmp.ut_name, argv[1]);
74 		argc = 0;
75 	}
76 	while (utmp.ut_name[0] == '\0') {
77 		namep = utmp.ut_name;
78 		printf("login: ");
79 		while ((c = getchar()) != '\n') {
80 			if(c == ' ')
81 				c = '_';
82 			if (c == EOF)
83 				exit(0);
84 			if (namep < utmp.ut_name+NMAX)
85 				*namep++ = c;
86 		}
87 	}
88 	setpwent();
89 	if ((pwd = getpwnam(utmp.ut_name)) == NULL)
90 		pwd = &nouser;
91 	endpwent();
92 	if (!strcmp(pwd->pw_shell, "/bin/csh")) {
93 		ldisc = NTTYDISC;
94 		ioctl(0, TIOCSETD, &ldisc);
95 	}
96 	if (*pwd->pw_passwd != '\0') {
97 		nice(-4);
98 		namep = crypt(getpass("Password:"),pwd->pw_passwd);
99 		nice(4);
100 		if (strcmp(namep, pwd->pw_passwd)) {
101 bad:
102 			printf("Login incorrect\n");
103 			if (ttyn[LMAX] == 'd') {
104 				FILE *console = fopen("/dev/console", "w");
105 				if (console != NULL) {
106 					fprintf(console, "\r\nBADDIALUP %s %s\r\n", ttyn+5, utmp.ut_name);
107 					fclose(console);
108 				}
109 			}
110 			goto loop;
111 		}
112 	}
113 	sprintf(user, "USER=%.*s", NMAX, pwd->pw_name);
114 	if (pwd->pw_uid == 0 && ttyn[5] != 'c')
115 		goto bad;
116 	if (ttyn[LMAX] == 'd') {
117 		FILE *console = fopen("/dev/console", "w");
118 		if (console != NULL) {
119 			fprintf(console, "\r\nDIALUP %s %s\r\n", ttyn+5, pwd->pw_name);
120 			fclose(console);
121 		}
122 	}
123 	if((f = open(lastlog, 2)) >= 0) {
124 		struct lastlog ll;
125 
126 		lseek(f, pwd->pw_uid * sizeof (struct lastlog), 0);
127 		if (read(f, (char *) &ll, sizeof ll) == sizeof ll && ll.ll_time != 0) {
128 			register char *ep = (char *) ctime(&ll.ll_time);
129 			printf("Last login: ");
130 			ep[24 - 5] = 0;
131 			printf("%s on %.*s\n", ep, LMAX, ll.ll_line);
132 		}
133 		lseek(f, pwd->pw_uid * sizeof (struct lastlog), 0);
134 		time(&ll.ll_time);
135 		strcpyn(ll.ll_line, ttyn+5, LMAX);
136 		write(f, (char *) &ll, sizeof ll);
137 		close(f);
138 	}
139 	if(chdir(pwd->pw_dir) < 0) {
140 		printf("No directory\n");
141 		goto loop;
142 	}
143 	time(&utmp.ut_time);
144 	t = ttyslot();
145 	if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
146 		lseek(f, (long)(t*sizeof(utmp)), 0);
147 		SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
148 		write(f, (char *)&utmp, sizeof(utmp));
149 		close(f);
150 	}
151 	if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
152 		lseek(f, 0L, 2);
153 		write(f, (char *)&utmp, sizeof(utmp));
154 		close(f);
155 	}
156 	chown(ttyn, pwd->pw_uid, pwd->pw_gid);
157 	setgid(pwd->pw_gid);
158 	setuid(pwd->pw_uid);
159 	if (*pwd->pw_shell == '\0')
160 		pwd->pw_shell = "/bin/sh";
161 	environ = envinit;
162 	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
163 	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
164 	strncat(term, stypeof(ttyn), sizeof(term)-6);
165 	if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
166 		namep = pwd->pw_shell;
167 	else
168 		namep++;
169 	strcat(minusnam, namep);
170 	alarm(0);
171 	umask(022);
172 	showmotd();
173 	strcat(maildir, pwd->pw_name);
174 	if(access(maildir,4)==0) {
175 		struct stat statb;
176 		stat(maildir, &statb);
177 		if (statb.st_size)
178 			printf("You have mail.\n");
179 	}
180 	signal(SIGQUIT, SIG_DFL);
181 	signal(SIGINT, SIG_DFL);
182 	execlp(pwd->pw_shell, minusnam, 0);
183 	printf("No shell\n");
184 	exit(0);
185 }
186 
187 int	stopmotd;
188 catch()
189 {
190 	signal(SIGINT, SIG_IGN);
191 	stopmotd++;
192 }
193 
194 showmotd()
195 {
196 	FILE *mf;
197 	register c;
198 
199 	signal(SIGINT, catch);
200 	if((mf = fopen("/etc/motd","r")) != NULL) {
201 		while((c = getc(mf)) != EOF && stopmotd == 0)
202 			putchar(c);
203 		fclose(mf);
204 	}
205 	signal(SIGINT, SIG_IGN);
206 }
207 
208 #define UNKNOWN "su"
209 
210 char *
211 stypeof(ttyid)
212 char	*ttyid;
213 {
214 	static char	typebuf[16];
215 	char		buf[50];
216 	register FILE	*f;
217 	register char	*p, *t, *q;
218 
219 	if (ttyid == NULL)
220 		return (UNKNOWN);
221 	f = fopen("/etc/ttytype", "r");
222 	if (f == NULL)
223 		return (UNKNOWN);
224 	/* split off end of name */
225 	for (p = q = ttyid; *p != 0; p++)
226 		if (*p == '/')
227 			q = p + 1;
228 
229 	/* scan the file */
230 	while (fgets(buf, sizeof buf, f) != NULL)
231 	{
232 		for (t=buf; *t!=' '; t++)
233 			;
234 		*t++ = 0;
235 		for (p=t; *p>' '; p++)
236 			;
237 		*p = 0;
238 		if (strcmp(q,t)==0) {
239 			strcpy(typebuf, buf);
240 			fclose(f);
241 			return (typebuf);
242 		}
243 	}
244 	fclose (f);
245 	return (UNKNOWN);
246 }
247