📄 ckucon.c
字号:
else /* Otherwise */ switch (inesc) { /* enter state switcher */ case ES_NORMAL: /* NORMAL state */ if (c == ESC) /* Got an ESC */ inesc = ES_GOTESC; /* Change state to GOTESC */ break; /* Otherwise stay in NORMAL state */ case ES_GOTESC: /* GOTESC state */ if (c == '[') /* Left bracket after ESC is CSI */ inesc = ES_GOTCSI; /* Change to GOTCSI state */ else if (c == 'P' || (c > 0134 && c < 0140)) { /* P, [, ^, or _ */ inesc = ES_STRING; /* Switch to STRING-absorption state */#ifdef CK_APC if (c == '_' && pid == 0 && /* APC handled in child only */ (apcstatus & APC_ON)) { /* and only if not disabled. */ debug(F100,"CONNECT APC begin","",0); apcactive = APC_REMOTE; /* Set APC-Active flag */ apclength = 0; /* and reset APC buffer pointer */ }#endif /* CK_APC */ } else if (c > 057 && c < 0177) /* Final character '0' thru '~' */ inesc = ES_NORMAL; /* Back to normal */ else if (c != ESC) /* ESC in an escape sequence... */ inesc = ES_ESCSEQ; /* starts a new escape sequence */ break; /* Intermediate or ignored ctrl char */ case ES_ESCSEQ: /* ESCSEQ -- in an escape sequence */ if (c > 057 && c < 0177) /* Final character '0' thru '~' */ inesc = ES_NORMAL; /* Return to NORMAL state. */ else if (c == ESC) /* ESC ... */ inesc = ES_GOTESC; /* starts a new escape sequence */ break; /* Intermediate or ignored ctrl char */ case ES_GOTCSI: /* GOTCSI -- In a control sequence */ if (c > 077 && c < 0177) /* Final character '@' thru '~' */ inesc = ES_NORMAL; /* Return to NORMAL. */ else if (c == ESC) /* ESC ... */ inesc = ES_GOTESC; /* starts over. */ break; /* Intermediate or ignored ctrl char */ case ES_STRING: /* Inside a string */ if (c == ESC) /* ESC may be 1st char of terminator */ inesc = ES_TERMIN; /* Go see. */#ifdef CK_APC else if (apcactive && (apclength < apcbuflen)) /* If in APC, */ apcbuf[apclength++] = c; /* deposit this character. */ else { /* Buffer overrun */ apcactive = 0; /* Discard what we got */ apclength = 0; /* and go back to normal */ apcbuf[0] = 0; /* Not pretty, but what else */ inesc = ES_NORMAL; /* can we do? (ST might not come) */ }#endif /* CK_APC */ break; /* Absorb all other characters. */ case ES_TERMIN: /* May have a string terminator */ if (c == '\\') { /* which must be backslash */ inesc = ES_NORMAL; /* If so, back to NORMAL */#ifdef CK_APC if (apcactive) { /* If it was an APC string, */ debug(F101,"CONNECT APC terminated","",c); apcbuf[apclength] = NUL; /* terminate it and then ... */ return(1); }#endif /* CK_APC */ } else { /* Otherwise */ inesc = ES_STRING; /* Back to string absorption. */#ifdef CK_APC if (apcactive && (apclength+1 < apcbuflen)) { /* In APC string */ apcbuf[apclength++] = ESC; /* deposit the Esc character */ apcbuf[apclength++] = c; /* and this character too */ }#endif /* CK_APC */ } } return(0);}#endif /* NOESCSEQ *//* Connect state parent/child communication signal handlers *//* Routines used by the child process */static intpipemsg(n) int n; { /* Send message ID to parent */ int code = n & 255; return(write(xpipe[1], &code, sizeof(code)));}/* Environment pointer for CK_FORK_SIG signal handling in child... */#ifdef CK_POSIX_SIGstatic sigjmp_buf sig_env;#elsestatic jmp_buf sig_env;#endif /* CK_POSIX_SIG */static SIGTYP /* CK_FORK_SIG handling in child ... */forkint(foo) int foo; { /* It is important to disable CK_FORK_SIG before longjmp */ signal(CK_FORK_SIG, SIG_IGN); /* Set to ignore CK_FORK_SIG */ debug(F100,"CONNECT forkint - CK_FORK_SIG", "", 0); /* Force return from ck_sndmsg() */ cklongjmp(sig_env, 1); /* NOTREACHED */}static VOIDck_sndmsg() { /* Executed by child only ... */ debug(F100,"CONNECT ck_sndmsg, active", "", active); if (#ifdef CK_POSIX_SIG sigsetjmp(sig_env,1)#else setjmp(sig_env)#endif /* CK_POSIX_SIG */ == 0) { debug(F100,"CONNECT ck_sndmsg signaling parent","",0); signal(CK_FORK_SIG, forkint); /* Set up signal handler */ kill(parent_id, CK_FORK_SIG); /* Kick the parent */ debug(F100,"ck_sndmsg pausing","",0); for (;;) pause(); /* Wait for CK_FORK_SIG or SIGKILL */ /* NOTREACHED */ } /* We come here from forkint() via [sig]cklongjmp(sig_env,1) */ debug(F100,"CONNECT ck_sndmsg is parent - returning", "", 0);}/* Routines used by the parent process */#ifdef CK_POSIX_SIG /* Environment pointer for CONNECT errors */static sigjmp_buf con_env;#elsestatic jmp_buf con_env;#endif /* CK_POSIX_SIG *//* pipeint() handles CK_FORK_SIG signals from the lower (port) fork. It reads a function code from the pipe that connects the two forks, then reads additional data from the pipe, then handles it.*/static SIGTYPpipeint(arg) int arg; { /* Dummy argument */ int code, cx, x, i /* , n */ ;#ifndef NOCCTRAP extern ckjmpbuf cmjbuf;#endif /* NOCCTRAP */ /* IMPORTANT: At this point, the child fork is waiting for CK_FORK_SIG (eventually for SIGKILL) inside of ck_sndmsg(). So we can't get any subsequent CK_FORK_SIG from child before we send it CK_FORK_SIG. */ signal(CK_FORK_SIG, SIG_IGN); /* Ignore CK_FORK_SIG now */ debug(F101,"CONNECT pipeint arg","",arg); read(xpipe[0], &code, sizeof(code)); /* Get function code from pipe */ debug(F101,"CONNECT pipeint code","",code); cx = code & 255; /* 8-bit version of function code */#ifndef NOCCTRAP#ifndef NOICP#define USECCJMPBUF#endif /* NOICP */#endif /* NOCCTRAP *//* Read info passed back up to us by the lower fork, depending on the function requested. The same number of items must be read from the pipe in the same order as the lower fork put them there. Trying to read something that's not there makes the program hang uninterruptibly. Pay close attention -- notice how we fall through some of the cases rather than break; that's deliberate.*/ switch (cx) {#ifdef CK_TRIGGER case CEV_TRI: /* Trigger string */ debug(F100,"CONNECT trigger","",0); read(xpipe[0], (char *)&i, sizeof(i)); /* Trigger index */ debug(F101,"CONNECT trigger index","",i); makestr(&triggerval,tt_trigger[i]); /* Make a copy of the trigger */ debug(F110,"CONNECT triggerval",triggerval,0); read(xpipe[0], (char *)&ibc, sizeof(ibc)); /* Copy child's */ debug(F101,"CONNECT trigger ibc (upper)","",ibc); /* input buffer. */ if (ibc > 0) { read(xpipe[0], (char *)&ibp, sizeof(ibp)); read(xpipe[0], ibp, ibc); } /* Fall thru... */#endif /* CK_TRIGGER */ case CEV_HUP:/* The CEV_HUP case is executed when the other side has hung up on us. In some cases, this happens before we have had a chance to execute the setjmp(con_env,1) call, and in that case we'd better not take the longjmp! A good example is when you TELNET to port 13 on the local host; it prints its asctime() string (26 chars) and then closes the connection.*/#ifdef CK_TRIGGER if (cx == CEV_TRI) sjval = CEV_TRI; /* Set global variable. */ else#endif /* CK_TRIGGER */ sjval = CEV_HUP; if (jbset) { /* jmp_buf is initialized */ cklongjmp(con_env,sjval); /* so do the right thing. */ } else { int x = 0;#ifdef USECCJMPBUF /* jmp_buf not init'd yet a close approximation... */#ifdef CK_TRIGGER if (cx == CEV_HUP)#endif /* CK_TRIGGER */ ttclos(0); /* Close our end of the connection */ if (pid) { debug(F101,"CONNECT trigger killing pid","",pid);#ifdef BEOSORBEBOX { long ret_val; x = kill(pid,SIGKILLTHR); /* Kill lower fork */ wait_for_thread (pid, &ret_val); }#else#ifdef Plan9 x = kill(pid, SIGKILL); /* (should always use this really) */#else x = kill(pid,9); /* Kill lower fork (history) */#endif /* Plan9 */ wait((WAIT_T *)0); /* Wait till gone. */ if (x < 0) { printf("ERROR: Failure to kill pid %ld: %s, errno=%d\n", (long) pid, ck_errstr(), errno); debug(F111,"CONNECT error killing stale pid", ck_errstr(),errno); } pid = (PID_T) 0;#endif /* BEOSORBEBOX */ } conres(); /* Reset the console. */ if (!quiet) { printf("\r\n(Back at %s)\r\n", *myhost ? myhost :#ifdef UNIX "local UNIX system"#else "local system"#endif /* UNIX */ ); } what = W_NOTHING; /* So console modes are set right. */ printf("\r\n"); /* prevent prompt-stomping */ cklongjmp(cmjbuf,0); /* Do what the Ctrl-C handler does */#else printf("\r\nLongjump failure - fatal\r\n"); doexit(GOOD_EXIT,-1); /* Better than dumping core... */#endif /* USECCJMPBUF */ }#ifdef USECCJMPBUF#undef USECCJMPBUF#endif /* USECCJMPBUF */ case CEV_DUP: /* Child sends duplex change */ read(xpipe[0], (char *)&duplex, sizeof(duplex)); debug(F101,"CONNECT pipeint duplex","",duplex); break;#ifdef TNCODE case CEV_MEBIN: /* Child sends me_binary change */ read(xpipe[0], (char *)&TELOPT_ME(TELOPT_BINARY), sizeof(TELOPT_ME(TELOPT_BINARY)) ); debug(F101,"CONNECT pipeint me_binary","",TELOPT_ME(TELOPT_BINARY)); break; case CEV_UBIN: /* Child sends u_binary change */ read(xpipe[0], (char *)&TELOPT_U(TELOPT_BINARY), sizeof(TELOPT_U(TELOPT_BINARY)) ); debug(F101,"CONNECT pipeint u_binary","",TELOPT_U(TELOPT_BINARY)); break;#endif /* TNCODE */#ifdef CK_APC case CEV_AUL: /* Autoupload */ justone = 1; debug(F100,"CONNECT autoupload at parent","",0);#ifdef CK_AUTODL case CEV_ADL: /* Autodownload */ apcactive = APC_LOCAL; if (!justone) debug(F100,"CONNECT autodownload at parent","",0); /* Copy child's Kermit packet if any */ read(xpipe[0], (char *)&x, sizeof(x)); debug(F101,"CONNECT trigger ibc (upper)","",ibc); if (x > 0) read(xpipe[0], (char *)ksbuf, x+1);#endif /* CK_AUTODL */ case CEV_APC: /* Application Program Command */ read(xpipe[0], (char *)&apclength, sizeof(apclength)); read(xpipe[0], apcbuf, apclength+1); /* Include trailing zero byte */ debug(F111,"CONNECT APC at parent",apcbuf,apclength); read(xpipe[0], (char *)&ibc, sizeof(ibc)); /* Copy child's */ if (ibc > 0) { /* input buffer. */ read(xpipe[0], (char *)&ibp, sizeof(ibp)); read(xpipe[0], ibp, ibc); } obc = 0; obp = obuf; *obuf = NUL; /* Because port fork flushed */ sjval = CEV_APC; cklongjmp(con_env,sjval); /* NOTREACHED */#endif /* CK_APC */#ifdef SUNX25 case CEV_PAD: /* X.25 PAD parameter change */ debug(F100,"CONNECT pipeint PAD change","",0); read(xpipe[0],padparms,MAXPADPARMS); sjval = CEV_PAD; /* Set global variable. */#ifdef COMMENT /* We might not need to do this... */ cklongjmp(con_env,sjval); /* NOTREACHED */#else /* COMMENT */ break;#endif /* COMMENT */#endif /* SUNX25 */ } signal(CK_FORK_SIG, pipeint); /* Set up signal handler */ kill(pid, CK_FORK_SIG); /* Signal the port fork ... */}/* C K C P U T C -- C-Kermit CONNECT Put Character to Screen *//* Output is buffered to avoid slow screen writes on fast connections. NOTE: These could (easily?) become macros ...*/static intckcputf() { /* Dump the output buffer */ int x = 0; if (obc > 0) /* If we have any characters, */ x = conxo(obc,obuf); /* dump them, */ obp = obuf; /* reset the pointer */ obc = 0; /* and the counter. */ return(x); /* Return conxo's return code */}intckcputc(c) int c; { int x; *obp++ = c & 0xff; /* Deposit the character */ obc++; /* Count it */ if (ibc == 0 || /* If input buffer about empty */ obc == OBUFL) { /* or output buffer full */ debug(F101,"CONNECT CKCPUTC obc","",obc); x = conxo(obc,obuf); /* dump the buffer, */ obp = obuf; /* reset the pointer */ obc = 0; /* and the counter. */ return(x); /* Return conxo's return code */ } else return(0);}/* C K C G E T C -- C-Kermit CONNECT Get Character *//* Buffered read from communication device. Returns the next character, refilling the buffer if necessary. On error, returns ttinc's return code (see ttinc() description). Dummy argument for compatible calling conventions with ttinc(). NOTE: We don't have a macro for this because we have to pass a pointer to this function as an argument to tn_doop().*/intckcgetc(dummy) int dummy; { int c, n;#ifdef CK_SSL extern int ssl_active_flag, tls_active_flag;#endif /* CK_SSL */#ifdef CK_ENCRYPTION /* No buffering for possibly encrypted connections */ if (network && IS_TELNET() && TELOPT_ME(TELOPT_AUTHENTICATION)) return(ttinc(0));#endif /* CK_ENCRYPTION */#ifdef CK_SSL if (ssl_active_flag || tls_active_flag) return(ttinc(0));#endif /* CK_SSL */#ifdef COMMENT/* too much */ debug(F101,"CONNECT CKCGETC 1 ibc","",ibc); /* Log */#endif /* COMMENT */ if (ibc < 1) { /* Need to refill buffer? */ ibc = 0; /* Yes, reset count */ ibp = ibuf; /* and buffer pointer */ /* debug(F100,"CONNECT CKCGETC 1 calling ttinc(0)","",0); */#ifdef COMMENT/* This check is not worth the overhead. Scenario: ttchk() returns 0, so we fall through to the blocking ttinc(). While in ttinc(), the connection is lost. But the read() that ttinc() calls does not notice, and never returns. This happens at least in HP-UX, and can be seen when we turn off the modem.*/ if (!network && (carrier != CAR_OFF)) if ((n = ttchk()) < 0) /* Make sure connection is not lost */ return(n);#endif /* COMMENT */ c = ttinc(0); /* Read one character, blocking */ /* debug(F101,"CONNECT CKCGETC 1 ttinc(0)","",c); */ if (c < 0) { /* If error, return error code */ return(c); } else { /* Otherwise, got one character */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -