📄 gaptelnetd.c
字号:
/* but only if not blocked on output */#define WARNING "\r\n\007You've been idle much too long. Respond or log off.\r\n" strcpy(nfrontp, WARNING); nfrontp += sizeof(WARNING); } continue; }#ifdef DEBUG BUGOUT("keepalive expired -- calling cleanup");#endif /* keepalive count has expired */ cleanup(); return(1); } /* * Something to read from the network... */ if (FD_ISSET(net, &ibits)) { ncc = read(net, buf, sizeof(buf));#ifdef DEBUG BUGOUT("read %d from net, cc=0%o,dt=0%o", ncc-sizeof(struct sphdr), si->sp_cc, si->sp_dt);#endif if (ncc < 0 && errno == EWOULDBLOCK) ncc = 0; else if (ncc < sizeof(struct sphdr)) {#ifdef DEBUG BUGOUT("short read, %d. calling cleanup",ncc);#endif cleanup(); /* will probably fail or block */ return(1); } else if (si->sp_cc & SP_OB) {#ifdef DEBUG BUGOUT("Got OOB control 0%o", (u_char) buf[sizeof(struct sphdr)]);#endif /* a status or OOB control */ switch ((u_char) buf[sizeof(struct sphdr)]) { case GAPCTLinterrupt: /* shove interrupt char in buffer */ interrupt(); break; /* from switch */ case GAPCTLareYouThere: sendoobdata(GAPCTLiAmHere); break; /* from switch */ default: /* Ignore other controls instead of: * sendoobdata( * GAPCTLunexpectedRemoteBehavior); */ break; /* from switch */ } ncc = 0; /* no chars here */ } else if (si->sp_dt==GAPCTLnone || si->sp_dt==0) { /* the normal case */ /* N.B. the standard says dt should be 0300 * i.e. GAPCTLnone, but Interlisp CHAT * generates 0, so we accept that too. */ ncc -= sizeof(struct sphdr);#ifdef DEBUG BUGOUT("Now ncc == %d",ncc);#endif netip = buf + sizeof(struct sphdr); keepalives = 0; } else if(si->sp_dt==GAPCTLcleanup) {#ifdef DEBUG BUGOUT("got CLEANUP packet. Done");#endif cleanup(); /* normal termination */ return(0); } else if (si->sp_dt==SPPSST_END) { /* got premature termination */ quitquit(net, pty); return(1); } else { /* some other inband ctl */#ifdef DEBUG BUGOUT("ignoring IB packet, data = 0%o...", (u_char) buf[sizeof(struct sphdr)]);#endif } } /* * Something to read from the pty... */ if (FD_ISSET(pty, &ibits)) { if (frametimeout > 0) sleep(frametimeout); pcc = read(pty, ptyibuf, sizeof(ptyibuf));#ifdef DEBUG BUGOUT("read from pty %d",pcc);#endif if (pcc < 0 && errno == EWOULDBLOCK) pcc = 0; else if (pcc <= 0) {#ifdef DEBUG BUGOUT("short read from pty. Calling cleanup");#endif cleanup(); return(1); /* ?? abnormal termination */ } ptyip = ptyibuf; } while (pcc > 0) { if ((&netobuf[sizeof(netobuf)] - nfrontp) < 2) break; *nfrontp++ = *ptyip++ & 0377; pcc--; } if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0) netflush(); while (ncc > 0) { if ((&ptyobuf[sizeof(ptyobuf)] - pfrontp) < 2) break; *pfrontp++ = *netip++ & 0377; ncc--; } if (FD_ISSET(pty, &obits) && (pfrontp - pbackp) > 0) ptyflush(); } /* we should never get to here */#ifdef DEBUG BUGOUT("broke out of for(;;) somehow. calling cleanup");#endif cleanup(); return(0);}/* * Send out of band data to other end of network */sendoobdata(value) u_char value;{ struct { struct sphdr hdr; char val; } oob; oob.hdr = our_sphdr; oob.val = value;#ifdef DEBUG BUGOUT("sendoobdata 0%o",value);#endif send(net, &oob, sizeof(oob), MSG_OOB);}/* * Send interrupt to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write intr char. */interrupt(){ struct sgttyb b; struct tchars tchars; ptyflush(); /* half-hearted */ ioctl(pty, TIOCGETP, &b); if (b.sg_flags & RAW) { *pfrontp++ = '\0'; return; } *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ? '\177' : tchars.t_intrc;}ptyflush(){ register int n; if ((n = pfrontp - pbackp) > 0) n = write(pty, pbackp, n);#ifdef DEBUG BUGOUT("ptyflush wrote %d",n);#endif if (n < 0) return; pbackp += n; if (pbackp >= pfrontp) /* actually, > is an error */ pbackp = pfrontp = ptyobuf;}netflush(){ register int n; if ((n = nfrontp - nbackp) > 0) { our_iovec[1].iov_len = ((n > SPPMAXDATA) ? SPPMAXDATA : n); our_iovec[1].iov_base = nbackp; n = writev(net, our_iovec, 2) - sizeof(struct sphdr); }#ifdef DEBUG BUGOUT("netflush wrote %d",n); if (our_iovec[0].iov_base != (char*)&our_sphdr) BUGOUT("Oops: our_iovec clobbered"); BUGOUT("header: %d %d, %d %d %d %d %d %d", our_sphdr.sp_cc, our_sphdr.sp_dt, our_sphdr.sp_sid, our_sphdr.sp_did, our_sphdr.sp_seq, our_sphdr.sp_ack, our_sphdr.sp_alo);#endif if (n < 0) { if (errno == EWOULDBLOCK) return; /* should blow this guy away... */ return; } nbackp += n; if (nbackp >= nfrontp) /* actually , > is an error */ nbackp = nfrontp = netobuf;}/* * handle receipt of an SPPSST_END packet * This is currently an error, since client didn't send "cleanup" first */quitquit(){#ifdef DEBUG BUGOUT("quitquit");#endif changeSPPopts(net, SPPSST_ENDREPLY, 1); write(net, &our_sphdr, sizeof(our_sphdr)); sleep(3); rmut(); vhangup(); /* XXX */ shutdown(net, 1); close(net);}/* * shut down the data connection for one reason or another */cleanup(){ int fdmask; struct timeval timeout; struct sphdr *si = (struct sphdr *)buf; int off = 0; signal(SIGCHLD, SIG_IGN); sendoobdata(GAPCTLcleanup); changeSPPopts(net, SPPSST_END, 1); if (write(net, &our_sphdr, sizeof(our_sphdr)) >= 0) { fdmask = 1<<net; timeout.tv_sec = 10; timeout.tv_usec = 0; while (select(net+1,&fdmask,(int*)0, (int*)0, &timeout) > 0 && read(net,buf,sizeof(buf)) >= sizeof(struct sphdr)) {#ifdef DEBUG BUGOUT("cleanup -- got packet");#endif if ((!(si->sp_cc & SP_OB)) && (si->sp_dt == SPPSST_ENDREPLY || si->sp_dt == SPPSST_END)) { changeSPPopts(net, SPPSST_ENDREPLY, 1); write(net, &our_sphdr, sizeof(our_sphdr));#ifdef DEBUG BUGOUT("cleanup -- wrote ENDREPLY");#endif sleep(1); changeSPPopts(net,0,0); ioctl(net, FIONBIO, &off); rmut(); vhangup(); /* XXX */ return; } /* loop: ignore everything except ENDREPLY */ fdmask = 1<<net; timeout.tv_sec = 10; timeout.tv_usec = 0; } /* timed out or read failed */ changeSPPopts(net, SPPSST_ENDREPLY, 1); write(net, &our_sphdr, sizeof(our_sphdr)); /* try one more time */ sleep(1); } /* write failed or we timed out on read */ shutdown(net, 1); close(net); rmut(); vhangup(); /* XXX */}/* * SIGCHLD interrupt handler */childdied(){#ifdef DEBUG BUGOUT("child died");#endif cleanup(); longjmp(childdiedbuf, -1);}changeSPPopts(s, stream, eom) int s; /* SPP socket */ u_char stream; /* datastream type */ char eom; /* Boolean EOM */{ our_sphdr.sp_dt = stream; our_sphdr.sp_cc = (eom ? SP_EM : 0);}#include <utmp.h>struct utmp wtmp;char wtmpf[] = "/usr/adm/wtmp";char utmp[] = "/etc/utmp";#define SCPYN(a, b) strncpy(a, b, sizeof (a))#define SCMPN(a, b) strncmp(a, b, sizeof (a))rmut(){ register f; int found = 0; f = open(utmp, 2); if (f >= 0) { while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) { if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) continue; lseek(f, -(long)sizeof (wtmp), 1); SCPYN(wtmp.ut_name, ""); SCPYN(wtmp.ut_host, ""); time(&wtmp.ut_time); write(f, (char *)&wtmp, sizeof (wtmp)); found++; } close(f); } if (found) { f = open(wtmpf, 1); if (f >= 0) { SCPYN(wtmp.ut_line, line+5); SCPYN(wtmp.ut_name, ""); SCPYN(wtmp.ut_host, ""); time(&wtmp.ut_time); lseek(f, (long)0, 2); write(f, (char *)&wtmp, sizeof (wtmp)); close(f); } } chmod(line, 0666); chown(line, 0, 0); line[strlen("/dev/")] = 'p'; chmod(line, 0666); chown(line, 0, 0);}/* * Convert network-format xns address * to ascii * --Replace this with a clearinghouse name lookup someday. */char *wsname(addr) struct ns_addr addr;{ static char b[50]; char temp[15]; char *t; union { u_short y_net[2]; u_long y_long; } netvalue; /* net */ netvalue.y_net[0] = addr.x_net.s_net[0]; netvalue.y_net[1] = addr.x_net.s_net[1]; /* build a host number */ sprintf(temp,"%02X%02X%02X%02X%02X%02X", addr.x_host.c_host[0], addr.x_host.c_host[1], addr.x_host.c_host[2], addr.x_host.c_host[3], addr.x_host.c_host[4], addr.x_host.c_host[5]); /* strip leading zeros */ for (t = temp; *t == '0'; t++) ; sprintf(b, "%lXH.%sH", ntohl(netvalue.y_long),t); return (b);}#ifdef DEBUGBUGOUT(str,a,b,c,d,e,f,g,h) char *str;{ FILE *fd; fd = fopen("/tmp/GAP3d.log","a"); fprintf(fd,str,a,b,c,d,e,f,g,h); putc('\n',fd); fclose(fd);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -