📄 gcomm.c
字号:
#ifndef lintstatic const char rcsid[] = "$Id: gcomm.c,v 1.1.1.1 2001/03/08 00:01:47 efalk Exp $" ;#endif/* main program for gcomm */#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <unistd.h>#include <stdarg.h>#include <termios.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <netdb.h>#include <netinet/in.h>#include <sys/types.h>#include <sys/time.h>#include <sys/param.h>#include <gdk/gdk.h>#include <gdk/gdkx.h>#include <gtk/gtk.h>#include "params.h"#include "confirmer.h"#include "gcomm.h"#include "buffers.h"#include "windows.h"#include "winutils.h"#include "callbacks.h"#include "serial.h"#include "network.h"#include "pipe.h"#include "term.h"#include "Xmodem/zmodem.h"#include "transfers.h"#ifdef IODEBUG#include "Xmodem/seriallog.h"#else#define SerialLogFlush()#define SerialLog(a,b,c)#endifextern GtkWidget *create_mainwindow(void) ; int connectionType = ConnectionSerial ; int outputType = OutputVerbatim ; bool connectionActive = False ; bool connecting = False ; int connectAbort = 0 ; int connectTime0 = 0 ; /* connect time */ int connectTime = 0 ; /* elapsed time, seconds */ bool dialogActive = False ; bool transferActive = False ; int dialogTimeout ; bool debugEcho = False ; bool secure = False ; bool localEcho = False ; bool deferConnection = False ; bool haveHost = False ; char serialPortName[80] = "/dev/modem" ; char *hostName = "" ; char *hostPort = "" ; char *programArgs = "" ; int baudRate = -1 ; int byteSize = -1 ; /* 5,7,8 */ int stopBits = -1 ; /* 1,2 */ int parityType = -1 ; int flowControl = -1 ; bool inputStrip = -1 ; /* 0,1 */ bool TDD = False ; /* 0,1 */ bool uuLock = False ; int hardwareFlow = 0 ; int modemFlags ; int modemAttn = ModemAttnEsc ; char modemEsc[4] = "+" ; char phoneNo[80] = "", modemType[80] = "at", modemInit[80] = "", modemReset[80] = "" ; char connectMsg[80] = "", disconnectMsg[80] = "" ;#define MAXARGS 1024 int xferProtocol = XferZmodem ; int packetSize = 0, windowSize = 0, xferType = 0, noLoc = 0, xferAscii = 0, xferResume = 0 ; const int baudList[] = { 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400} ; const int nbaudList = sizeof(baudList)/sizeof(baudList[0]) ; /* On buffers: There are three ring-buffers in use here: * inputBuf holds data received from remote end * termBuf holds data to be displayed on terminal * outputBuf holds data to be send to remote end. * * Since no translation occurs on output, terminal input * is appended directly to outputBuf. * * Also, when no output translation is in effect, no dialog * is taking place, etc., terminal is driven directly from * inputBuf. */ Buffer inputBuf, termBuf ; Buffer outputBuf ; Buffer *lastread = NULL ; Buffer *terminalBuffer ; int termiHandler, termoHandler, inputHandler, outputHandler ; int timeHandler, modemLightsHandler, dialogHandler ; int dialogIdleHandler ; int windowFd = -1 ; int ifd = -1, ofd = -1 ; bool logging = False ;static bool uid, euid ;static bool gid, egid ;#define streq(a,b) (strcmp(a,b)==0)static void ParseArgs(int argc, char **argv) ;static void protocolArg(char *) ;static void parityArg(char *) ;static void flowcontrolArg(char *) ;static void modemArg(char *) ;static void networkArg(char *) ;static void addProgArgs(int *argc, char ***argv) ;static int remoteLookup(char *target, FILE *file, char *line) ;static void remoteParse(char *) ;static void sigfunc() ;#ifndef minstatic int min(a,b) int a,b ; { return b<a ? b : a ; }#endifstatic char usage[] ="gcomm [arguments] [var=value] [remotename|phone#]\n\ -l /dev/ttyX set serial line\n\ -p 8n1 set protocol\n\ -b nnnn set baud rate\n\ -parity <p> set parity none|even|odd|zero|one\n\ -stop 1|2 set stop bits\n\ -csize <n> set character size 5-8\n\ -echo set local echo\n\ -output <t> set output type 0=verbatim, 1=debug\n\ -debug turn on debug output\n\ -translate translate control, meta characters on output\n\ -lock lock port\n\ -flow <type> flow control none|xon|rts\n\ -modem <attn> modem attn: esc|break|dtr\n\ -modemesc <c> set modem escape char\n\ -net host make IP connection to host[:port]\n\ -prog <name> connect to program\n\ -c '...' execute chat script\n\ -e <file> run expect script\n\ -n set parameters but don't connect\n\ -w run without window\n\ -q this list\n\ var=value set environment variable\n\ remotename remote system name from $REMOTE, $HOME/.remote or /etc/remote\n\ phone# phone number\n" ;static int done = 0 ;intmain(int argc, char **argv){ /* security: The *first* thing we do is find out if this is * a set-uid program, and if so, switch to user mode right * away to prevent hanky-panky. * * Actually, that's not good enough. Consider just dropping * suid priveleges completely. */ uid = getuid() ; euid = geteuid() ; if( euid != uid ) seteuid(uid) ; gid = getgid() ; egid = getegid() ; if( egid != gid ) setegid(gid) ; gtk_set_locale (); gtk_init (&argc, &argv); ParseArgs(argc, argv) ;#ifdef IODEBUG if( logging ) { if( (SerialLogFile = fopen("xfer.log","w")) == NULL ) perror("xfer.log") ; if( (zmodemlogfile = fopen("zmodem.log","w")) == NULL ) perror("zmodem.log") ; }#endif signal(SIGINT, sigfunc) ; signal(SIGTERM, sigfunc) ; signal(SIGPIPE, SIG_IGN) ; /* Initialize windows */ /* TODO: no windows if -w specified */#ifdef ENABLE_NLS bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR); textdomain (PACKAGE);#endif#ifdef COMMENT add_pixmap_directory (PACKAGE_DATA_DIR "/pixmaps"); add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");#endif /* COMMENT */ mainwindow = create_mainwindow (); quitConfirm = create_confirmer ( "Connection still open\nreally quit?", mainwindow); gtk_widget_show (mainwindow); TermInfo() ;#ifdef COMMENT windowFd = XConnectionNumber( GDK_DISPLAY() ) ;#endif /* COMMENT */ clear_buffers() ; /* Remote input vectored straight to terminal. This will change * if there's a dialog active, a transfer in progress, etc. */ SelectTermBuf() ; termiHandler = termoHandler = inputHandler = outputHandler = -1 ; timeHandler = modemLightsHandler = dialogHandler = -1 ; dialogIdleHandler = -1 ; /* Earlier version of this program had a big select loop. Let's * try letting gtk input handlers do the job instead. * Enable callbacks for all open inputs, plus a couple timeout * functions. If an output stream won't accept any more data, * and the buffer is full, shut down the corresponding input. */ /* For now, only enable terminal input, which will be dropped on * the floor if there's no connection. */ termiHandler = gdk_input_add( 0, GDK_INPUT_READ, termiCB, NULL ) ; if( haveHost && !deferConnection ) MakeConnection() ; gtk_main() ; TermExit() ; SerialLogFlush() ; exit(0) ;}static voidsigfunc(){ /* an interrupt during a connection just cancels the connection */ if( connecting ) connectAbort = 1 ; else done = 1 ;} /* HANDLE COMMAND LINE ARGUMENTS */static voidParseArgs(int argc, char **argv){ int i ; char *ptr ; while( --argc > 0 ) { ++argv ; if( **argv == '-' ) { if( streq(*argv, "-?") || streq(*argv, "-q") ) { fprintf(stderr, usage) ; exit(0) ; } else if( streq(*argv, "-n") ) deferConnection = 1 ; else if( streq(*argv, "-l") && --argc > 0 ) { strncpy(serialPortName, *++argv, sizeof(serialPortName)-1) ; haveHost = 1 ; } else if( streq(*argv, "-p") && --argc > 0 ) protocolArg(*++argv) ; else if( streq(*argv, "-b") && --argc > 0 ) baudRate = atoi(*++argv) ; else if( streq(*argv, "-parity") && --argc > 0 ) parityArg(*++argv) ; else if( streq(*argv, "-stop") && --argc > 0 ) { i = atoi(*++argv) ; if( i >= 1 && i <= 2 ) stopBits = i ; } else if( streq(*argv, "-csize") && --argc > 0 ) { i = atoi(*++argv) ; if( i >= 5 && i <= 8 ) byteSize = i ; } else if( streq(*argv, "-echo") ) localEcho = 1 ; else if( streq(*argv, "-output") && --argc > 0 ) { i = atoi(*++argv) ; if( i >= 0 && i <= 1 ) outputType = i ; } else if( streq(*argv, "-debug") ) debugEcho = 1 ; else if( streq(*argv, "-translate") ) outputType = OutputDebug ; else if( streq(*argv, "-lock") ) uuLock = 1 ; else if( streq(*argv, "-flow") && --argc > 0 ) flowcontrolArg(*++argv) ; else if( streq(*argv, "-modemesc") && --argc > 0 ) strncpy(modemEsc, *++argv, sizeof(modemEsc)) ; else if( streq(*argv, "-modem") && --argc > 0 ) modemArg(*++argv) ; else if( streq(*argv, "-net") && --argc > 0 ) networkArg(*++argv) ; else if( streq(*argv, "-prog") && --argc > 0 ) { ++argv ; addProgArgs(&argc, &argv) ; } else if( streq(*argv, "-c") && --argc > 0 ) ++argv ; /* TODO: chat script */ else if( streq(*argv, "-e") && --argc > 0 ) ++argv ; /* TODO: expect script */ else if( streq(*argv, "-log") ) logging = True ; /* TODO: -call */ /* TODO: -exec */ /* ignore window system arguments */ else if( (streq(*argv, "-d") && --argc > 0) || (streq(*argv, "-g") && --argc > 0) ) ++argv ; else if( (streq(*argv, "-Ws") && (argc -= 2) > 0) || (streq(*argv, "-Wp") && (argc -= 2) > 0) ) argv += 2 ; else if( streq(*argv, "-Wi") ) {/* nothing */} else { fprintf(stderr, "unknown argument %s\n%s", *argv, usage) ; exit(1) ; } } else if( (ptr = strchr(*argv, '=')) != NULL ) putenv(*argv) ; else if( isdigit(**argv) ) { strncpy(phoneNo, *argv, sizeof(phoneNo)) ; haveHost = 1 ; } else remoteParse(*argv) ; }} /* parse -p argument */static voidprotocolArg( char *proto ){static char *usage = "unrecognized protocol %s, use '8n1', '7e1', etc.\n" ; if( proto[0] >= '5' && proto[0] <= '8' ) byteSize = proto[0] - '0' ; else { fprintf(stderr, usage, proto) ; return ; } switch( proto[1] ) { case 'n': parityType = ParityNone ; inputStrip = 0 ; break ; case 'e': parityType = ParityEven ; inputStrip = 1 ; break ; case 'o': parityType = ParityOdd ; inputStrip = 1 ; break ; case '0': parityType = ParityZero ; inputStrip = 1 ; break ; case '1': parityType = ParityOne ; inputStrip = 1 ; break ; default: fprintf(stderr, usage, proto) ; return ; } if( proto[2] >= '1' && proto[2] <= '2' ) stopBits = proto[2] - '0' ; else { fprintf(stderr, usage, proto) ; return ; }} /* utility: parse string argument */static intparseArg(char *arg, char *names[], int max){ int i ; for(i=0; i<max; ++i) if( streq(arg, names[i]) ) { return i ; } return -1 ;} /* parse -parity argument */static voidparityArg(char *par){static char *names[5] = {"none", "even", "odd", "zero", "one"} ; int i = parseArg(par, names, 5) ; if( i != -1 ) parityType = i ; else fprintf(stderr, "unrecognized parity %s, use 'none', 'odd', etc.\n", par) ;} /* parse -flow argument */static voidflowcontrolArg(char *flow){static char *names[3] = {"none", "xon", "rts"} ; int i = parseArg(flow, names, 3) ; if( i != -1 ) flowControl = i ; else fprintf(stderr, "unrecognized flow %s, use 'none', 'xon', 'rts'.\n", flow) ;} /* parse -modem argument */static voidmodemArg(char *mod){static char *names[3] = {"esc", "break", "dtr"} ; int i = parseArg(mod, names, 3) ; if( i != -1 ) modemAttn = i ; else fprintf(stderr, "unrecognized modem attn %s, use 'esc', 'break', 'dtr'.\n", mod) ;} /* libc strncat is badly broken; use this instead */static voidgstrcat(char *dst, char *src, int n){ int ld = strlen(dst) ; int ls = strlen(src) ; dst += ld ; n -= ld + 1 ; if( ls < n ) memcpy(dst, src, ls+1) ; else { memcpy(dst, src, n) ; dst[n] = '\0' ; }} /* parse -prog argument. Test for embedded spaces or special * characters, and append to programArgs */static voidaddProgArg(char *arg){ if( programArgs[0] != '\0' ) strcat(programArgs, " ") ; if( strchr(arg, ' ') == NULL && strchr(arg, '\t') == NULL && strchr(arg, '\'') == NULL && strchr(arg, '\\') == NULL && strchr(arg, '"') == NULL ) { gstrcat(programArgs, arg, MAXARGS) ; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -