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