|
|
1.1 root 1: #ifndef lint
2: static char RCSid[] = "$Header: gaptelnetd.c,v 2.4 86/10/20 12:00:04 root Exp $";
3: #endif
4: /*
5: * server for GAP-style (TransportObject=server,teletype) telnet connections
6: * Note that we support only GAP version 3
7: */
8:
9: /* $Log: gaptelnetd.c,v $
10: * Revision 2.4 86/10/20 12:00:04 root
11: * Fix bug (finally) causing delayed close of connections when UNIX logs out.
12: *
13: * Revision 2.3 86/10/11 12:39:53 jqj
14: * Fixes from Bill Jackson: put lower fork in correct tty and process
15: * group -- required for real 4.3 release.
16: *
17: * Revision 2.2 86/09/12 09:50:28 jqj
18: * Fixes for 4.3bsd:
19: * 1/ added setpgrp(0,0) to make csh happy (symptom was that chat
20: * sessions would work only if default shell was /bin/sh).
21: * 2/ change to FD_ macros since ibits and obits can now be more than
22: * 32 bits long (we could have more than 32 open descriptors in principal).
23: *
24: * Revision 2.1 86/05/16 11:04:00 jqj
25: * fix to correspond to new semantics for enumerations (global)
26: *
27: * Revision 2.0 85/11/21 07:23:06 jqj
28: * 4.3BSD standard release
29: *
30: * Revision 1.3 85/11/21 06:53:22 jqj
31: * symbolic values for connection type
32: *
33: * Revision 1.2 85/11/08 17:17:13 bill
34: * version on bullwinkle
35: *
36: * Revision 1.3 85/08/05 09:58:00 jqj
37: * fixed for Interlisp -- data from Interlisp appears with dt==0 (wrong!)
38: * also, Interlisp trys to connect to a tty rather than a ttyHost.
39: * increased inactivity timeout to 4 hrs
40: *
41: * Revision 1.2 85/05/23 06:22:18 jqj
42: * *** empty log message ***
43: *
44: * Revision 1.1 85/05/22 09:46:52 jqj
45: * Initial revision
46: */
47: #include <stdio.h>
48: #include <signal.h>
49: #include <sgtty.h>
50: #include <sys/types.h>
51: #include <sys/time.h>
52: #include <sys/uio.h>
53: #include <sys/socket.h>
54: #include <netns/ns.h>
55: #include <netns/idp.h>
56: #include <netns/sp.h>
57: #include <sys/wait.h>
58: #include <xnscourier/realcourierconnection.h>
59: #include "GAP3.h"
60: #include "gapcontrols.h"
61: #include <xnscourier/except.h>
62: #include <errno.h>
63:
64: #define BELL '\07'
65: #define BANNER "\r\n\r\n4.3 BSD UNIX (%s)\r\n\r\r\n\r"
66:
67: int pty, net;
68: extern CourierConnection *_serverConnection;
69: char buf[sizeof(struct sphdr)+SPPMAXDATA];
70: struct sphdr our_sphdr;
71: struct iovec our_iovec[2] = {{((caddr_t)&our_sphdr), sizeof(our_sphdr)}};
72: /*
73: * I/O data buffers, pointers, and counters.
74: */
75: char ptyibuf[512], *ptyip = ptyibuf;
76: char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
77: char *netip = buf;
78: char netobuf[512], *nfrontp = netobuf, *nbackp = netobuf;
79: int pcc, ncc;
80: char line[12];
81: extern char **environ;
82: extern int errno;
83:
84: char *envinit[3];
85:
86: /*
87: * session parameters
88: */
89: Cardinal frametimeout; /* 0 or time in seconds to wait */
90:
91:
92: /*
93: * This modified version of the server is necessary since GAP specifies
94: * that the telnet data-transfer session occurs after the RPC to create
95: * it has returned!
96: */
97: Server(skipcount,skippedwords)
98: int skipcount;
99: Unspecified skippedwords[];
100: {
101: Cardinal _procedure;
102: register Unspecified *_buf;
103: LongCardinal programnum;
104: Cardinal versionnum;
105: Cardinal _n;
106:
107: #ifdef DEBUG
108: BUGOUT("Server: %d %d",skipcount,skippedwords);
109: #endif
110: for (;;) {
111: _buf = ReceiveCallMessage(&_procedure, skipcount, skippedwords);
112: DURING switch (_procedure) {
113: case 3:
114: server_GAP3_Delete(_buf);
115: break;
116: case 2:
117: server_GAP3_Create(_buf);
118: net = _serverConnection->fd;
119: gaptelnet(); /* returns on connection close */
120: break;
121: case 0:
122: server_GAP3_Reset(_buf);
123: break;
124: default:
125: NoSuchProcedureValue("GAP", _procedure);
126: break;
127: } HANDLER {
128: Deallocate(_buf);
129: switch (Exception.Code) {
130: case GAP3_serviceNotFound:
131: case GAP3_userNotAuthorized:
132: case GAP3_userNotAuthenticated:
133: case GAP3_serviceTooBusy:
134: case GAP3_terminalAddressInvalid:
135: case GAP3_terminalAddressInUse:
136: case GAP3_controllerDoesNotExist:
137: case GAP3_controllerAlreadyExists:
138: case GAP3_gapCommunicationError:
139: case GAP3_gapNotExported:
140: case GAP3_bugInGAPCode:
141: case GAP3_tooManyGateStreams:
142: case GAP3_inconsistentParams:
143: case GAP3_transmissionMediumUnavailable:
144: case GAP3_dialingHardwareProblem:
145: case GAP3_noDialingHardware:
146: case GAP3_badAddressFormat:
147: case GAP3_mediumConnectFailed:
148: case GAP3_illegalTransport:
149: case GAP3_noCommunicationHardware:
150: case GAP3_unimplemented:
151: _buf = Allocate(0);
152: SendAbortMessage(Exception.Code-ERROR_OFFSET, 0, _buf);
153: break;
154: default:
155: _buf = Allocate(0);
156: SendRejectMessage(unspecifiedError, 0, _buf);
157: break;
158: }
159: } END_HANDLER;
160: Deallocate(_buf);
161: for (;;) {
162: skipcount = LookAheadCallMsg(&programnum, &versionnum,
163: skippedwords);
164: if (skipcount < 0) return(0); /* timed out */
165: if (programnum != 3 || versionnum != 3)
166: ExecCourierProgram(programnum, versionnum,
167: skipcount, skippedwords);
168: } /* loop if can't exec that program */
169: }
170: }
171:
172: void
173: GAP3_Delete(session)
174: GAP3_SessionHandle session;
175: {
176: }
177:
178: void
179: GAP3_Reset()
180: {
181: }
182:
183: GAP3_CreateResults
184: GAP3_Create(conn, BDTproc, sessionparams, transports,
185: createTimeout, credentials, verifier)
186: CourierConnection *conn;
187: int BDTproc;
188: GAP3_SessionParameterObject sessionparams;
189: struct {Cardinal length;
190: GAP3_TransportObject *sequence;
191: } transports;
192: GAP3_WaitTime createTimeout;
193: Authentication1_Credentials credentials;
194: Authentication1_Verifier verifier;
195: {
196: GAP3_CreateResults result;
197: char *c1, *c2, *host;
198: int t, pid, mypid;
199: struct sgttyb b;
200: char *wsname();
201: struct sockaddr_ns who;
202: int whosize = sizeof(who);
203: LongCardinal servicetype;
204: GAP3_CommParamObject *cp;
205: GAP3_Duplexity duplexity; /* fullDuplex, halfDuplex */
206:
207: #ifdef DEBUG
208: BUGOUT("CREATE");
209: #endif
210: switch (sessionparams.designator) {
211: case GAP3_oldTty:
212: case GAP3_oldTtyHost:
213: frametimeout = sessionparams.GAP3_oldTtyHost_case.frameTimeout/1000;
214: /* could set other parameters here */
215: break;
216: case GAP3_tty:
217: case GAP3_ttyHost:
218: frametimeout = sessionparams.GAP3_ttyHost_case.frameTimeout/1000;
219: /* could set other parameters here */
220: break;
221: default:
222: raise(GAP3_unimplemented, 0);
223: /*NOTREACHED*/
224: }
225: if (transports.length != 2) {
226: raise(GAP3_illegalTransport);
227: /*NOTREACHED*/
228: }
229: switch (transports.sequence[0].designator) {
230: case GAP3_service:
231: servicetype = transports.sequence[0].GAP3_service_case.id;
232: switch (servicetype) {
233: case TTYService_any: /* 0 */
234: servicetype = TTYService_sa;
235: case TTYService_sa: /* 1 */
236: case TTYService_exec: /* 2 */
237: case TTYService_its: /* 3 */
238: break;
239: default:
240: raise(GAP3_serviceNotFound, 0);
241: /*NOTREACHED*/
242: }
243: duplexity = GAP3_fullduplex;/* services are allways fulldup */
244: break;
245: case GAP3_rs232c: /* maybe some day */
246: cp = &transports.sequence[0].GAP3_rs232c_case.commParams;
247: if (cp->accessDetail.designator == GAP3_directConn) {
248: duplexity = cp->accessDetail.GAP3_directConn_case.duplex;
249: servicetype = TTYService_sa; /* fake it */
250: break;
251: }
252: raise(GAP3_noCommunicationHardware, 0);
253: /*NOTREACHED*/
254: default:
255: raise(GAP3_illegalTransport, 0);
256: /*NOTREACHED*/
257: }
258: if (transports.sequence[1].designator != GAP3_teletype)
259: raise(GAP3_illegalTransport, 0);
260: /* ignore createTimeout */
261: /* ignore credentials and verifier */
262:
263: for (c1 = "pq"; *c1 != 0; c1++)
264: for (c2 = "0123456789abcdef"; *c2 != 0; c2++) {
265: sprintf(line, "/dev/pty%c%c", *c1, *c2);
266: pty = open(line, 2);
267: if (pty < 0) continue;
268: line[strlen("/dev/")] = 't';
269: t = open(line, 2);
270: if (t > 0) goto gotpty;
271: close(pty);
272: }
273: raise(GAP3_serviceTooBusy, 0);
274: /*NOTREACHED*/
275: gotpty:
276: getpeername(_serverConnection->fd, &who, &whosize);
277: host = wsname(who.sns_addr);
278: #ifdef DEBUG
279: BUGOUT("gotpty <%s> %d <%s>",line, pty, host);
280: #endif
281: ioctl(t, TIOCGETP, &b);
282: b.sg_flags = CRMOD|XTABS|ANYP;
283: ioctl(t, TIOCSETP, &b);
284: ioctl(pty, TIOCGETP, &b);
285: if (duplexity == GAP3_fullduplex)
286: b.sg_flags |= ECHO;
287: else
288: b.sg_flags &= ~ECHO;
289: ioctl(pty, TIOCSETP, &b);
290: /* we do the fork now so we can return failures as REPORTS */
291: pid = fork();
292: if (pid < 0) {
293: close(pty); close(t);
294: raise(GAP3_serviceTooBusy, 0);
295: /*NOTREACHED*/
296: }
297: else if (pid == 0) { /* in the execed fork */
298: sleep(1); /* let parent get ready for us */
299: close(_serverConnection->fd); /* close net */
300: close(pty);
301: dup2(t, 0);
302: dup2(t, 1);
303: dup2(t, 2);
304: if (t > 2) close(t);
305: envinit[0] = "TERM=network";
306: envinit[1] = (char*) 0;
307: mypid = getpid();
308: (void) ioctl( 0, TIOCSPGRP, (char *)&mypid );
309: (void) setpgrp(0, mypid);
310: #ifdef DEBUG
311: BUGOUT("about to exec /bin/login");
312: #endif
313: execl("/bin/login","login", "-h", host, 0);
314: #ifdef DEBUG
315: BUGOUT("exec of /bin/login failed");
316: #endif
317: perror("/bin/login");
318: exit(1);
319: /*NOTREACHED*/
320: }
321: close(t);
322: #ifdef DEBUG
323: BUGOUT("fork successful");
324: #endif
325: result.session[0] = pid;
326: return(result);
327: }
328:
329: jmp_buf childdiedbuf;
330:
331: /*
332: * Main loop. Select from pty and network, and
333: * hand data to telnet receiver finite state machine.
334: * Returns 0 on orderly shutdown, 1 on abnormal shutdown.
335: */
336: gaptelnet()
337: {
338: int on = 1;
339: char hostname[32];
340: int childdied();
341: fd_set ibits, obits;
342: register int c;
343: struct sphdr *si = (struct sphdr *)buf;
344: static struct timeval timeout = {600,0};
345: int keepalives = 0;
346: int i;
347:
348: #ifdef DEBUG
349: BUGOUT("gaptelnet net=%d,pty=%d",net,pty);
350: #endif
351: if (setjmp(childdiedbuf) != 0)
352: return(0); /* child died */
353: signal(SIGCHLD, childdied);
354: signal(SIGTSTP, SIG_IGN);
355: ioctl(net, FIONBIO, &on);
356: ioctl(pty, FIONBIO, &on);
357: (void) setpgrp(0, 0);
358:
359:
360: /*
361: * Show banner that getty never gave.
362: */
363: gethostname(hostname, sizeof (hostname));
364: sprintf(nfrontp, BANNER, hostname);
365: nfrontp += strlen(nfrontp);
366: /*
367: * Send status message indicating we're ready to go
368: */
369: changeSPPopts(net, GAPCTLnone, 1);
370: sendoobdata(GAPCTLmediumUp);
371: for (;;) {
372: #ifdef DEBUG
373: BUGOUT("looping in gaptelnet");
374: #endif
375: if (ncc < 0 && pcc < 0)
376: break;
377: FD_ZERO(&ibits);
378: FD_ZERO(&obits);
379: /*
380: * Never look for input if there's still
381: * stuff in the corresponding output buffer
382: */
383: if (nfrontp - nbackp || pcc > 0)
384: FD_SET(net, &obits);
385: else
386: FD_SET(pty, &ibits);
387: if (pfrontp - pbackp || ncc > 0)
388: FD_SET(pty, &obits);
389: else
390: FD_SET(net, &ibits);
391:
392: timeout.tv_sec = 14400; /* 4 hrs. */
393: timeout.tv_usec = 0;
394: if ((c = select(16, &ibits, &obits, 0, &timeout)) < 1) {
395: if (c < 0) {
396: if (errno != EINTR) {
397: sleep(5);
398: }
399: continue;
400: }
401: /* ASSERT(ibits == 0 && obits == 0); */
402: /* timeout means no activity for a long time */
403: #ifdef DEBUG
404: BUGOUT("timeout from select");
405: #endif
406: if (keepalives++ < 2) {
407: /* first time through send warning */
408: if (nfrontp == nbackp && pcc == 0) {
409: /* but only if not blocked on output */
410: #define WARNING "\r\n\007You've been idle much too long. Respond or log off.\r\n"
411: strcpy(nfrontp, WARNING);
412: nfrontp += sizeof(WARNING);
413: }
414: continue;
415: }
416: #ifdef DEBUG
417: BUGOUT("keepalive expired -- calling cleanup");
418: #endif
419: /* keepalive count has expired */
420: cleanup();
421: return(1);
422: }
423:
424: /*
425: * Something to read from the network...
426: */
427: if (FD_ISSET(net, &ibits)) {
428: ncc = read(net, buf, sizeof(buf));
429: #ifdef DEBUG
430: BUGOUT("read %d from net, cc=0%o,dt=0%o",
431: ncc-sizeof(struct sphdr), si->sp_cc, si->sp_dt);
432: #endif
433: if (ncc < 0 && errno == EWOULDBLOCK)
434: ncc = 0;
435: else if (ncc < sizeof(struct sphdr)) {
436: #ifdef DEBUG
437: BUGOUT("short read, %d. calling cleanup",ncc);
438: #endif
439: cleanup(); /* will probably fail or block */
440: return(1);
441: }
442: else if (si->sp_cc & SP_OB) {
443: #ifdef DEBUG
444: BUGOUT("Got OOB control 0%o",
445: (u_char) buf[sizeof(struct sphdr)]);
446: #endif
447: /* a status or OOB control */
448: switch ((u_char) buf[sizeof(struct sphdr)]) {
449: case GAPCTLinterrupt:
450: /* shove interrupt char in buffer */
451: interrupt();
452: break; /* from switch */
453: case GAPCTLareYouThere:
454: sendoobdata(GAPCTLiAmHere);
455: break; /* from switch */
456: default:
457: /* Ignore other controls instead of:
458: * sendoobdata(
459: * GAPCTLunexpectedRemoteBehavior);
460: */
461: break; /* from switch */
462: }
463: ncc = 0; /* no chars here */
464: }
465: else if (si->sp_dt==GAPCTLnone ||
466: si->sp_dt==0) {
467: /* the normal case */
468: /* N.B. the standard says dt should be 0300
469: * i.e. GAPCTLnone, but Interlisp CHAT
470: * generates 0, so we accept that too.
471: */
472: ncc -= sizeof(struct sphdr);
473: #ifdef DEBUG
474: BUGOUT("Now ncc == %d",ncc);
475: #endif
476: netip = buf + sizeof(struct sphdr);
477: keepalives = 0;
478: }
479: else if(si->sp_dt==GAPCTLcleanup) {
480: #ifdef DEBUG
481: BUGOUT("got CLEANUP packet. Done");
482: #endif
483: cleanup(); /* normal termination */
484: return(0);
485: }
486: else if (si->sp_dt==SPPSST_END) {
487: /* got premature termination */
488: quitquit(net, pty);
489: return(1);
490: }
491: else {
492: /* some other inband ctl */
493: #ifdef DEBUG
494: BUGOUT("ignoring IB packet, data = 0%o...",
495: (u_char) buf[sizeof(struct sphdr)]);
496: #endif
497: }
498: }
499:
500: /*
501: * Something to read from the pty...
502: */
503: if (FD_ISSET(pty, &ibits)) {
504: if (frametimeout > 0) sleep(frametimeout);
505: pcc = read(pty, ptyibuf, sizeof(ptyibuf));
506: #ifdef DEBUG
507: BUGOUT("read from pty %d",pcc);
508: #endif
509: if (pcc < 0 && errno == EWOULDBLOCK)
510: pcc = 0;
511: else if (pcc <= 0) {
512: #ifdef DEBUG
513: BUGOUT("short read from pty. Calling cleanup");
514: #endif
515: cleanup();
516: return(1); /* ?? abnormal termination */
517: }
518: ptyip = ptyibuf;
519: }
520:
521: while (pcc > 0) {
522: if ((&netobuf[sizeof(netobuf)] - nfrontp) < 2)
523: break;
524: *nfrontp++ = *ptyip++ & 0377; pcc--;
525: }
526: if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0)
527: netflush();
528: while (ncc > 0) {
529: if ((&ptyobuf[sizeof(ptyobuf)] - pfrontp) < 2) break;
530: *pfrontp++ = *netip++ & 0377;
531: ncc--;
532: }
533: if (FD_ISSET(pty, &obits) && (pfrontp - pbackp) > 0)
534: ptyflush();
535: }
536: /* we should never get to here */
537: #ifdef DEBUG
538: BUGOUT("broke out of for(;;) somehow. calling cleanup");
539: #endif
540: cleanup();
541: return(0);
542: }
543:
544: /*
545: * Send out of band data to other end of network
546: */
547: sendoobdata(value)
548: u_char value;
549: {
550: struct {
551: struct sphdr hdr;
552: char val;
553: } oob;
554: oob.hdr = our_sphdr;
555: oob.val = value;
556: #ifdef DEBUG
557: BUGOUT("sendoobdata 0%o",value);
558: #endif
559: send(net, &oob, sizeof(oob), MSG_OOB);
560: }
561:
562: /*
563: * Send interrupt to process on other side of pty.
564: * If it is in raw mode, just write NULL;
565: * otherwise, write intr char.
566: */
567: interrupt()
568: {
569: struct sgttyb b;
570: struct tchars tchars;
571:
572: ptyflush(); /* half-hearted */
573: ioctl(pty, TIOCGETP, &b);
574: if (b.sg_flags & RAW) {
575: *pfrontp++ = '\0';
576: return;
577: }
578: *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
579: '\177' : tchars.t_intrc;
580: }
581:
582: ptyflush()
583: {
584: register int n;
585:
586: if ((n = pfrontp - pbackp) > 0)
587: n = write(pty, pbackp, n);
588: #ifdef DEBUG
589: BUGOUT("ptyflush wrote %d",n);
590: #endif
591: if (n < 0)
592: return;
593: pbackp += n;
594: if (pbackp >= pfrontp) /* actually, > is an error */
595: pbackp = pfrontp = ptyobuf;
596: }
597:
598: netflush()
599: {
600: register int n;
601:
602: if ((n = nfrontp - nbackp) > 0) {
603: our_iovec[1].iov_len = ((n > SPPMAXDATA) ? SPPMAXDATA : n);
604: our_iovec[1].iov_base = nbackp;
605: n = writev(net, our_iovec, 2) - sizeof(struct sphdr);
606: }
607: #ifdef DEBUG
608: BUGOUT("netflush wrote %d",n);
609: if (our_iovec[0].iov_base != (char*)&our_sphdr)
610: BUGOUT("Oops: our_iovec clobbered");
611: BUGOUT("header: %d %d, %d %d %d %d %d %d",
612: our_sphdr.sp_cc, our_sphdr.sp_dt,
613: our_sphdr.sp_sid, our_sphdr.sp_did, our_sphdr.sp_seq,
614: our_sphdr.sp_ack, our_sphdr.sp_alo);
615: #endif
616: if (n < 0) {
617: if (errno == EWOULDBLOCK)
618: return;
619: /* should blow this guy away... */
620: return;
621: }
622: nbackp += n;
623: if (nbackp >= nfrontp) /* actually , > is an error */
624: nbackp = nfrontp = netobuf;
625: }
626:
627: /*
628: * handle receipt of an SPPSST_END packet
629: * This is currently an error, since client didn't send "cleanup" first
630: */
631: quitquit()
632: {
633: #ifdef DEBUG
634: BUGOUT("quitquit");
635: #endif
636: changeSPPopts(net, SPPSST_ENDREPLY, 1);
637: write(net, &our_sphdr, sizeof(our_sphdr));
638: sleep(3);
639:
640: rmut();
641: vhangup(); /* XXX */
642: shutdown(net, 1);
643: close(net);
644: }
645:
646: /*
647: * shut down the data connection for one reason or another
648: */
649: cleanup()
650: {
651: int fdmask;
652: struct timeval timeout;
653: struct sphdr *si = (struct sphdr *)buf;
654: int off = 0;
655:
656: signal(SIGCHLD, SIG_IGN);
657: sendoobdata(GAPCTLcleanup);
658: changeSPPopts(net, SPPSST_END, 1);
659: if (write(net, &our_sphdr, sizeof(our_sphdr)) >= 0) {
660: fdmask = 1<<net;
661: timeout.tv_sec = 10;
662: timeout.tv_usec = 0;
663: while (select(net+1,&fdmask,(int*)0, (int*)0, &timeout) > 0 &&
664: read(net,buf,sizeof(buf)) >= sizeof(struct sphdr)) {
665: #ifdef DEBUG
666: BUGOUT("cleanup -- got packet");
667: #endif
668: if ((!(si->sp_cc & SP_OB))
669: && (si->sp_dt == SPPSST_ENDREPLY ||
670: si->sp_dt == SPPSST_END)) {
671: changeSPPopts(net, SPPSST_ENDREPLY, 1);
672: write(net, &our_sphdr, sizeof(our_sphdr));
673: #ifdef DEBUG
674: BUGOUT("cleanup -- wrote ENDREPLY");
675: #endif
676: sleep(1);
677: changeSPPopts(net,0,0);
678: ioctl(net, FIONBIO, &off);
679: rmut();
680: vhangup(); /* XXX */
681: return;
682: }
683: /* loop: ignore everything except ENDREPLY */
684: fdmask = 1<<net;
685: timeout.tv_sec = 10;
686: timeout.tv_usec = 0;
687: }
688: /* timed out or read failed */
689: changeSPPopts(net, SPPSST_ENDREPLY, 1);
690: write(net, &our_sphdr, sizeof(our_sphdr)); /* try one more time */
691: sleep(1);
692: }
693: /* write failed or we timed out on read */
694: shutdown(net, 1);
695: close(net);
696: rmut();
697: vhangup(); /* XXX */
698: }
699:
700: /*
701: * SIGCHLD interrupt handler
702: */
703: childdied()
704: {
705: #ifdef DEBUG
706: BUGOUT("child died");
707: #endif
708: cleanup();
709: longjmp(childdiedbuf, -1);
710: }
711:
712: changeSPPopts(s, stream, eom)
713: int s; /* SPP socket */
714: u_char stream; /* datastream type */
715: char eom; /* Boolean EOM */
716: {
717: our_sphdr.sp_dt = stream;
718: our_sphdr.sp_cc = (eom ? SP_EM : 0);
719: }
720:
721:
722: #include <utmp.h>
723:
724: struct utmp wtmp;
725: char wtmpf[] = "/usr/adm/wtmp";
726: char utmp[] = "/etc/utmp";
727: #define SCPYN(a, b) strncpy(a, b, sizeof (a))
728: #define SCMPN(a, b) strncmp(a, b, sizeof (a))
729:
730: rmut()
731: {
732: register f;
733: int found = 0;
734:
735: f = open(utmp, 2);
736: if (f >= 0) {
737: while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) {
738: if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
739: continue;
740: lseek(f, -(long)sizeof (wtmp), 1);
741: SCPYN(wtmp.ut_name, "");
742: SCPYN(wtmp.ut_host, "");
743: time(&wtmp.ut_time);
744: write(f, (char *)&wtmp, sizeof (wtmp));
745: found++;
746: }
747: close(f);
748: }
749: if (found) {
750: f = open(wtmpf, 1);
751: if (f >= 0) {
752: SCPYN(wtmp.ut_line, line+5);
753: SCPYN(wtmp.ut_name, "");
754: SCPYN(wtmp.ut_host, "");
755: time(&wtmp.ut_time);
756: lseek(f, (long)0, 2);
757: write(f, (char *)&wtmp, sizeof (wtmp));
758: close(f);
759: }
760: }
761: chmod(line, 0666);
762: chown(line, 0, 0);
763: line[strlen("/dev/")] = 'p';
764: chmod(line, 0666);
765: chown(line, 0, 0);
766: }
767:
768: /*
769: * Convert network-format xns address
770: * to ascii
771: * --Replace this with a clearinghouse name lookup someday.
772: */
773: char *
774: wsname(addr)
775: struct ns_addr addr;
776: {
777: static char b[50];
778: char temp[15];
779: char *t;
780: union {
781: u_short y_net[2];
782: u_long y_long;
783: } netvalue;
784:
785:
786: /* net */
787: netvalue.y_net[0] = addr.x_net.s_net[0];
788: netvalue.y_net[1] = addr.x_net.s_net[1];
789:
790: /* build a host number */
791: sprintf(temp,"%02X%02X%02X%02X%02X%02X",
792: addr.x_host.c_host[0],
793: addr.x_host.c_host[1],
794: addr.x_host.c_host[2],
795: addr.x_host.c_host[3],
796: addr.x_host.c_host[4],
797: addr.x_host.c_host[5]);
798: /* strip leading zeros */
799: for (t = temp; *t == '0'; t++)
800: ;
801: sprintf(b, "%lXH.%sH", ntohl(netvalue.y_long),t);
802: return (b);
803: }
804:
805: #ifdef DEBUG
806: BUGOUT(str,a,b,c,d,e,f,g,h)
807: char *str;
808: {
809: FILE *fd;
810: fd = fopen("/tmp/GAP3d.log","a");
811: fprintf(fd,str,a,b,c,d,e,f,g,h);
812: putc('\n',fd);
813: fclose(fd);
814: }
815: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.