date and time created 86/01/05 18:46:22 by sam
[unix-history] / usr / src / libexec / uucpd / uucpd.c
CommitLineData
cd56d176 1#ifndef lint
79b62878 2static char sccsid[] = "@(#)uucpd.c 5.4 (Berkeley) %G%";
cd56d176
RC
3#endif
4
5/*
79b62878 6 * 4.2BSD or 2.9BSD TCP/IP server for uucico
46b15d8a 7 * uucico's TCP channel causes this server to be run at the remote end.
cd56d176
RC
8 */
9
46b15d8a 10#include "uucp.h"
79b62878
JB
11#include <netdb.h>
12#ifdef BSD2_9
13#include <sys/localopts.h>
14#include <sys/file.h>
15#endif BSD2_9
46b15d8a 16#include <signal.h>
cd56d176 17#include <errno.h>
cd56d176
RC
18#include <sys/socket.h>
19#include <netinet/in.h>
46b15d8a 20#include <sys/wait.h>
79b62878 21#include <sys/ioctl.h>
46b15d8a
RC
22#include <pwd.h>
23#include <lastlog.h>
cd56d176 24
79b62878
JB
25#if !defined(BSD4_2) && !defined(BSD2_9)
26--- You must have either BSD4_2 or BSD2_9 defined for this to work
27#endif !BSD4_2 && !BSD2_9
28#if defined(BSD4_2) && defined(BSD2_9)
29--- You may not have both BSD4_2 and BSD2_9 defined for this to work
30#endif /* check for stupidity */
31
46b15d8a
RC
32char lastlog[] = "/usr/adm/lastlog";
33struct sockaddr_in hisctladdr;
34int hisaddrlen = sizeof hisctladdr;
35struct sockaddr_in myctladdr;
36int mypid;
cd56d176 37
79b62878
JB
38char Username[64];
39char *nenv[] = {
40 Username,
41 NULL,
42};
43extern char **environ;
44
cd56d176 45main(argc, argv)
46b15d8a
RC
46int argc;
47char **argv;
cd56d176 48{
1a85e9d2 49#ifndef BSDINETD
46b15d8a
RC
50 register int s, tcp_socket;
51 struct servent *sp;
1a85e9d2 52#endif !BSDINETD
46b15d8a
RC
53 extern int errno;
54 int dologout();
cd56d176 55
79b62878 56 environ = nenv;
46b15d8a
RC
57#ifdef BSDINETD
58 close(1); close(2);
59 dup(0); dup(0);
60 hisaddrlen = sizeof (hisctladdr);
61 if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
cd56d176
RC
62 fprintf(stderr, "%s: ", argv[0]);
63 perror("getpeername");
64 _exit(1);
65 }
46b15d8a
RC
66 if (fork() == 0)
67 doit(&hisctladdr);
68 dologout();
cd56d176 69 exit(1);
46b15d8a
RC
70#else !BSDINETD
71 sp = getservbyname("uucp", "tcp");
72 if (sp == NULL){
73 perror("uucpd: getservbyname");
74 exit(1);
75 }
79b62878
JB
76 if (fork())
77 exit(0);
46b15d8a
RC
78 if ((s=open("/dev/tty", 2)) >= 0){
79 ioctl(s, TIOCNOTTY, (char *)0);
80 close(s);
81 }
82
83 bzero((char *)&myctladdr, sizeof (myctladdr));
79b62878
JB
84 myctladdr.sin_family = AF_INET;
85 myctladdr.sin_port = sp->s_port;
86#ifdef BSD4_2
87 tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
88 if (tcp_socket < 0) {
46b15d8a
RC
89 perror("uucpd: socket");
90 exit(1);
91 }
79b62878 92 if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
46b15d8a
RC
93 perror("uucpd: bind");
94 exit(1);
95 }
79b62878 96 listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */
46b15d8a 97 signal(SIGCHLD, dologout);
46b15d8a
RC
98
99 for(;;) {
100 s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
101 if (s < 0){
79b62878 102 if (errno == EINTR)
46b15d8a
RC
103 continue;
104 perror("uucpd: accept");
105 exit(1);
106 }
79b62878 107 if (fork() == 0) {
46b15d8a
RC
108 close(0); close(1); close(2);
109 dup(s); dup(s); dup(s);
79b62878 110 close(tcp_socket); close(s);
46b15d8a
RC
111 doit(&hisctladdr);
112 exit(1);
113 }
114 close(s);
115 }
79b62878
JB
116#endif BSD4_2
117
118#ifdef BSD2_9
119 for(;;) {
120 signal(SIGCHLD, dologout);
121 s = socket(SOCK_STREAM, 0, &myctladdr,
122 SO_ACCEPTCONN|SO_KEEPALIVE);
123 if (s < 0) {
124 perror("uucpd: socket");
125 exit(1);
126 }
127 if (accept(s, &hisctladdr) < 0) {
128 if (errno == EINTR) {
129 close(s);
130 continue;
131 }
132 perror("uucpd: accept");
133 exit(1);
134 }
135 if (fork() == 0) {
136 close(0); close(1); close(2);
137 dup(s); dup(s); dup(s);
138 close(s);
139 doit(&hisctladdr);
140 exit(1);
141 }
142 }
143#endif BSD2_9
144#endif !BSDINETD
46b15d8a
RC
145}
146
147doit(sinp)
148struct sockaddr_in *sinp;
149{
79b62878 150 char user[64], passwd[64];
46b15d8a
RC
151 char *xpasswd, *crypt();
152 struct passwd *pw, *getpwnam();
153
154 alarm(60);
1a85e9d2 155 printf("login: "); fflush(stdout);
46b15d8a
RC
156 if (readline(user, sizeof user) < 0) {
157 fprintf(stderr, "user read\n");
158 return;
159 }
160 /* truncate username to 8 characters */
161 user[8] = '\0';
162 pw = getpwnam(user);
163 if (pw == NULL) {
164 fprintf(stderr, "user unknown\n");
165 return;
166 }
167 if (strcmp(pw->pw_shell, UUCICO)) {
168 fprintf(stderr, "Login incorrect.");
169 return;
170 }
171 if (pw->pw_passwd && *pw->pw_passwd != '\0') {
1a85e9d2 172 printf("Password: "); fflush(stdout);
46b15d8a
RC
173 if (readline(passwd, sizeof passwd) < 0) {
174 fprintf(stderr, "passwd read\n");
175 return;
176 }
177 xpasswd = crypt(passwd, pw->pw_passwd);
178 if (strcmp(xpasswd, pw->pw_passwd)) {
179 fprintf(stderr, "Login incorrect.");
180 return;
181 }
182 }
183 alarm(0);
79b62878 184 sprintf(Username, "USER=%s", user);
46b15d8a 185 dologin(pw, sinp);
79b62878
JB
186 setgid(pw->pw_gid);
187#ifdef BSD4_2
46b15d8a 188 initgroups(pw->pw_name, pw->pw_gid);
79b62878 189#endif BSD4_2
46b15d8a 190 chdir(pw->pw_dir);
79b62878
JB
191 setuid(pw->pw_uid);
192#ifdef BSD4_2
46b15d8a 193 execl(UUCICO, "uucico", (char *)0);
79b62878
JB
194#endif BSD4_2
195#ifdef BSD2_9
196 sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr));
197 execl(UUCICO, "uucico", passwd, (char *)0);
198#endif BSD2_9
46b15d8a
RC
199 perror("uucico server: execl");
200}
201
202readline(p, n)
1a85e9d2
RC
203register char *p;
204register int n;
46b15d8a
RC
205{
206 char c;
207
208 while (n-- > 0) {
209 if (read(0, &c, 1) <= 0)
210 return(-1);
211 c &= 0177;
212 if (c == '\n' || c == '\r') {
213 *p = '\0';
214 return(0);
215 }
216 *p++ = c;
217 }
218 return(-1);
219}
220
221#include <utmp.h>
79b62878 222#ifdef BSD4_2
46b15d8a 223#include <fcntl.h>
79b62878
JB
224#endif BSD4_2
225
226#ifdef BSD2_9
227#define O_APPEND 0 /* kludge */
228#define wait3(a,b,c) wait2(a,b)
229#endif BSD2_9
46b15d8a
RC
230
231#define SCPYN(a, b) strncpy(a, b, sizeof (a))
232
233struct utmp utmp;
234
235dologout()
236{
237 union wait status;
238 int pid, wtmp;
239
240#ifdef BSDINETD
79b62878 241 while ((pid=wait(&status)) > 0) {
46b15d8a 242#else !BSDINETD
79b62878 243 while ((pid=wait3(&status,WNOHANG,0)) > 0) {
46b15d8a
RC
244#endif !BSDINETD
245 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
246 if (wtmp >= 0) {
247 sprintf(utmp.ut_line, "uucp%.4d", pid);
248 SCPYN(utmp.ut_name, "");
249 SCPYN(utmp.ut_host, "");
79b62878
JB
250 (void) time(&utmp.ut_time);
251#ifdef BSD2_9
252 (void) lseek(wtmp, 0L, 2);
253#endif BSD2_9
46b15d8a
RC
254 (void) write(wtmp, (char *)&utmp, sizeof (utmp));
255 (void) close(wtmp);
256 }
257 }
258}
259
260/*
261 * Record login in wtmp file.
262 */
263dologin(pw, sin)
264struct passwd *pw;
265struct sockaddr_in *sin;
266{
267 char line[32];
268 char remotehost[32];
269 int wtmp, f;
270 struct hostent *hp = gethostbyaddr(&sin->sin_addr,
271 sizeof (struct in_addr), AF_INET);
272
273 if (hp) {
274 strncpy(remotehost, hp->h_name, sizeof (remotehost));
275 endhostent();
276 } else
277 strncpy(remotehost, inet_ntoa(sin->sin_addr),
278 sizeof (remotehost));
279 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
280 if (wtmp >= 0) {
281 /* hack, but must be unique and no tty line */
282 sprintf(line, "uucp%.4d", getpid());
283 SCPYN(utmp.ut_line, line);
284 SCPYN(utmp.ut_name, pw->pw_name);
285 SCPYN(utmp.ut_host, remotehost);
79b62878
JB
286 time(&utmp.ut_time);
287#ifdef BSD2_9
288 (void) lseek(wtmp, 0L, 2);
289#endif BSD2_9
46b15d8a
RC
290 (void) write(wtmp, (char *)&utmp, sizeof (utmp));
291 (void) close(wtmp);
292 }
293 if ((f = open(lastlog, 2)) >= 0) {
294 struct lastlog ll;
295
296 time(&ll.ll_time);
297 lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
298 strcpy(line, remotehost);
299 SCPYN(ll.ll_line, line);
300 SCPYN(ll.ll_host, remotehost);
301 (void) write(f, (char *) &ll, sizeof ll);
302 (void) close(f);
303 }
cd56d176 304}