bug fixes and changes from Rick Adams
[unix-history] / usr / src / libexec / uucpd / uucpd.c
CommitLineData
cd56d176 1#ifndef lint
46b15d8a 2static char sccsid[] = "@(#)uucpd.c 5.2 (Berkeley) %G%";
cd56d176
RC
3#endif
4
5/*
46b15d8a
RC
6 * 4.2BSD TCP/IP server for uucico
7 * uucico's TCP channel causes this server to be run at the remote end.
cd56d176
RC
8 */
9
46b15d8a
RC
10#include "uucp.h"
11#include <signal.h>
cd56d176 12#include <errno.h>
46b15d8a 13#include <sys/param.h>
cd56d176 14#include <sys/socket.h>
46b15d8a 15#include <sys/ioctl.h>
cd56d176 16#include <netinet/in.h>
46b15d8a
RC
17#include <netdb.h>
18#include <sys/wait.h>
19#include <pwd.h>
20#include <lastlog.h>
cd56d176 21
46b15d8a
RC
22char lastlog[] = "/usr/adm/lastlog";
23struct sockaddr_in hisctladdr;
24int hisaddrlen = sizeof hisctladdr;
25struct sockaddr_in myctladdr;
26int mypid;
cd56d176
RC
27
28main(argc, argv)
46b15d8a
RC
29int argc;
30char **argv;
cd56d176 31{
46b15d8a
RC
32 register int s, tcp_socket;
33 struct servent *sp;
34 extern int errno;
35 int dologout();
cd56d176 36
46b15d8a
RC
37#ifdef BSDINETD
38 close(1); close(2);
39 dup(0); dup(0);
40 hisaddrlen = sizeof (hisctladdr);
41 if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
cd56d176
RC
42 fprintf(stderr, "%s: ", argv[0]);
43 perror("getpeername");
44 _exit(1);
45 }
46b15d8a
RC
46 if (fork() == 0)
47 doit(&hisctladdr);
48 dologout();
cd56d176 49 exit(1);
46b15d8a
RC
50#else !BSDINETD
51 sp = getservbyname("uucp", "tcp");
52 if (sp == NULL){
53 perror("uucpd: getservbyname");
54 exit(1);
55 }
56 if ((s=open("/dev/tty", 2)) >= 0){
57 ioctl(s, TIOCNOTTY, (char *)0);
58 close(s);
59 }
60
61 bzero((char *)&myctladdr, sizeof (myctladdr));
62 tcp_socket = socket(AF_INET, SOCK_STREAM, 0, 0);
63 if ( tcp_socket<0 ) {
64 perror("uucpd: socket");
65 exit(1);
66 }
67 myctladdr.sin_port = sp->s_port;
68 if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr), 0) < 0) {
69 perror("uucpd: bind");
70 exit(1);
71 }
72 signal(SIGCHLD, dologout);
73 listen(tcp_socket, 5); /* 5's as good as any */
74
75 for(;;) {
76 s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
77 if (s < 0){
78 if (errno == EINTR)
79 continue;
80 perror("uucpd: accept");
81 exit(1);
82 }
83 if (fork()== 0) {
84 close(0); close(1); close(2);
85 dup(s); dup(s); dup(s);
86 close(tcp_socket);close(s);
87 doit(&hisctladdr);
88 exit(1);
89 }
90 close(s);
91 }
92#endif
93}
94
95doit(sinp)
96struct sockaddr_in *sinp;
97{
98 char ebuf[32];
99 char user[64];
100 char passwd[64];
101 char *xpasswd, *crypt();
102 struct passwd *pw, *getpwnam();
103
104 alarm(60);
105 if (readline(user, sizeof user) < 0) {
106 fprintf(stderr, "user read\n");
107 return;
108 }
109 /* truncate username to 8 characters */
110 user[8] = '\0';
111 pw = getpwnam(user);
112 if (pw == NULL) {
113 fprintf(stderr, "user unknown\n");
114 return;
115 }
116 if (strcmp(pw->pw_shell, UUCICO)) {
117 fprintf(stderr, "Login incorrect.");
118 return;
119 }
120 if (pw->pw_passwd && *pw->pw_passwd != '\0') {
121 if (readline(passwd, sizeof passwd) < 0) {
122 fprintf(stderr, "passwd read\n");
123 return;
124 }
125 xpasswd = crypt(passwd, pw->pw_passwd);
126 if (strcmp(xpasswd, pw->pw_passwd)) {
127 fprintf(stderr, "Login incorrect.");
128 return;
129 }
130 }
131 alarm(0);
132 dologin(pw, sinp);
133 setegid(pw->pw_gid);
134 initgroups(pw->pw_name, pw->pw_gid);
135 chdir(pw->pw_dir);
136 seteuid(pw->pw_uid);
137 execl(UUCICO, "uucico", (char *)0);
138 perror("uucico server: execl");
139}
140
141readline(p, n)
142 register char *p;
143 register int n;
144{
145 char c;
146
147 while (n-- > 0) {
148 if (read(0, &c, 1) <= 0)
149 return(-1);
150 c &= 0177;
151 if (c == '\n' || c == '\r') {
152 *p = '\0';
153 return(0);
154 }
155 *p++ = c;
156 }
157 return(-1);
158}
159
160#include <utmp.h>
161#include <fcntl.h>
162
163#define SCPYN(a, b) strncpy(a, b, sizeof (a))
164
165struct utmp utmp;
166
167dologout()
168{
169 union wait status;
170 int pid, wtmp;
171
172#ifdef BSDINETD
173 while ((pid=wait(&status)) > 0 ) {
174#else !BSDINETD
175 while ((pid=wait3(&status,WNOHANG,0)) > 0 ) {
176#endif !BSDINETD
177 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
178 if (wtmp >= 0) {
179 sprintf(utmp.ut_line, "uucp%.4d", pid);
180 SCPYN(utmp.ut_name, "");
181 SCPYN(utmp.ut_host, "");
182 utmp.ut_time = time(0);
183 (void) write(wtmp, (char *)&utmp, sizeof (utmp));
184 (void) close(wtmp);
185 }
186 }
187}
188
189/*
190 * Record login in wtmp file.
191 */
192dologin(pw, sin)
193struct passwd *pw;
194struct sockaddr_in *sin;
195{
196 char line[32];
197 char remotehost[32];
198 int wtmp, f;
199 struct hostent *hp = gethostbyaddr(&sin->sin_addr,
200 sizeof (struct in_addr), AF_INET);
201
202 if (hp) {
203 strncpy(remotehost, hp->h_name, sizeof (remotehost));
204 endhostent();
205 } else
206 strncpy(remotehost, inet_ntoa(sin->sin_addr),
207 sizeof (remotehost));
208 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
209 if (wtmp >= 0) {
210 /* hack, but must be unique and no tty line */
211 sprintf(line, "uucp%.4d", getpid());
212 SCPYN(utmp.ut_line, line);
213 SCPYN(utmp.ut_name, pw->pw_name);
214 SCPYN(utmp.ut_host, remotehost);
215 utmp.ut_time = time(0);
216 (void) write(wtmp, (char *)&utmp, sizeof (utmp));
217 (void) close(wtmp);
218 }
219 if ((f = open(lastlog, 2)) >= 0) {
220 struct lastlog ll;
221
222 time(&ll.ll_time);
223 lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
224 strcpy(line, remotehost);
225 SCPYN(ll.ll_line, line);
226 SCPYN(ll.ll_host, remotehost);
227 (void) write(f, (char *) &ll, sizeof ll);
228 (void) close(f);
229 }
cd56d176 230}