📄 gaptelnetd.c
字号:
#ifndef lintstatic char RCSid[] = "$Header: gaptelnetd.c,v 2.4 86/10/20 12:00:04 root Exp $";#endif/* * server for GAP-style (TransportObject=server,teletype) telnet connections * Note that we support only GAP version 3 *//* $Log: gaptelnetd.c,v $ * Revision 2.4 86/10/20 12:00:04 root * Fix bug (finally) causing delayed close of connections when UNIX logs out. * * Revision 2.3 86/10/11 12:39:53 jqj * Fixes from Bill Jackson: put lower fork in correct tty and process * group -- required for real 4.3 release. * * Revision 2.2 86/09/12 09:50:28 jqj * Fixes for 4.3bsd: * 1/ added setpgrp(0,0) to make csh happy (symptom was that chat * sessions would work only if default shell was /bin/sh). * 2/ change to FD_ macros since ibits and obits can now be more than * 32 bits long (we could have more than 32 open descriptors in principal). * * Revision 2.1 86/05/16 11:04:00 jqj * fix to correspond to new semantics for enumerations (global) * * Revision 2.0 85/11/21 07:23:06 jqj * 4.3BSD standard release * * Revision 1.3 85/11/21 06:53:22 jqj * symbolic values for connection type * * Revision 1.2 85/11/08 17:17:13 bill * version on bullwinkle * * Revision 1.3 85/08/05 09:58:00 jqj * fixed for Interlisp -- data from Interlisp appears with dt==0 (wrong!) * also, Interlisp trys to connect to a tty rather than a ttyHost. * increased inactivity timeout to 4 hrs * * Revision 1.2 85/05/23 06:22:18 jqj * *** empty log message *** * * Revision 1.1 85/05/22 09:46:52 jqj * Initial revision */#include <stdio.h>#include <signal.h>#include <sgtty.h>#include <sys/types.h>#include <sys/time.h>#include <sys/uio.h>#include <sys/socket.h>#include <netns/ns.h>#include <netns/idp.h>#include <netns/sp.h>#include <sys/wait.h>#include <xnscourier/realcourierconnection.h>#include "GAP3.h"#include "gapcontrols.h"#include <xnscourier/except.h>#include <errno.h>#define BELL '\07'#define BANNER "\r\n\r\n4.3 BSD UNIX (%s)\r\n\r\r\n\r"int pty, net;extern CourierConnection *_serverConnection;char buf[sizeof(struct sphdr)+SPPMAXDATA];struct sphdr our_sphdr;struct iovec our_iovec[2] = {{((caddr_t)&our_sphdr), sizeof(our_sphdr)}};/* * I/O data buffers, pointers, and counters. */char ptyibuf[512], *ptyip = ptyibuf;char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;char *netip = buf;char netobuf[512], *nfrontp = netobuf, *nbackp = netobuf;int pcc, ncc;char line[12];extern char **environ;extern int errno;char *envinit[3];/* * session parameters */Cardinal frametimeout; /* 0 or time in seconds to wait *//* * This modified version of the server is necessary since GAP specifies * that the telnet data-transfer session occurs after the RPC to create * it has returned! */Server(skipcount,skippedwords) int skipcount; Unspecified skippedwords[];{ Cardinal _procedure; register Unspecified *_buf; LongCardinal programnum; Cardinal versionnum; Cardinal _n;#ifdef DEBUG BUGOUT("Server: %d %d",skipcount,skippedwords);#endif for (;;) { _buf = ReceiveCallMessage(&_procedure, skipcount, skippedwords); DURING switch (_procedure) { case 3: server_GAP3_Delete(_buf); break; case 2: server_GAP3_Create(_buf); net = _serverConnection->fd; gaptelnet(); /* returns on connection close */ break; case 0: server_GAP3_Reset(_buf); break; default: NoSuchProcedureValue("GAP", _procedure); break; } HANDLER { Deallocate(_buf); switch (Exception.Code) { case GAP3_serviceNotFound: case GAP3_userNotAuthorized: case GAP3_userNotAuthenticated: case GAP3_serviceTooBusy: case GAP3_terminalAddressInvalid: case GAP3_terminalAddressInUse: case GAP3_controllerDoesNotExist: case GAP3_controllerAlreadyExists: case GAP3_gapCommunicationError: case GAP3_gapNotExported: case GAP3_bugInGAPCode: case GAP3_tooManyGateStreams: case GAP3_inconsistentParams: case GAP3_transmissionMediumUnavailable: case GAP3_dialingHardwareProblem: case GAP3_noDialingHardware: case GAP3_badAddressFormat: case GAP3_mediumConnectFailed: case GAP3_illegalTransport: case GAP3_noCommunicationHardware: case GAP3_unimplemented: _buf = Allocate(0); SendAbortMessage(Exception.Code-ERROR_OFFSET, 0, _buf); break; default: _buf = Allocate(0); SendRejectMessage(unspecifiedError, 0, _buf); break; } } END_HANDLER; Deallocate(_buf); for (;;) { skipcount = LookAheadCallMsg(&programnum, &versionnum, skippedwords); if (skipcount < 0) return(0); /* timed out */ if (programnum != 3 || versionnum != 3) ExecCourierProgram(programnum, versionnum, skipcount, skippedwords); } /* loop if can't exec that program */ }}voidGAP3_Delete(session) GAP3_SessionHandle session; {}voidGAP3_Reset(){}GAP3_CreateResultsGAP3_Create(conn, BDTproc, sessionparams, transports, createTimeout, credentials, verifier) CourierConnection *conn; int BDTproc; GAP3_SessionParameterObject sessionparams; struct {Cardinal length; GAP3_TransportObject *sequence; } transports; GAP3_WaitTime createTimeout; Authentication1_Credentials credentials; Authentication1_Verifier verifier;{ GAP3_CreateResults result; char *c1, *c2, *host; int t, pid, mypid; struct sgttyb b; char *wsname(); struct sockaddr_ns who; int whosize = sizeof(who); LongCardinal servicetype; GAP3_CommParamObject *cp; GAP3_Duplexity duplexity; /* fullDuplex, halfDuplex */#ifdef DEBUG BUGOUT("CREATE");#endif switch (sessionparams.designator) { case GAP3_oldTty: case GAP3_oldTtyHost: frametimeout = sessionparams.GAP3_oldTtyHost_case.frameTimeout/1000; /* could set other parameters here */ break; case GAP3_tty: case GAP3_ttyHost: frametimeout = sessionparams.GAP3_ttyHost_case.frameTimeout/1000; /* could set other parameters here */ break; default: raise(GAP3_unimplemented, 0); /*NOTREACHED*/ } if (transports.length != 2) { raise(GAP3_illegalTransport); /*NOTREACHED*/ } switch (transports.sequence[0].designator) { case GAP3_service: servicetype = transports.sequence[0].GAP3_service_case.id; switch (servicetype) { case TTYService_any: /* 0 */ servicetype = TTYService_sa; case TTYService_sa: /* 1 */ case TTYService_exec: /* 2 */ case TTYService_its: /* 3 */ break; default: raise(GAP3_serviceNotFound, 0); /*NOTREACHED*/ } duplexity = GAP3_fullduplex;/* services are allways fulldup */ break; case GAP3_rs232c: /* maybe some day */ cp = &transports.sequence[0].GAP3_rs232c_case.commParams; if (cp->accessDetail.designator == GAP3_directConn) { duplexity = cp->accessDetail.GAP3_directConn_case.duplex; servicetype = TTYService_sa; /* fake it */ break; } raise(GAP3_noCommunicationHardware, 0); /*NOTREACHED*/ default: raise(GAP3_illegalTransport, 0); /*NOTREACHED*/ } if (transports.sequence[1].designator != GAP3_teletype) raise(GAP3_illegalTransport, 0); /* ignore createTimeout */ /* ignore credentials and verifier */ for (c1 = "pq"; *c1 != 0; c1++) for (c2 = "0123456789abcdef"; *c2 != 0; c2++) { sprintf(line, "/dev/pty%c%c", *c1, *c2); pty = open(line, 2); if (pty < 0) continue; line[strlen("/dev/")] = 't'; t = open(line, 2); if (t > 0) goto gotpty; close(pty); } raise(GAP3_serviceTooBusy, 0); /*NOTREACHED*/ gotpty: getpeername(_serverConnection->fd, &who, &whosize); host = wsname(who.sns_addr);#ifdef DEBUG BUGOUT("gotpty <%s> %d <%s>",line, pty, host);#endif ioctl(t, TIOCGETP, &b); b.sg_flags = CRMOD|XTABS|ANYP; ioctl(t, TIOCSETP, &b); ioctl(pty, TIOCGETP, &b); if (duplexity == GAP3_fullduplex) b.sg_flags |= ECHO; else b.sg_flags &= ~ECHO; ioctl(pty, TIOCSETP, &b); /* we do the fork now so we can return failures as REPORTS */ pid = fork(); if (pid < 0) { close(pty); close(t); raise(GAP3_serviceTooBusy, 0); /*NOTREACHED*/ } else if (pid == 0) { /* in the execed fork */ sleep(1); /* let parent get ready for us */ close(_serverConnection->fd); /* close net */ close(pty); dup2(t, 0); dup2(t, 1); dup2(t, 2); if (t > 2) close(t); envinit[0] = "TERM=network"; envinit[1] = (char*) 0; mypid = getpid(); (void) ioctl( 0, TIOCSPGRP, (char *)&mypid ); (void) setpgrp(0, mypid);#ifdef DEBUG BUGOUT("about to exec /bin/login");#endif execl("/bin/login","login", "-h", host, 0);#ifdef DEBUG BUGOUT("exec of /bin/login failed");#endif perror("/bin/login"); exit(1); /*NOTREACHED*/ } close(t);#ifdef DEBUG BUGOUT("fork successful");#endif result.session[0] = pid; return(result);}jmp_buf childdiedbuf;/* * Main loop. Select from pty and network, and * hand data to telnet receiver finite state machine. * Returns 0 on orderly shutdown, 1 on abnormal shutdown. */gaptelnet(){ int on = 1; char hostname[32]; int childdied(); fd_set ibits, obits; register int c; struct sphdr *si = (struct sphdr *)buf; static struct timeval timeout = {600,0}; int keepalives = 0; int i;#ifdef DEBUG BUGOUT("gaptelnet net=%d,pty=%d",net,pty);#endif if (setjmp(childdiedbuf) != 0) return(0); /* child died */ signal(SIGCHLD, childdied); signal(SIGTSTP, SIG_IGN); ioctl(net, FIONBIO, &on); ioctl(pty, FIONBIO, &on); (void) setpgrp(0, 0); /* * Show banner that getty never gave. */ gethostname(hostname, sizeof (hostname)); sprintf(nfrontp, BANNER, hostname); nfrontp += strlen(nfrontp); /* * Send status message indicating we're ready to go */ changeSPPopts(net, GAPCTLnone, 1); sendoobdata(GAPCTLmediumUp); for (;;) {#ifdef DEBUG BUGOUT("looping in gaptelnet");#endif if (ncc < 0 && pcc < 0) break; FD_ZERO(&ibits); FD_ZERO(&obits); /* * Never look for input if there's still * stuff in the corresponding output buffer */ if (nfrontp - nbackp || pcc > 0) FD_SET(net, &obits); else FD_SET(pty, &ibits); if (pfrontp - pbackp || ncc > 0) FD_SET(pty, &obits); else FD_SET(net, &ibits); timeout.tv_sec = 14400; /* 4 hrs. */ timeout.tv_usec = 0; if ((c = select(16, &ibits, &obits, 0, &timeout)) < 1) { if (c < 0) { if (errno != EINTR) { sleep(5); } continue; } /* ASSERT(ibits == 0 && obits == 0); */ /* timeout means no activity for a long time */#ifdef DEBUG BUGOUT("timeout from select");#endif if (keepalives++ < 2) { /* first time through send warning */ if (nfrontp == nbackp && pcc == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -