clean up problems when QUEUE compile flag not defined; clean up hostname
[unix-history] / usr / src / libexec / rlogind / rlogind.c
CommitLineData
a10a364d 1#ifndef lint
aa5cf406 2static char sccsid[] = "@(#)rlogind.c 4.10 83/01/22";
a10a364d
BJ
3#endif
4
5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <sys/socket.h>
c6c678f1
SL
9
10#include <netinet/in.h>
11
a10a364d
BJ
12#include <errno.h>
13#include <pwd.h>
14#include <wait.h>
15#include <signal.h>
16#include <sgtty.h>
17#include <stdio.h>
3f5b52bc 18#include <netdb.h>
a10a364d
BJ
19
20extern errno;
92e31018 21int reapchild();
a10a364d 22struct passwd *getpwnam();
3f5b52bc 23char *crypt(), *rindex(), *index(), *malloc();
3f5b52bc 24struct sockaddr_in sin = { AF_INET };
a10a364d
BJ
25/*
26 * remote login server:
27 * remuser\0
28 * locuser\0
29 * terminal type\0
30 * data
31 */
32main(argc, argv)
33 int argc;
34 char **argv;
35{
92e31018 36 int f, options = SO_KEEPALIVE;
a10a364d 37 struct sockaddr_in from;
3f5b52bc 38 struct servent *sp;
a10a364d 39
3f5b52bc
SL
40 sp = getservbyname("login", "tcp");
41 if (sp == 0) {
42 fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n");
43 exit(1);
44 }
a10a364d
BJ
45#ifndef DEBUG
46 if (fork())
47 exit(0);
48 for (f = 0; f < 10; f++)
49 (void) close(f);
50 (void) open("/", 0);
51 (void) dup2(0, 1);
52 (void) dup2(0, 2);
53 { int tt = open("/dev/tty", 2);
54 if (tt > 0) {
55 ioctl(tt, TIOCNOTTY, 0);
56 close(tt);
57 }
58 }
59#endif
cb2d476f 60 sin.sin_port = sp->s_port;
a10a364d 61 argc--, argv++;
c6c678f1 62 if (argc > 0 && !strcmp(argv[0], "-d")) {
92e31018
SL
63 options |= SO_DEBUG;
64 argc--, argv++;
65 }
66 if (argc > 0) {
3f5b52bc
SL
67 int port = atoi(argv[0]);
68
69 if (port < 0) {
70 fprintf(stderr, "%s: bad port #\n", argv[0]);
71 exit(1);
72 }
cb2d476f 73 sin.sin_port = htons((u_short)port);
3f5b52bc
SL
74 argv++, argc--;
75 }
85b11450 76 f = socket(AF_INET, SOCK_STREAM, 0, 0);
c6c678f1
SL
77 if (f < 0) {
78 perror("rlogind: socket");
79 exit(1);
80 }
92e31018
SL
81 if (options & SO_DEBUG)
82 if (setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
83 perror("rlogind: setsockopt (SO_DEBUG)");
84#ifdef notdef
85 if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
86 perror("rlogind: setsocktopt (SO_KEEPALIVE)");
87#endif
c6c678f1
SL
88 if (bind(f, &sin, sizeof (sin), 0) < 0) {
89 perror("rlogind: bind");
90 exit(1);
91 }
aa5cf406 92 sigset(SIGCHLD, reapchild);
c6c678f1 93 listen(f, 10);
a10a364d 94 for (;;) {
c6c678f1
SL
95 int s, len = sizeof (from);
96
97 s = accept(f, &from, &len, 0);
98 if (s < 0) {
92e31018
SL
99 if (errno == EINTR)
100 continue;
82c973f2 101 perror("rlogind: accept");
a10a364d
BJ
102 continue;
103 }
104 if (fork() == 0)
c6c678f1
SL
105 doit(s, &from);
106 close(s);
a10a364d
BJ
107 }
108}
109
92e31018
SL
110reapchild()
111{
112 union wait status;
113
114 while (wait3(&status, WNOHANG, 0) > 0)
115 ;
116}
117
a10a364d
BJ
118char locuser[32], remuser[32];
119char buf[BUFSIZ];
120int child;
121int cleanup();
122int netf;
123extern errno;
124char *line;
125
126doit(f, fromp)
127 int f;
128 struct sockaddr_in *fromp;
129{
3f5b52bc 130 char c;
82c973f2 131 int i, p, cc, t, pid;
a10a364d 132 int stop = TIOCPKT_DOSTOP;
3f5b52bc 133 register struct hostent *hp;
a10a364d
BJ
134
135 alarm(60);
136 read(f, &c, 1);
137 if (c != 0)
138 exit(1);
139 alarm(0);
cb2d476f 140 fromp->sin_port = htons((u_short)fromp->sin_port);
3f5b52bc
SL
141 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
142 fromp->sin_family);
82c973f2
SL
143 if (hp == 0)
144 fatal(f, "Host name for your address unknown");
a10a364d
BJ
145 if (fromp->sin_family != AF_INET ||
146 fromp->sin_port >= IPPORT_RESERVED ||
82c973f2
SL
147 hp == 0)
148 fatal(f, "Permission denied");
a10a364d
BJ
149 write(f, "", 1);
150 for (c = 'p'; c <= 's'; c++) {
151 struct stat stb;
152 line = "/dev/ptyXX";
153 line[strlen("/dev/pty")] = c;
154 line[strlen("/dev/ptyp")] = '0';
155 if (stat(line, &stb) < 0)
156 break;
157 for (i = 0; i < 16; i++) {
158 line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
159 p = open(line, 2);
160 if (p > 0)
161 goto gotpty;
162 }
163 }
82c973f2
SL
164 fatal(f, "All network ports in use");
165 /*NOTREACHED*/
a10a364d
BJ
166gotpty:
167 dup2(f, 0);
168 line[strlen("/dev/")] = 't';
169#ifdef DEBUG
170 { int tt = open("/dev/tty", 2);
171 if (tt > 0) {
172 ioctl(tt, TIOCNOTTY, 0);
173 close(tt);
174 }
175 }
176#endif
177 t = open(line, 2);
82c973f2
SL
178 if (t < 0)
179 fatalperror(f, line, errno);
a10a364d
BJ
180 { struct sgttyb b;
181 gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
182 }
82c973f2
SL
183 pid = fork();
184 if (pid < 0)
185 fatalperror(f, "", errno);
186 if (pid) {
a10a364d
BJ
187 char pibuf[1024], fibuf[1024], *pbp, *fbp;
188 int pcc = 0, fcc = 0, on = 1;
189/* FILE *console = fopen("/dev/console", "w"); */
190/* setbuf(console, 0); */
191
192/* fprintf(console, "f %d p %d\r\n", f, p); */
193 ioctl(f, FIONBIO, &on);
194 ioctl(p, FIONBIO, &on);
195 ioctl(p, TIOCPKT, &on);
196 signal(SIGTSTP, SIG_IGN);
197 sigset(SIGCHLD, cleanup);
198 for (;;) {
199 int ibits = 0, obits = 0;
82c973f2
SL
200
201 if (fcc)
202 obits |= (1<<p);
203 else
204 ibits |= (1<<f);
a10a364d 205 if (pcc >= 0)
82c973f2
SL
206 if (pcc)
207 obits |= (1<<f);
208 else
209 ibits |= (1<<p);
210 if (fcc < 0 && pcc < 0)
211 break;
a10a364d 212/* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */
c6c678f1 213 select(16, &ibits, &obits, 0, 0, 0);
a10a364d
BJ
214/* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */
215 if (ibits == 0 && obits == 0) {
216 sleep(5);
217 continue;
218 }
219 if (ibits & (1<<f)) {
220 fcc = read(f, fibuf, sizeof (fibuf));
221/* fprintf(console, "%d from f\r\n", fcc); */
222 if (fcc < 0 && errno == EWOULDBLOCK)
223 fcc = 0;
224 else {
225 if (fcc <= 0)
226 break;
227 fbp = fibuf;
228 }
229 }
230 if (ibits & (1<<p)) {
231 pcc = read(p, pibuf, sizeof (pibuf));
232/* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */
233 pbp = pibuf;
234 if (pcc < 0 && errno == EWOULDBLOCK)
235 pcc = 0;
236 else if (pcc <= 0)
237 pcc = -1;
238 else if (pibuf[0] == 0)
239 pbp++, pcc--;
240 else {
241 if (pibuf[0]&(TIOCPKT_FLUSHWRITE|
242 TIOCPKT_NOSTOP|
243 TIOCPKT_DOSTOP)) {
244 int nstop = pibuf[0] &
245 (TIOCPKT_NOSTOP|
246 TIOCPKT_DOSTOP);
247 if (nstop)
248 stop = nstop;
249 pibuf[0] |= nstop;
c6c678f1 250 send(f,&pibuf[0],1,SOF_OOB);
a10a364d
BJ
251 }
252 pcc = 0;
253 }
254 }
255 if ((obits & (1<<f)) && pcc > 0) {
256 cc = write(f, pbp, pcc);
257/* fprintf(console, "%d of %d to f\r\n", cc, pcc); */
258 if (cc > 0) {
259 pcc -= cc;
260 pbp += cc;
261 }
262 }
263 if ((obits & (1<<p)) && fcc > 0) {
264 cc = write(p, fbp, fcc);
265/* fprintf(console, "%d of %d to p\r\n", cc, fcc); */
266 if (cc > 0) {
267 fcc -= cc;
268 fbp += cc;
269 }
270 }
271 }
272 cleanup();
273 }
274 close(f);
275 close(p);
276 dup2(t, 0);
277 dup2(t, 1);
278 dup2(t, 2);
279 close(t);
3f5b52bc 280 execl("/bin/login", "login", "-r", hp->h_name, 0);
82c973f2
SL
281 fatalperror(2, "/bin/login", errno);
282 /*NOTREACHED*/
a10a364d
BJ
283}
284
285cleanup()
286{
a10a364d
BJ
287
288 rmut();
dd83e8ac 289 vhangup(); /* XXX */
ff24c640 290 shutdown(netf, 2);
a10a364d
BJ
291 kill(0, SIGKILL);
292 exit(1);
293}
294
82c973f2
SL
295fatal(f, msg)
296 int f;
297 char *msg;
298{
299 char buf[BUFSIZ];
300
301 buf[0] = '\01'; /* error indicator */
302 (void) sprintf(buf + 1, "rlogind: %s.\n", msg);
303 (void) write(f, buf, strlen(buf));
304 exit(1);
305}
306
307fatalperror(f, msg, errno)
308 int f;
309 char *msg;
310 int errno;
311{
312 char buf[BUFSIZ];
313 extern char *sys_errlist[];
314
315 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
316 fatal(f, buf);
317}
318
a10a364d
BJ
319#include <utmp.h>
320
321struct utmp wtmp;
322char wtmpf[] = "/usr/adm/wtmp";
323char utmp[] = "/etc/utmp";
324#define SCPYN(a, b) strncpy(a, b, sizeof(a))
325#define SCMPN(a, b) strncmp(a, b, sizeof(a))
326
327rmut()
328{
329 register f;
330 int found = 0;
331
332 f = open(utmp, 2);
333 if (f >= 0) {
334 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
335 if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
336 continue;
337 lseek(f, -(long)sizeof(wtmp), 1);
338 SCPYN(wtmp.ut_name, "");
339 time(&wtmp.ut_time);
340 write(f, (char *)&wtmp, sizeof(wtmp));
341 found++;
342 }
343 close(f);
344 }
345 if (found) {
346 f = open(wtmpf, 1);
347 if (f >= 0) {
348 SCPYN(wtmp.ut_line, line+5);
349 SCPYN(wtmp.ut_name, "");
350 time(&wtmp.ut_time);
351 lseek(f, (long)0, 2);
352 write(f, (char *)&wtmp, sizeof(wtmp));
353 close(f);
354 }
355 }
356 chmod(line, 0666);
357 chown(line, 0, 0);
358 line[strlen("/dev/")] = 'p';
359 chmod(line, 0666);
360 chown(line, 0, 0);
361}