📄 gunixio.c
字号:
/* G U N I X I O -- UNIX i/o module for gkermit *//* UNIX i/o functions for gkermit. Author: Frank da Cruz The Kermit Project Columbia University 612 West 115th Street New York NY 10025-7799 USA http://www.columbia.edu/kermit/ kermit@columbia.edu Copyright (C) 1999, The Trustees of Columbia University in the City of New York. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* CONTENTS... Console Output: tmsg - Type a message tmsgl - Type a line Communication Device: ttopen - Open ttpkt - Put in packet mode ttres - Restore normal mode ttinl - Input a raw packet ttol - Send a packet ttchk - Check if input ready ttflui - Flush input buffer File: zchki - See if file can be opened for input zopeni - Open input file zopeno - Open output file zclosi - Close input file zcloso - Close output file zrtol - Remote-to-Local filename conversion zltor - Local-to-Remote filename conversion zgetc - Get character from input file*/#include <stdio.h> /* Standard input/output */#ifdef POSIX#include <termios.h> /* Terminal modes */#else#ifdef SYSV#include <termio.h>#else#include <sgtty.h>#endif /* SYSV */#endif /* POSIX */#include <ctype.h> /* Character types */#include <sys/types.h> /* Needed e.g. by <stat.h> */#include <signal.h> /* Interrupts */#include <setjmp.h> /* Longjumps */#include <sys/stat.h> /* File exist, file size */#include <errno.h> /* Error symbols */#include "gkermit.h" /* gkermit definitions *//* All versions of HP-UX need Xon/Xoff */#ifdef hpux /* HP-UX Pre-7.00 */#ifndef __hpux#define __hpux#endif /* __hpux */#endif /* hpux */#ifdef __hpux /* HP-UX 7.00 and later */#ifndef SETXONXOFF#define SETXONXOFF#endif /* SETXONXOFF */#endif /* __hpux */#ifdef NOXONXOFF /* -DNOXONXOFF overrides */#ifdef SETXONXOFF#undef SETXONXOFF#endif /* SETXONXOFF */#endif /* NOXONXOFF */#ifndef TINBUFSIZ /* read() inpbut buffer */#ifdef USE_GETCHAR#define TINBUFSIZ 0 /* getchar() has its own */#else#ifdef SMALL#define TINBUFSIZ 240#else#define TINBUFSIZ 4080#endif /* SMALL */#endif /* USE_GETCHAR */#endif /* TINBUFSIZ */#ifndef DUMBIO#ifndef USE_GETCHAR#ifndef NOFCNTL_H /* For nonblocking buffered read() */#ifdef SYS_FCNTL_H#include <sys/fcntl.h>#else#include <fcntl.h>#ifndef O_NDELAY#ifdef O_NONBLOCK#define O_NDELAY O_NONBLOCK#endif /* O_NONBLOCK */#endif /* O_NDELAY */#endif /* SYS_FCNTL_H */#endif /* NOFCNTL_H */#endif /* USE_GETCHAR */#endif /* DUMBIO */#ifdef O_NDELAY /* For System V R3 and earlier */#ifndef EWOULDBLOCK#ifdef EAGAIN#define EWOULDBLOCK EAGAIN#endif /* EAGAIN */#endif /* EWOULDBLOCK */#endif /* O_NDELAY */#ifndef DUMBIO /* To force single-char read/write */#ifndef USE_GETCHAR#ifndef O_NDELAY#define DUMBIO#endif /* O_NDELAY */#endif /* USE_GETCHAR */#endif /* DUMBIO *//* Header file deficiencies section... */#ifndef R_OK#define R_OK 4#endif /* R_OK */#ifndef W_OK#define W_OK 2#endif /* W_OK */#ifndef _IFMT#ifdef S_IFMT#define _IFMT S_IFMT#else#define _IFMT 0170000#endif /* S_IFMT */#endif /* _IFMT */#ifndef S_ISREG#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)#endif /* S_ISREG *//* External variables */extern int literal; /* Literal filenames */extern int quiet; /* No messages */extern int keep; /* Keep incomplete files */extern int streamok; /* OK to offer streaming */extern int nomodes; /* Don't get/set tty modes */extern int xonxoff; /* Set Xon/Xoff */extern int noxonxoff; /* Don't set Xon/Xoff */extern FILE * db; /* Debug log file *//* Exported variables */FILE *ifp, *ofp; /* Input and output file pointers */char zinbuf[MAXRECORD+1]; /* File input buffer */int zincnt = 0; /* count */char * zinptr = NULL; /* and pointer. *//* Private global variables */static int havemodes = 0; /* Have obtained terminal modes */static int ttflags = -1; /* Terminal flags */static int nonblock = 0; /* Nonblocking i/o enabled */static char tinbuf[TINBUFSIZ+16]; /* Communications input buffer */static char * tinptr = NULL; /* Pointer to current item */static int tincnt = 0; /* Buffer count */static int tlast = 0; /* Last item in buffer */static int xparity = 0; /* Parity in use, 0 = none */static int raw = 0; /* Terminal rawmode flag */static char work[MAXPATHLEN+1]; /* Filename conversion buffer *//* Terminal mode structs */#ifdef POSIX /* POSIX */static struct termios ttold, ttraw;#else#ifdef SYSV /* System V */static struct termio ttold = {0};static struct termio ttraw = {0};#else#ifdef BSD /* 4.2 BSD or UNIX V7 */static struct sgttyb ttold, ttraw;#endif /* BSD */#endif /* SYSV */#endif /* POSIX */static jmp_buf jbuf; /* Longjump buffer for timeouts *//* Functions... */SIGTYPdoexit(x) int x; { /* Exit routine */ if (x) /* If failure */ ttflui(); /* flush pending junk we won't read */ ttres(); /* Reset the communication device */#ifdef F_SETFL if (ttflags > -1) /* Restore its flags */ fcntl(0,F_SETFL,ttflags);#endif /* F_SETFL */ if (debug) { fprintf(db,"exit %d\n",x); fclose(db); } exit(x);}VOIDsysinit() { /* To be run first thing */#ifdef F_SETFL ttflags = fcntl(0,F_GETFL,0); /* Get and save stdin flags */#endif /* F_SETFL */#ifdef SIGINT signal(SIGINT,SIG_IGN); /* Ignore interrupts */#endif /* SIGINT */#ifdef SIGTSTP signal(SIGTSTP,SIG_IGN);#endif /* SIGTSTP */#ifdef SIGQUIT signal(SIGQUIT,SIG_IGN);#endif /* SIGQUIT */ signal(SIGHUP,doexit); /* Go here on hangup */}/* Console Functions */#ifdef COMMENT /* (not used) */VOIDtmsg(s) char *s; { /* tmsg() */ if (!quiet) fprintf(stderr,"%s",s); /* Type message on the screen. */}#endif /* COMMENT */VOIDtmsgl(s) char *s; { /* tmsgl() */ if (!quiet) { if (raw) fprintf(stderr,"%s\r\n",s); /* Type message with CRLF */ else fprintf(stderr,"%s\n",s); }}/* Debugging functions */VOIDlogerr(s) char * s; { /* Log text and errno */ if (!s) s = ""; if (!debug) return; if (db) fprintf(db,"%s: errno = %d\n",s,errno);}/* Parity function */char#ifdef __STDC__dopar(char ch)#elsedopar(ch) char ch;#endif /* __STDC__ */{ /* Do parity */ unsigned int a; if (!xparity) return(ch); else ch &= 0177; switch (xparity) { case 'm': return(ch | 128); /* Mark */ case 's': return(ch & 127); /* Space */ case 'o': /* Odd (fall thru) */ case 'e': /* Even */ a = (ch & 15) ^ ((ch >> 4) & 15); a = (a & 3) ^ ((a >> 2) & 3); a = (a & 1) ^ ((a >> 1) & 1); if (xparity == 'o') a = 1 - a; /* Switch sense for odd */ return(ch | (a << 7)); default: return(ch); }}/* Communication functions */intttopen(ttname) char *ttname; { /* "Open" the communication device */ if (debug) { /* Vital statistics for debug log */#ifdef __STDC__ fprintf(db,"ttopen __STDC__\n");#endif /* __STDC__ */#ifdef SIG_V fprintf(db,"ttopen SIG_V\n");#else#ifdef SIG_I fprintf(db,"ttopen SIG_I\n");#endif /* SIG_I */#endif /* SIG_V */#ifdef USE_GETCHAR fprintf(db,"ttopen getchar/putchar\n");#ifdef BUFSIZ fprintf(db,"ttopen BUFSIZ = %d\n", BUFSIZ);#endif /* BUFSIZ */#else#ifdef DUMBIO fprintf(db,"ttopen single-byte read/write\n");#else fprintf(db,"ttopen nonblocking read/write\n");#endif /* DUMBIO */#endif /* USE_GETCHAR */ fprintf(db,"ttopen TINBUFSIZ = %d\n", TINBUFSIZ);#ifdef __hpux fprintf(db,"ttopen __hpux\n");#endif /* __hpux */#ifdef pdp11 fprintf(db,"ttopen pdp11\n");#endif /* pdp11 */#ifdef SETXONXOFF fprintf(db,"ttopen SETXONXOFF\n");#endif /* SETXONXOFF */ fprintf(db,"ttopen xonxoff = %d\n",xonxoff); fprintf(db,"ttopen noxonxoff = %d\n",noxonxoff); fprintf(db,"ttopen ttflags %d\n",ttflags); fprintf(db,"ttopen nomodes %d\n",nomodes); } if (nomodes) { /* If external protocol */#ifdef SIGINT /* exit on interrupts */ signal(SIGINT,doexit);#endif /* SIGINT */#ifdef SIGTSTP signal(SIGTSTP,doexit);#endif /* SIGTSTP */#ifdef SIGQUIT signal(SIGQUIT,doexit);#endif /* SIGQUIT */ return(0); }#ifndef DUMBIO#ifndef USE_GETCHAR#ifdef O_NDELAY#ifdef F_SETFL if (ttflags != -1) { /* Set nonbocking i/o on stdin */ errno = 0; if (fcntl(0, F_SETFL,ttflags|O_NDELAY) == -1) logerr("ttopen fcntl(0,F_SETFL,O_NDELAY)"); else nonblock = 1; }#endif /* F_SETFL */#endif /* O_NDELAY */#endif /* USE_GETCHAR */#endif /* DUMBIO */ if (!nonblock) /* No streaming without */ streamok = -1; /* nonblocking reads */ if (debug) fprintf(db,"ttopen nonblock = %d\n", nonblock);#ifdef POSIX tcgetattr(0,&ttold); /* Get stdin device attributes */ tcgetattr(0,&ttraw);#else#ifdef SYSV ioctl(0,TCGETA,&ttold); ioctl(0,TCGETA,&ttraw);#else#ifdef BSD gtty(0,&ttold); gtty(0,&ttraw);#endif /* BSD */#endif /* SYSV */#endif /* POSIX */ havemodes++; return(0);}intttpkt(parity) int parity; { /* Put comm device in packet mode */#ifdef BSD int x;#endif /* BSD */ xparity = parity; /* Make local copy of parity */ if (nomodes) return(0);#ifdef SVORPOSIX /* System V or POSIX section... */ ttraw.c_iflag |= IGNPAR; ttraw.c_lflag &= ~(ICANON|ECHO); ttraw.c_lflag &= ~ISIG; ttraw.c_lflag |= NOFLSH;#ifdef SETXONXOFF if (!noxonxoff) { ttraw.c_iflag |= (IXON|IXOFF); if (debug) fprintf(db,"ttpkt SVORPOSIX Xon/Xoff\n"); }#else if (xonxoff) { if (debug) fprintf(db,"ttpkt SVORPOSIX Xon/Xoff\n"); ttraw.c_iflag |= (IXON|IXOFF); }#endif /* SETXONXOFF */#ifdef IEXTEN ttraw.c_lflag &= ~IEXTEN;#endif /* IEXTEN */#ifdef POSIX ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);#else ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);#endif /* POSIX */ ttraw.c_oflag &= ~OPOST; ttraw.c_cflag &= ~(CSIZE); ttraw.c_cflag |= (CS8|CREAD|HUPCL); ttraw.c_cflag &= ~(PARENB);#ifndef VEOF ttraw.c_cc[4] = 1;#else#ifdef VMIN ttraw.c_cc[VMIN] = 1;#endif /* VMIN */#endif /* VEOF */#ifndef VEOL ttraw.c_cc[5] = 0;#else#ifdef VTIME ttraw.c_cc[VTIME] = 0;#endif /* VTIME */#endif /* VEOL */#ifdef VINTR ttraw.c_cc[VINTR] = 0;#endif /* VINTR */#ifdef POSIX if (tcsetattr(0,TCSADRAIN,&ttraw) < 0) return(-1);#else if (ioctl(0,TCSETAW,&ttraw) < 0) return(-1);#ifdef SYSV#endif /* SYSV */#endif /* POSIX */#else /* Not SVORPOSIX */#ifdef BSD ttraw.sg_flags |= RAW; /* BSD/V7 raw (binary) mode */#ifdef SETXONXOFF if (!noxonxoff) { ttraw.sg_flags |= TANDEM; if (debug) fprintf(db,"ttpkt BSD Xon/Xoff\n"); }#else if (xonxoff) { ttraw.sg_flags |= TANDEM; if (debug) fprintf(db,"ttpkt BSD Xon/Xoff\n"); }#endif /* SETXONXOFF */ ttraw.sg_flags &= ~(ECHO|CRMOD); /* No echo, etc */ if (stty(0,&ttraw) < 0) return(-1); /* Set modes */#else system("stty raw -echo");#endif /* BSD */#endif /* SVORPOSIX */ raw = 1; /* Flag we're now in raw mode */ return(0);}intttres() { /* Reset terminal */ int x = 0; if (havemodes) { /* Restore old modes */#ifdef POSIX x = tcsetattr(0,TCSADRAIN,&ttold);#else#ifdef SYSV sleep(1); /* Let output finish */ x = ioctl(0,TCSETAW,&ttold);#else#ifdef BSD sleep(1); /* Let output finish */ x = stty(0,&ttold);#else x = system("stty -raw echo");#endif /* BSD */#endif /* SYSV */#endif /* POSIX */ } write(1,"\015\012",2); raw = 0; return(x);}intttchk() { /* Check if input ready */ int x = 0; if (nonblock) { /* Try to read */ errno = 0; x = read(0,&tinbuf[tlast],TINBUFSIZ-tlast);#ifdef EXTRADEBUG fprintf(db,"ttchk read %d errno = %d\n",x,errno);#endif /* EXTRADEBUG */#ifdef EWOULDBLOCK if (x < 0 && errno == EWOULDBLOCK) /* Nothing to read */ x = 0;#endif /* EWOULDBLOCK */ if (x < 0) /* Fatal i/o error */ return(-1); } tincnt += x; /* Buffer bookkeeping */ tlast += x; return(x + tincnt); /* How much is waiting to be read */}intttflui() { /* Flush comm device input buffer */#ifdef BSD long n = 1; /* Specify read queue */#endif /* BSD */ int x; tincnt = 0; /* Our own buffer */ tlast = 0; tinptr = tinbuf; errno = 0;#ifdef POSIX x = tcflush(0,TCIFLUSH); /* kernel/driver buffers */#else#ifdef SYSV x = ioctl(0,TCFLSH,0);#else#ifdef BSD x = ioctl(0,TIOCFLUSH,&n);#endif /* BSD */#endif /* SYSV */#endif /* POSIX */ if (debug) fprintf(db,"ttflui = %d, errno = %d\n",x,errno); return(x);}SIGTYPtimerh(dummy) int dummy; { /* Timeout handler */ longjmp(jbuf,1); SIGRETURN;}/* ttinl() - Read a raw packet. Call with: dest - where to put it max - maximum length timo - timeout (seconds, 0 = none) eol - packet terminator turn - half-duplex line turnaround character to wait for, 0 = none Returns length obtained, or -1 if error or timeout, -2 on disconnection.*/#ifndef DEBUGWRAP#define DEBUGWRAP 48#endif /* DEBUGWRAP */int#ifdef __STDC__ttinl(char * dest, int max, int timo, char eol, char soh, int turn)#elsettinl(dest,max,timo,eol,soh,turn) int max, timo, turn; char eol, soh, *dest;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -