📄 ckucon.c
字号:
#endif /* COMMENT */ obp = obuf; obc = 0;#endif /* DYNAMIC */ kbp = kbuf; /* Always clear these. */ *kbp = NUL; /* No need to preserve them between */ kbc = 0; /* CONNECT sessions. */#ifdef DEBUG if (deblog) { debug(F101,"CONNECT conect entry ttyfd","",ttyfd); debug(F101,"CONNECT conect entry ibc","",ibc); debug(F101,"CONNECT conect entry obc","",obc); debug(F101,"CONNECT conect entry kbc","",kbc);#ifdef CK_TRIGGER debug(F110,"CONNECT conect trigger",tt_trigger[0],0);#endif /* CK_TRIGGER */ if (ttyfd > -1) { n = ttchk(); debug(F101,"CONNECT conect entry ttchk","",n); } }#endif /* DEBUG */ if (ttyfd < 0) { /* If communication device not open */ debug(F101,"CONNECT ttnproto","",ttnproto); debug(F111,"CONNECT opening",ttname,0); /* Open it now */ if (ttopen(ttname, &local, network ? -nettype : mdmtyp, 0 ) < 0) { ckmakmsg(temp,TMPLEN,"Sorry, can't open ",ttname,NULL,NULL); perror(temp); debug(F110,"CONNECT open failure",ttname,0); goto conret0; }#ifdef IKS_OPTION /* If peer is in Kermit server mode, return now. */ if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start) return(0);#endif /* IKS_OPTION */ } dohangup = 0; /* Hangup not requested yet */#ifdef ANYX25 dox25clr = 0; /* X.25 clear not requested yet */#endif /* ANYX25 */ if (msgflg) {#ifdef NETCONN if (network) { if (ttpipe) printf("Connecting via command \"%s\"",ttname); else printf("Connecting to host %s",ttname);#ifdef ANYX25 if (nettype == NET_SX25 || nettype == NET_IX25) printf(", Link ID %d, LCN %d",linkid,lcn);#endif /* ANYX25 */ } else {#endif /* NETCONN */ printf("Connecting to %s",ttname); if (speed > -1L) printf(", speed %ld",speed);#ifdef NETCONN }#endif /* NETCONN */ if (tt_escape) { printf("\r\n"); shoesc(escape); printf("Type the escape character followed by C to get back,\r\n"); printf("or followed by ? to see other options.\r\n"); } else { printf(".\r\n\nESCAPE CHARACTER IS DISABLED\r\n\n"); } if (seslog) { extern int slogts; char * s = ""; switch (sessft) { case XYFT_D: s = "debug"; break; case XYFT_T: s = slogts ? "timestamped-text" : "text"; break; default: s = "binary"; } printf("Session Log: %s, %s\r\n",sesfil,s); } if (debses) printf("Debugging Display...)\r\n"); printf("----------------------------------------------------\r\n"); fflush(stdout); }/* Condition console terminal and communication line */ if (conbin((char)escape) < 0) { printf("Sorry, can't condition console terminal\n"); goto conret0; } debug(F101,"CONNECT cmask","",cmask); debug(F101,"CONNECT cmdmsk","",cmdmsk); debug(F101,"CONNECT speed before ttvt","",speed); if ((n = ttvt(speed,flow)) < 0) { /* Enter "virtual terminal" mode */ if (!network) { debug(F101,"CONNECT ttvt","",n); tthang(); /* Hang up and close the device. */ ttclos(0); dologend(); if (ttopen(ttname, /* Open it again... */ &local, network ? -nettype : mdmtyp, 0 ) < 0) { ckmakmsg(temp,TMPLEN,"Sorry, can't reopen ",ttname,NULL,NULL); perror(temp); goto conret0; }#ifdef IKS_OPTION if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start) return(0);#endif /* IKS_OPTION */ if (ttvt(speed,flow) < 0) { /* Try virtual terminal mode again. */ conres(); /* Failure this time is fatal. */ printf("Sorry, Can't condition communication line\n"); goto conret0; } } } debug(F101,"CONNECT ttvt ok, escape","",escape); debug(F101,"CONNECT carrier-watch","",carrier); if ((!network #ifdef TN_COMPORT || istncomport()#endif /* TN_COMPORT */ ) && (carrier != CAR_OFF)) { int x; x = ttgmdm(); debug(F100,"CONNECT ttgmdm","",x); if ((x > -1) && !(x & BM_DCD)) {#ifndef NOHINTS extern int hints;#endif /* NOHINTS */ debug(F100,"CONNECT ttgmdm CD test fails","",x); conres(); printf("?Carrier required but not detected.\n");#ifndef NOHINTS if (!hints) return(0); printf("***********************************\n"); printf(" Hint: To CONNECT to a serial device that\n"); printf(" is not presenting the Carrier Detect signal,\n"); printf(" first tell C-Kermit to:\n\n"); printf(" SET CARRIER-WATCH OFF\n\n"); printf("***********************************\n\n");#endif /* NOHINTS */ goto conret0; } debug(F100,"CONNECT ttgmdm ok","",0); }#ifndef NOCSETS/* Set up character set translations */ unicode = 0; /* Assume Unicode won't be involved */ tcs = 0; /* "Transfer" or "Other" charset */ sxo = rxo = NULL; /* Initialize byte-to-byte functions */ sxi = rxi = NULL; if (tcsr != tcsl) { /* Remote and local sets differ... */#ifdef UNICODE if (tcsr == FC_UTF8 || /* Remote charset is UTF-8 */ tcsl == FC_UTF8) { /* or local one is. */ xuf = xl_ufc[tcsl]; /* Incoming Unicode to local */ if (xuf || tcsl == FC_UTF8) { tcs = (tcsr == FC_UTF8) ? tcsl : tcsr; /* The "other" set */ xfu = xl_fcu[tcs]; /* Local byte to remote Unicode */ if (xfu) unicode = (tcsr == FC_UTF8) ? 1 : 2; } tcssize = fcsinfo[tcs].size; /* Size of other character set. */ } else {#endif /* UNICODE */ tcs = gettcs(tcsr,tcsl); /* Get intermediate set. */ sxo = xls[tcs][tcsl]; /* translation function */ rxo = xlr[tcs][tcsr]; /* pointers for output functions */ sxi = xls[tcs][tcsr]; /* and for input functions. */ rxi = xlr[tcs][tcsl];#ifdef UNICODE }#endif /* UNICODE */ }/* This is to prevent use of zmstuff() and zdstuff() by translation functions. They only work with disk i/o, not with communication i/o. Luckily Russian translation functions don't do any stuffing...*/ langsv = language;#ifndef NOCYRIL if (language != L_RUSSIAN)#endif /* NOCYRIL */ language = L_USASCII;#ifdef COMMENT#ifdef DEBUG if (deblog) { debug(F101,"CONNECT tcs","",tcs); debug(F101,"CONNECT tcsl","",tcsl); debug(F101,"CONNECT tcsr","",tcsr); debug(F101,"CONNECT fcsinfo[tcsl].size","",fcsinfo[tcsl].size); debug(F101,"CONNECT fcsinfo[tcsr].size","",fcsinfo[tcsr].size); debug(F101,"CONNECT unicode","",unicode); }#endif /* DEBUG */#endif /* COMMENT */#ifdef CK_XYZ#ifndef XYZ_INTERNAL { extern int binary; /* See about ZMODEM autodownloads */ char * s; s = binary ? ptab[PROTO_Z].p_b_rcmd : ptab[PROTO_Z].p_t_rcmd; if (!s) s = ""; zmdlok = (*s != NUL); /* OK if we have external commands */ }#endif /* XYZ_INTERNAL */#endif /* CK_XYZ */#ifndef NOESCSEQ/* We need to activate the escape-sequence recognition feature when: (a) translation is elected, AND (b) the local and/or remote set is a 7-bit set other than US ASCII. Or: SET TERMINAL APC is not OFF (handled in the next statement).*/ escseq = (tcs != TC_TRANSP) && /* Not transparent */ (fcsinfo[tcsl].size == 128 || fcsinfo[tcsr].size == 128) && /* 7 bits */ (fcsinfo[tcsl].code != FC_USASCII); /* But not ASCII */#endif /* NOESCSEQ */#endif /* NOCSETS */#ifndef NOESCSEQ#ifdef CK_APC escseq = escseq || (apcstatus & APC_ON); apcactive = 0; /* An APC command is not active */ apclength = 0; /* ... */#endif /* CK_APC */ inesc = ES_NORMAL; /* Initial state of recognizer */ debug(F101,"CONNECT escseq","",escseq);#endif /* NOESCSEQ */ parent_id = getpid(); /* Get parent's pid for signalling */ debug(F101,"CONNECT parent pid","",parent_id); if (xpipe[0] > -1) /* If old pipe hanging around, close */ close(xpipe[0]); xpipe[0] = -1; if (xpipe[1] > -1) close(xpipe[1]); xpipe[1] = -1; goterr = 0; /* Error flag for pipe & fork */ if (pipe(xpipe) != 0) { /* Create new pipe to pass info */ perror("Can't make pipe"); /* between forks. */ debug(F101,"CONNECT pipe error","",errno); goterr = 1; } else#ifdef BEOSORBEBOX { pid = spawn_thread(concld, "Lower Fork", B_NORMAL_PRIORITY, NULL); resume_thread(pid); }#else if ((pid = fork()) == (PID_T) -1) { /* Pipe OK, make port fork. */ perror("Can't make port fork"); debug(F101,"CONNECT fork error","",errno); goterr = 1; }#endif /* BEOSORBEBOX */ debug(F101,"CONNECT created fork, pid","",pid); if (goterr) { /* Failed to make pipe or fork */ conres(); /* Reset the console. */ if (msgflg) { printf("\r\nCommunications disconnect (Back at %s)\r\n", *myhost ? myhost :#ifdef UNIX "local UNIX system"#else "local system"#endif /* UNIX */ ); } printf("\n"); what = W_NOTHING; /* So console modes are set right. */#ifndef NOCSETS language = langsv; /* Restore language */#endif /* NOCSETS */ parent_id = (PID_T) 0; /* Clean up */ goto conret1; } debug(F101,"CONNECT fork pid","",pid);/* Upper fork (KEYB fork) reads keystrokes and sends them out. */ if (pid) { /* pid != 0, so I am the upper fork. *//* Before doing anything significant, the child fork must wait for a go-ahead character from xpipe[0]. Before starting to wait, we have enough time to clear buffers and set up the signal handler. When done with this, we will allow the child to continue by satisfying its pending read. Remember the child and parent have separate address space. The child has its own copy of input buffers, so we must clear the input buffers in the parent. Otherwise strange effects may occur, like chunks of characters repeatedly echoed on terminal screen. The child process is designed to empty its input buffers by reading all available characters and either echoing them on the terminal screen or saving them for future use in the parent. The latter case happens during APC processing - see the code around CEV_APC occurrences to see how the child passes its ibuf etc to parent via xpipe, for preservation until the next entry to this module, to ensure that no characters are lost between CONNECT sessions.*//* This one needs a bit of extra explanation... In addition to the CONNECT module's own buffers, which are communicated and synchronized via xpipe, the low-level UNIX communication routines (ttinc, ttxin, etc) are also buffered, statically, in the ckutio.c module. But when the two CONNECT forks split off, the lower fork is updating this buffer's pointers and counts, but the upper fork never finds out about it and still has the old ones. The following UNIX-specific call to the ckutio.c module takes care of this... Without it, we get dual echoing of incoming characters.*/ ttflux();/* At this point, perhaps you are wondering why we use forks at all. It is simply because there is no other method portable among all UNIX variations. Not threads, not select(), ... (Yes, select() is more common now; it might actually be worth writing a variation of this module that works like BSD Telnet, one fork, driven by select()).*/ ibp = ibuf; /* Clear ibuf[]. */ ibc = 0; /* Child now has its own copy */ signal(CK_FORK_SIG, pipeint); /* Handler for messages from child. */ write(xpipe[1], ibuf, 1); /* Allow child to proceed */ close(xpipe[1]); xpipe[1] = -1; /* Parent - prevent future writes */ what = W_CONNECT; /* Keep track of what we're doing */ active = 1; debug(F101,"CONNECT keyboard fork duplex","",duplex);/* Catch communication errors or mode changes in lower fork. Note: Some C compilers (e.g. Cray UNICOS) interpret the ANSI C standard about setjmp() in a way that disallows constructions like: if ((var = [sig]setjmp(env)) == 0) ... which prevents the value returned by cklongjmp() from being used at all. So the signal handlers set a global variable, sjval, instead.*/ if (#ifdef CK_POSIX_SIG sigsetjmp(con_env,1)#else setjmp(con_env)#endif /* CK_POSIX_SIG */ == 0) { /* Normal entry... */ jbset = 1; /* Now we have a longjmp buffer */ sjval = CEV_NO; /* Initialize setjmp return code. */ debug(F101,"CONNECT setjmp normal entry","",sjval);#ifdef ANYX25 if (network && (nettype == NET_SX25 || nettype == NET_IX25)) { obufl = 0; bzero (x25obuf,sizeof(x25obuf)); }#endif /* ANYX25 *//* Here is the big loop that gets characters from the keyboard and sends them out the communication device. There are two components to the communication path: the connection from the keyboard to C-Kermit, and from C-Kermit to the remote computer. The treatment of the 8th bit of keyboard characters is governed by SET COMMAND BYTESIZE (cmdmsk). The treatment of the 8th bit of characters sent to the remote is governed by SET TERMINAL BYTESIZE (cmask). This distinction was introduced in edit 5A(164).*/ while (active) {#ifndef NOSETKEY if (kmptr) { /* Have current macro? */ debug(F100,"CONNECT kmptr non NULL","",0); if ((c = (CHAR) *kmptr++) == NUL) { /* Get char from it */ kmptr = NULL; /* If no more chars, */ debug(F100,"CONNECT macro empty, continuing","",0); continue; /* reset pointer and continue */ } debug(F000,"CONNECT char from macro","",c); } else /* No macro... */#endif /* NOSETKEY */ c = CONGKS(); /* Read from keyboard */#ifdef COMMENT/* too much... */ debug(F101,"CONNECT ** KEYB","",c);#endif /* COMMENT */ if (c == -1) { /* If r
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -