/* * 伪终端主控程序 for SCO UNIX * * Usage: mypty [-f config-file] [-l logdevice] * default config-file is /etc/mypty.conf * logdevice is /dev/tty12 * * cc -o mypty mypty.c -lsocket * 陈杰 2001/01/11 * * 注:本程序为简单计,各伪终端需使用不同的连接端口号 * 配置文件形如 * 终端号 合法地址 端口(需不重复) * ttyp11 192.0.0.1 2000 * ttyp11 192.0.0.2 2001 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "varargs.h"
#if defined(INTER) //struct tty { int x; }; #include #endif
// int LOGERR=1;
#define SCO32
#if !defined(TIOCPKT) #undef FIONBIO #include #endif
#define DEFAULT_CONFIG_FILE_NAME "/etc/mypty.conf" #define DEFAULT_LOGDEVICE "/dev/tty12" #define BUFLEN 1024
typedef struct myptyConfigStru Config, *PConfig;
struct myptyConfigStru { PConfig next; // 下一设备 char p_tty[32]; // 伪终端设备名 long ipaddr; // 合法客户地址 unsigned short port; // 侦听端口号 short status; // 状态 short flags; // 标志 long timeout; // 关闭连接的超时 int ptyfd; // 伪终端文件描述字 int sockfd; // 套接字 int waitfd; // 侦听套接字 char pty_buf[BUFLEN+1]; // 伪终端输入缓冲区 int pty_count; // 已输入字节数 char sock_buf[BUFLEN+1]; // 套接字缓冲区 int sock_count; // 已输入字节数 };
/* Define status */ #define IN_INIT 0 #define IN_ACT 1 #define PTY_OK 10 #define PTY_ERR 11 #define SOCK_OK 20 #define SOCK_ERR 21 #define WAIT_OK 30 #define WAIT_ERR 31
/* Define flags */ #define CONFIGURED 0x01 /* 已配置 */ #define INWAITCONN 0x02 /* 进入等待连接状态 */
PConfig szConf=NULL; PConfig ConfRoot=NULL; int AnyTimeout=0; int MaxFD=0; unsigned long localip=0; char *cnf_file=NULL; char *errname=NULL; pid_t mypid=-1;
void daemon_init(void); void mypty(void);
void cj_Errlog(va_alist) va_dcl { FILE *fp va_list args; char *fmt,buf[640]; struct tm *tm; time_t t;
// if (LOGERR){ fp = fopen(errname , "a" ) if (fp==NULL) return va_start(args); fmt = va_arg(args, char * ); vsprintf(buf, fmt, args ); va_end(args); t = time(NULL); tm = localtime(&t); if (mypid==-1) mypid = getpid(); fprintf(fp, "%04d-%02d-%02d %02d:%02d:%02d <%d>:%s\r\n", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, mypid, buf ) fclose(fp) // } return }
usage(void) { fprintf(stderr,"Usage: mypty [-f config-file] [-l logdevice]\n\7"); fprintf(stderr,"Default config-file is /etc/mypty.conf\n"); fprintf(stderr," logdevice is /dev/tty12\n"); fprintf(stderr,"Example:mypty -f /etc/mypty.conf\n"); fprintf(stderr," mypty -f /etc/mypty.conf -l /dev/null\n"); exit(-1); }
main(int argc, char *argv[]) { int c;
errname = DEFAULT_LOGDEVICE; cnf_file = DEFAULT_CONFIG_FILE_NAME; while ((c=getopt(argc, argv, "f:l:"))!=-1){ switch(c){ case 'f':cnf_file = optarg; if (access(cnf_file, R_OK)!=0){ perror(cnf_file); exit(2); } break; case 'l':errname = optarg; if (access(errname, F_OK)!=0) close(open(errname, O_CREAT, 0660)); if (access(errname, W_OK)!=0){ perror(errname); exit(2); } break; case '?':usage();break; default :fprintf(stderr,"Error options: %c <%d>", c, c); exit(1); } } daemon_init(); read_config(NULL); mypid = getpid(); mypty();
exit(0); }
static int lockfd=-1; static FILE *lockfp=NULL; void endproc(int sig) { PConfig pc;
for (pc=ConfRoot;ConfRoot;pc=ConfRoot){ close(pc->ptyfd); close(pc->waitfd); close(pc->sockfd); ConfRoot=pc->next; free(pc); } lockf(lockfd, F_ULOCK, 0); close(lockfd); cj_Errlog("Terminated signal received"); exit(0); }
void my_child(int sig) { int i, pid, stat;
pid = waitpid(-1, &stat, WNOHANG); while (pid>0) pid = waitpid(-1, &stat, WNOHANG); }
/* 转入后台, 监听客户连接 */ void daemon_init(void) { int i; int fd; int status; int frominit;
signal(SIGTERM, endproc); signal(SIGCLD, my_child); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif
/* 如果由 inittab 启动, 则无需手工进入后台 */ frominit = (getppid() == 1); if (!frominit) { switch (i=fork()) { case -1: perror("fork"); exit(1); case 0: break; default: exit(0); } }
umask(0); /* 回到根目录以避免文件系统装卸问题 */ chdir("/");
/* 设置成为新的进程组长 */ setpgrp();
/* 再次 fork 脱离控制台, 如果由 init 启动, 则父进程 wait */ switch (i=fork()) { case -1: perror("fork2"); exit(1); case 0: break; default: if (frominit) wait(&status); exit(0); } }
void reread_config(int sig) { /* 重读配置文件 */ cj_Errlog("Reconfigure: signal (%d) received.", sig); read_config(NULL); }
read_config(char *fname) { char buf[256], p_tty[32], ip[32], ports[32], dummy[64]; int lines=0, port; long ipaddr; PConfig pc, tail; struct hostent *hp; struct in_addr in;
if (fname) cnf_file = fname; cj_Errlog("read_config(%s) start.", cnf_file); if (lockfd==-1){ /* 第一次运行,测试锁 */ lockfd = open(cnf_file, O_RDWR); if (lockfd<0) { perror(cnf_file); exit(3); } if (lockf(lockfd, F_TLOCK, 0)<0){ cj_Errlog("Another copy of this program is running..."); close(lockfd); exit(1); } else cj_Errlog("Filelock of %s successfully", cnf_file); } if (lockfp==NULL) lockfp = fdopen(lockfd, "r"); if (lockfp==NULL) { // perror(cnf_file); cj_Errlog("Error open config file:<%d>%s", errno, cnf_file); goto done; } rewind(lockfp); for (pc=ConfRoot,tail=NULL;pc;tail=pc,pc=pc->next) pc->flags &= ~CONFIGURED; /* 置未配置标志 */ while (fgets(buf, sizeof(buf), lockfp)) { lines++; if (buf[0]==0 || buf[0]=='\n' || buf[0]=='#') continue; if (sscanf(buf,"%31s%31s%31s%31s",p_tty,ip,ports,dummy) != 3) { cj_Errlog("Config file format error: line=%d", lines); continue; } if (p_tty[0]=='#') continue; // 注释行 if (strncmp(p_tty, "ttyp", 4) != 0) { cj_Errlog("pty name error: lines=%d", lines); continue; } hp = gethostbyname(ip); if (hp) ipaddr = *(long *) hp->h_addr; else { ipaddr = inet_addr(ip); if (ipaddr==-1) { cj_Errlog("ip address error: lines=%d", lines); continue; } } port = atoi(ports); if (port <= 1024 || port >= 0x30000) { cj_Errlog("tcp port error: lines=%d", lines); continue; } for (pc=ConfRoot;pc;pc=pc->next) { if (strcmp(pc->p_tty, p_tty)==0) break; } if (pc==NULL) { pc = (PConfig) calloc(sizeof(Config),1); if (pc == NULL) { perror("calloc"); exit(2); } pc->next = NULL; if (tail) tail->next = pc; else ConfRoot = pc; tail = pc; strcpy(pc->p_tty, p_tty); AnyTimeout++; pc->status = IN_INIT; pc->flags = 0; pc->timeout = 0; pc->ptyfd = -1; pc->sockfd = -1; in.s_addr = ipaddr; cj_Errlog("new tty added:%s at %s:%d", pc->p_tty, inet_ntoa(in), port); } if (pc->status == IN_ACT || pc->status == SOCK_OK) { if (pc->ipaddr != ipaddr || pc->port != htons(port)) lost_connection(pc); } if (pc->status == WAIT_OK) { if (pc->ipaddr != ipaddr || pc->port != htons(port)) lost_listen(pc); } pc->ipaddr = ipaddr; pc->port = htons(port); pc->flags |= CONFIGURED; } // fclose(lockfp); endhostent(); done: for (pc=ConfRoot,tail=NULL;pc;pc=(tail?tail->next:ConfRoot)) { if (pc->flags & CONFIGURED) { tail = pc; continue; } /* 关闭未配置的伪终端 printf("Shutting down\n"); */ cj_Errlog("Shutting down: %s", pc->p_tty); close(pc->ptyfd); close(pc->waitfd); close(pc->sockfd);
if (tail==NULL) ConfRoot = pc->next; else tail->next = pc->next; free(pc); } cj_Errlog("read_config(%s) complete.", cnf_file); }
open_pty(PConfig pc) { int on = 1, target; long t = time(NULL); char p_tty[256];
sprintf(p_tty, "/dev/p%s", &pc->p_tty[1]); pc->ptyfd = open(p_tty, O_RDWR | O_NDELAY); // pc->ptyfd = open(p_tty, O_RDWR);
if (pc->ptyfd < 0) { // perror(pc->p_tty); cj_Errlog("error open %s", pc->p_tty); pc->timeout = t + 5; AnyTimeout++; pc->status = PTY_ERR; } else { /* pty devices */ ioctl(pc->ptyfd, TIOCPKT, &on); pc->status = PTY_OK; if (pc->ptyfd > MaxFD) MaxFD = pc->ptyfd; cj_Errlog("%s opened successfully", pc->p_tty); } }
open_socket(PConfig pc) { int on = 1, flags; long t = time(NULL); struct sockaddr_in sin; struct linger lg;
sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = pc->port; pc->waitfd = socket(AF_INET, SOCK_STREAM, 0); if (pc->waitfd < 0) { perror("socket"); exit(2); } flags = fcntl(pc->waitfd, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(pc->waitfd, F_SETFL, flags); lg.l_onoff = 1; lg.l_linger = 30; if (setsockopt(pc->waitfd,SOL_SOCKET,SO_LINGER,(char *)&lg,sizeof(lg)) < 0) { perror("SO_LINGER"); exit(2); } setsockopt(pc->waitfd,SOL_SOCKET,SO_REUSEADDR,NULL,0); if (bind(pc->waitfd, (struct sockaddr *)&sin, sizeof(sin))<0) { perror("Bind"); close(pc->waitfd); exit(2); } if (listen(pc->waitfd, 1)<0){ perror("Listen"); close(pc->waitfd); exit(2); } pc->sockfd = -1; pc->status = WAIT_OK; if (pc->waitfd > MaxFD) MaxFD = pc->waitfd; AnyTimeout++; // cj_Errlog("get waitfd ok: %d<%s>", pc->waitfd, pc->p_tty); }
lost_listen(PConfig pc) /* 失去监听套接字 */ { long t=time(NULL);
cj_Errlog("lost listen on %s at port %d", pc->p_tty, ntohs(pc->port)); close(pc->waitfd); pc->timeout = t + 5; AnyTimeout++; pc->status = WAIT_ERR; }
lost_connection(PConfig pc) /* 失去连接, 进入 wait */ { long t=time(NULL); struct in_addr from;
from.s_addr = pc->ipaddr; cj_Errlog("lost connection on %s from %s:%d", pc->p_tty, inet_ntoa(from), ntohs(pc->port)); pc->timeout = t + 5; AnyTimeout++; close(pc->sockfd); pc->status = PTY_OK; }
check_status(void) { PConfig pc; long t=time(NULL);
// cj_Errlog("Check status begin ", AnyTimeout); for (pc = ConfRoot;pc;pc=pc->next) { // cj_Errlog("Check %s: status=%d", pc->p_tty, pc->status); if (pc->status == IN_INIT) { /* 打开伪终端设备 */ AnyTimeout--; open_pty(pc); } else if (pc->status==PTY_ERR) { /* 超时结束重新尝试 */ if (pc->timeout <= t) { AnyTimeout--; open_pty(pc); } }
if (pc->status==PTY_OK) { /* 打开套接字, 进入 wait */ AnyTimeout--; open_socket(pc); } else if (pc->status==WAIT_ERR) { /* 超时结束重新尝试 */ if (pc->timeout <= t) { AnyTimeout--; open_socket(pc); } }
if (pc->status==WAIT_OK){ /* 等待客户连接 */ } else if (pc->status==SOCK_ERR){ AnyTimeout--; close(pc->sockfd); pc->status = WAIT_OK; }
if (pc->status == SOCK_OK){ // AnyTimeout--; pc->status = IN_ACT; close(pc->waitfd); } else if (pc->status == IN_ACT) AnyTimeout--; } // cj_Errlog("Check status end ", AnyTimeout); }
void mypty(void) { PConfig pc; fd_set infd, outfd, errfd; int n, len, on=1; char ch, *BufPtr; struct timeval tv; struct sockaddr_in from; char mesg[256];
sigset(SIGHUP, reread_config); for (;;) { while (ConfRoot == NULL) { // printf("mypty has nothing to do.\n"); /* 等待, 直到读完配置文件 */ pause(); } if (AnyTimeout) check_status(); /* 检查状态 */ FD_ZERO(&infd); FD_ZERO(&outfd); FD_ZERO(&errfd); for (pc=ConfRoot;pc;pc=pc->next) { if (pc->status != IN_ACT && pc->status != WAIT_OK){ if (pc->status==PTY_OK) read(pc->ptyfd, pc->pty_buf, BUFLEN); continue; } if (pc->status==IN_ACT){ FD_SET(pc->sockfd, &errfd); if (pc->pty_count > 0) FD_SET(pc->sockfd, &outfd); else FD_SET(pc->ptyfd, &infd);
if (pc->sock_count > 0) FD_SET(pc->ptyfd, &outfd); else FD_SET(pc->sockfd, &infd); } else FD_SET(pc->waitfd, &infd); } tv.tv_sec = 5; tv.tv_usec = 0; n = select(MaxFD+1, &infd, &outfd, &errfd, &tv); // cj_Errlog("select end of <%d>", n); if (n <= 0) { if (n < 0 && errno != EINTR) cj_Errlog("select return error:%d", errno); continue; } for (pc=ConfRoot;pc;pc=pc->next) { if (pc->status != IN_ACT && pc->status != WAIT_OK) continue; if (pc->status == IN_ACT){ BufPtr=pc->pty_buf;
if (FD_ISSET(pc->sockfd, &errfd)) { cj_Errlog("%s socket exception in errfd", pc->p_tty); lost_connection(pc); }
if (FD_ISSET(pc->ptyfd, &infd)) { pc->pty_count = read(pc->ptyfd, pc->pty_buf, BUFLEN); if (pc->pty_count<0) lost_connection(pc); // cj_Errlog("%s ptty in end<%d>", pc->p_tty, pc->pty_count); } if (FD_ISSET(pc->sockfd, &infd)) { pc->sock_count = read(pc->sockfd, pc->sock_buf, BUFLEN); if (pc->sock_count<=0) lost_connection(pc); // cj_Errlog("%s socket in end<%d>", pc->p_tty, pc->sock_count); }
if (FD_ISSET(pc->ptyfd, &outfd) || pc->sock_count>0) { // cj_Errlog("%s ptty out OK", pc->p_tty); if (write(pc->ptyfd, pc->sock_buf, pc->sock_count)<0) lost_connection(pc); pc->sock_count = 0; }
if (FD_ISSET(pc->ptyfd, &infd)) { if (pc->pty_count==0){ /* 描述字可读且读到0个字符 */ close(pc->ptyfd); sprintf(mesg, "/dev/p%s", &pc->p_tty[1]); pc->ptyfd = open(mesg, O_RDWR | O_NDELAY); if (pc->ptyfd<0) lost_connection(pc); else { ioctl(pc->ptyfd, TIOCPKT, &on); if (pc->ptyfd>MaxFD) MaxFD = pc->ptyfd; } } } if (FD_ISSET(pc->sockfd, &outfd) || pc->pty_count>0) { // cj_Errlog("%s socket out OK", pc->p_tty); if ( *BufPtr=='\0') { BufPtr++; if (write(pc->sockfd, BufPtr, --pc->pty_count)<0) lost_connection(pc); } else { if (send(pc->sockfd, BufPtr, 1, MSG_OOB)<0) lost_connection(pc); } pc->pty_count = 0; } } else{ if (FD_ISSET(pc->waitfd, &infd)) { /* 客户连接建立, 检查是否合法IP地址 */ // cj_Errlog("%s socket accept OK", pc->p_tty); len = sizeof(from); bzero((char *)&from,sizeof(from)); pc->sockfd = accept(pc->waitfd, (struct sockaddr *)&from, &len); // fcntl(pc->sockfd, F_SETFL, O_NDELAY); if (pc->sockfd<0) pc->status = SOCK_ERR; else{ if (from.sin_addr.s_addr != pc->ipaddr){ write(pc->sockfd, "Invalid custom address\r\n\7", 26); cj_Errlog("Remote address %s:%d denied", inet_ntoa(from.sin_addr), ntohs(pc->port)); pc->status = SOCK_ERR; } else{ sprintf(mesg, "Terminal ID: %s", pc->p_tty); write(pc->sockfd, mesg, strlen(mesg)+1);
伪终端主控程序 for SCO UNIX |
作者: 出处:Unix爱好者家园unix-cd.com 更新时间: 2005年08月03日
|
/* * 伪终端主控程序 for SCO UNIX * * Usage: mypty [-f config-file] [-l logdevice] * default config-file is /etc/mypty.conf * logdevice is /dev/tty12 * * cc -o mypty mypty.c -lsocket * 陈杰 2001/01/11 * * 注:本程序为简单计,各伪终端需使用不同的连接端口号 * 配置文件形如 * 终端号 合法地址 端口(需不重复) * ttyp11 192.0.0.1 2000 * ttyp11 192.0.0.2 2001 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "varargs.h"
#if defined(INTER) //struct tty { int x; }; #include #endif
// int LOGERR=1;
#define SCO32
#if !defined(TIOCPKT) #undef FIONBIO #include #endif
#define DEFAULT_CONFIG_FILE_NAME "/etc/mypty.conf" #define DEFAULT_LOGDEVICE "/dev/tty12" #define BUFLEN 1024
typedef struct myptyConfigStru Config, *PConfig;
struct myptyConfigStru { PConfig next; // 下一设备 char p_tty[32]; // 伪终端设备名 long ipaddr; // 合法客户地址 unsigned short port; // 侦听端口号 short status; // 状态 short flags; // 标志 long timeout; // 关闭连接的超时 int ptyfd; // 伪终端文件描述字 int sockfd; // 套接字 int waitfd; // 侦听套接字 char pty_buf[BUFLEN+1]; // 伪终端输入缓冲区 int pty_count; // 已输入字节数 char sock_buf[BUFLEN+1]; // 套接字缓冲区 int sock_count; // 已输入字节数 };
/* Define status */ #define IN_INIT 0 #define IN_ACT 1 #define PTY_OK 10 #define PTY_ERR 11 #define SOCK_OK 20 #define SOCK_ERR 21 #define WAIT_OK 30 #define WAIT_ERR 31
/* Define flags */ #define CONFIGURED 0x01 /* 已配置 */ #define INWAITCONN 0x02 /* 进入等待连接状态 */
PConfig szConf=NULL; PConfig ConfRoot=NULL; int AnyTimeout=0; int MaxFD=0; unsigned long localip=0; char *cnf_file=NULL; char *errname=NULL; pid_t mypid=-1;
void daemon_init(void); void mypty(void);
void cj_Errlog(va_alist) va_dcl { FILE *fp va_list args; char *fmt,buf[640]; struct tm *tm; time_t t;
// if (LOGERR){ fp = fopen(errname , "a" ) if (fp==NULL) return va_start(args); fmt = va_arg(args, char * ); vsprintf(buf, fmt, args ); va_end(args); t = time(NULL); tm = localtime(&t); if (mypid==-1) mypid = getpid(); fprintf(fp, "%04d-%02d-%02d %02d:%02d:%02d <%d>:%s\r\n", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, mypid, buf ) fclose(fp) // } return }
usage(void) { fprintf(stderr,"Usage: mypty [-f config-file] [-l logdevice]\n\7"); fprintf(stderr,"Default config-file is /etc/mypty.conf\n"); fprintf(stderr," logdevice is /dev/tty12\n"); fprintf(stderr,"Example:mypty -f /etc/mypty.conf\n"); fprintf(stderr," mypty -f /etc/mypty.conf -l /dev/null\n"); exit(-1); }
main(int argc, char *argv[]) { int c;
errname = DEFAULT_LOGDEVICE; cnf_file = DEFAULT_CONFIG_FILE_NAME; while ((c=getopt(argc, argv, "f:l:"))!=-1){ switch(c){ case 'f':cnf_file = optarg; if (access(cnf_file, R_OK)!=0){ perror(cnf_file); exit(2); } break; case 'l':errname = optarg; if (access(errname, F_OK)!=0) close(open(errname, O_CREAT, 0660)); if (access(errname, W_OK)!=0){ perror(errname); exit(2); } break; case '?':usage();break; default :fprintf(stderr,"Error options: %c <%d>", c, c); exit(1); } } daemon_init(); read_config(NULL); mypid = getpid(); mypty();
exit(0); }
static int lockfd=-1; static FILE *lockfp=NULL; void endproc(int sig) { PConfig pc;
for (pc=ConfRoot;ConfRoot;pc=ConfRoot){ close(pc->ptyfd); close(pc->waitfd); close(pc->sockfd); ConfRoot=pc->next; free(pc); } lockf(lockfd, F_ULOCK, 0); close(lockfd); cj_Errlog("Terminated signal received"); exit(0); }
void my_child(int sig) { int i, pid, stat;
pid = waitpid(-1, &stat, WNOHANG); while (pid>0) pid = waitpid(-1, &stat, WNOHANG); }
/* 转入后台, 监听客户连接 */ void daemon_init(void) { int i; int fd; int status; int frominit;
signal(SIGTERM, endproc); signal(SIGCLD, my_child); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif
/* 如果由 inittab 启动, 则无需手工进入后台 */ frominit = (getppid() == 1); if (!frominit) { switch (i=fork()) { case -1: perror("fork"); exit(1); case 0: break; default: exit(0); } }
umask(0); /* 回到根目录以避免文件系统装卸问题 */ chdir("/");
/* 设置成为新的进程组长 */ setpgrp();
/* 再次 fork 脱离控制台, 如果由 init 启动, 则父进程 wait */ switch (i=fork()) { case -1: perror("fork2"); exit(1); case 0: break; default: if (frominit) wait(&status); exit(0); } }
void reread_config(int sig) { /* 重读配置文件 */ cj_Errlog("Reconfigure: signal (%d) received.", sig); read_config(NULL); }
read_config(char *fname) { char buf[256], p_tty[32], ip[32], ports[32], dummy[64]; int lines=0, port; long ipaddr; PConfig pc, tail; struct hostent *hp; struct in_addr in;
if (fname) cnf_file = fname; cj_Errlog("read_config(%s) start.", cnf_file); if (lockfd==-1){ /* 第一次运行,测试锁 */ lockfd = open(cnf_file, O_RDWR); if (lockfd<0) { perror(cnf_file); exit(3); } if (lockf(lockfd, F_TLOCK, 0)<0){ cj_Errlog("Another copy of this program is running..."); close(lockfd); exit(1); } else cj_Errlog("Filelock of %s successfully", cnf_file); } if (lockfp==NULL) lockfp = fdopen(lockfd, "r"); if (lockfp==NULL) { // perror(cnf_file); cj_Errlog("Error open config file:<%d>%s", errno, cnf_file); goto done; } rewind(lockfp); for (pc=ConfRoot,tail=NULL;pc;tail=pc,pc=pc->next) pc->flags &= ~CONFIGURED; /* 置未配置标志 */ while (fgets(buf, sizeof(buf), lockfp)) { lines++; if (buf[0]==0 || buf[0]=='\n' || buf[0]=='#') continue; if (sscanf(buf,"%31s%31s%31s%31s",p_tty,ip,ports,dummy) != 3) { cj_Errlog("Config file format error: line=%d", lines); continue; } if (p_tty[0]=='#') continue; // 注释行 if (strncmp(p_tty, "ttyp", 4) != 0) { cj_Errlog("pty name error: lines=%d", lines); continue; } hp = gethostbyname(ip); if (hp) ipaddr = *(long *) hp->h_addr; else { ipaddr = inet_addr(ip); if (ipaddr==-1) { cj_Errlog("ip address error: lines=%d", lines); continue; } } port = atoi(ports); if (port <= 1024 || port >= 0x30000) { cj_Errlog("tcp port error: lines=%d", lines); continue; } for (pc=ConfRoot;pc;pc=pc->next) { if (strcmp(pc->p_tty, p_tty)==0) break; } if (pc==NULL) { pc = (PConfig) calloc(sizeof(Config),1); if (pc == NULL) { perror("calloc"); exit(2); } pc->next = NULL; if (tail) tail->next = pc; else ConfRoot = pc; tail = pc; strcpy(pc->p_tty, p_tty); AnyTimeout++; pc->status = IN_INIT; pc->flags = 0; pc->timeout = 0; pc->ptyfd = -1; pc->sockfd = -1; in.s_addr = ipaddr; cj_Errlog("new tty added:%s at %s:%d", pc->p_tty, inet_ntoa(in), port); } if (pc->status == IN_ACT || pc->status == SOCK_OK) { if (pc->ipaddr != ipaddr || pc->port != htons(port)) lost_connection(pc); } if (pc->status == WAIT_OK) { if (pc->ipaddr != ipaddr || pc->port != htons(port)) lost_listen(pc); } pc->ipaddr = ipaddr; pc->port = htons(port); pc->flags |= CONFIGURED; } // fclose(lockfp); endhostent(); done: for (pc=ConfRoot,tail=NULL;pc;pc=(tail?tail->next:ConfRoot)) { if (pc->flags & CONFIGURED) { tail = pc; continue; } /* 关闭未配置的伪终端 printf("Shutting down\n"); */ cj_Errlog("Shutting down: %s", pc->p_tty); close(pc->ptyfd); close(pc->waitfd); close(pc->sockfd);
if (tail==NULL) ConfRoot = pc->next; else tail->next = pc->next; free(pc); } cj_Errlog("read_config(%s) complete.", cnf_file); }
open_pty(PConfig pc) { int on = 1, target; long t = time(NULL); char p_tty[256];
sprintf(p_tty, "/dev/p%s", &pc->p_tty[1]); pc->ptyfd = open(p_tty, O_RDWR | O_NDELAY); // pc->ptyfd = open(p_tty, O_RDWR);
if (pc->ptyfd < 0) { // perror(pc->p_tty); cj_Errlog("error open %s", pc->p_tty); pc->timeout = t + 5; AnyTimeout++; pc->status = PTY_ERR; } else { /* pty devices */ ioctl(pc->ptyfd, TIOCPKT, &on); pc->status = PTY_OK; if (pc->ptyfd > MaxFD) MaxFD = pc->ptyfd; cj_Errlog("%s opened successfully", pc->p_tty); } }
open_socket(PConfig pc) { int on = 1, flags; long t = time(NULL); struct sockaddr_in sin; struct linger lg;
sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = pc->port; pc->waitfd = socket(AF_INET, SOCK_STREAM, 0); if (pc->waitfd < 0) { perror("socket"); exit(2); } flags = fcntl(pc->waitfd, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(pc->waitfd, F_SETFL, flags); lg.l_onoff = 1; lg.l_linger = 30; if (setsockopt(pc->waitfd,SOL_SOCKET,SO_LINGER,(char *)&lg,sizeof(lg)) < 0) { perror("SO_LINGER"); exit(2); } setsockopt(pc->waitfd,SOL_SOCKET,SO_REUSEADDR,NULL,0); if (bind(pc->waitfd, (struct sockaddr *)&sin, sizeof(sin))<0) { perror("Bind"); close(pc->waitfd); exit(2); } if (listen(pc->waitfd, 1)<0){ perror("Listen"); close(pc->waitfd); exit(2); } pc->sockfd = -1; pc->status = WAIT_OK; if (pc->waitfd > MaxFD) MaxFD = pc->waitfd; AnyTimeout++; // cj_Errlog("get waitfd ok: %d<%s>", pc->waitfd, pc->p_tty); }
lost_listen(PConfig pc) /* 失去监听套接字 */ { long t=time(NULL);
cj_Errlog("lost listen on %s at port %d", pc->p_tty, ntohs(pc->port)); close(pc->waitfd); pc->timeout = t + 5; AnyTimeout++; pc->status = WAIT_ERR; }
lost_connection(PConfig pc) /* 失去连接, 进入 wait */ { long t=time(NULL); struct in_addr from;
from.s_addr = pc->ipaddr; cj_Errlog("lost connection on %s from %s:%d", pc->p_tty, inet_ntoa(from), ntohs(pc->port)); pc->timeout = t + 5; AnyTimeout++; close(pc->sockfd); pc->status = PTY_OK; }
check_status(void) { PConfig pc; long t=time(NULL);
// cj_Errlog("Check status begin ", AnyTimeout); for (pc = ConfRoot;pc;pc=pc->next) { // cj_Errlog("Check %s: status=%d", pc->p_tty, pc->status); if (pc->status == IN_INIT) { /* 打开伪终端设备 */ AnyTimeout--; open_pty(pc); } else if (pc->status==PTY_ERR) { /* 超时结束重新尝试 */ if (pc->timeout <= t) { AnyTimeout--; open_pty(pc); } }
if (pc->status==PTY_OK) { /* 打开套接字, 进入 wait */ AnyTimeout--; open_socket(pc); } else if (pc->status==WAIT_ERR) { /* 超时结束重新尝试 */ if (pc->timeout <= t) { AnyTimeout--; open_socket(pc); } }
if (pc->status==WAIT_OK){ /* 等待客户连接 */ } else if (pc->status==SOCK_ERR){ AnyTimeout--; close(pc->sockfd); pc->status = WAIT_OK; }
if (pc->status == SOCK_OK){ // AnyTimeout--; pc->status = IN_ACT; close(pc->waitfd); } else if (pc->status == IN_ACT) AnyTimeout--; } // cj_Errlog("Check status end ", AnyTimeout); }
void mypty(void) { PConfig pc; fd_set infd, outfd, errfd; int n, len, on=1; char ch, *BufPtr; struct timeval tv; struct sockaddr_in from; char mesg[256];
sigset(SIGHUP, reread_config); for (;;) { while (ConfRoot == NULL) { // printf("mypty has nothing to do.\n"); /* 等待, 直到读完配置文件 */ pause(); } if (AnyTimeout) check_status(); /* 检查状态 */ FD_ZERO(&infd); FD_ZERO(&outfd); FD_ZERO(&errfd); for (pc=ConfRoot;pc;pc=pc->next) { if (pc->status != IN_ACT && pc->status != WAIT_OK){ if (pc->status==PTY_OK) read(pc->ptyfd, pc->pty_buf, BUFLEN); continue; } if (pc->status==IN_ACT){ FD_SET(pc->sockfd, &errfd); if (pc->pty_count > 0) FD_SET(pc->sockfd, &outfd); else FD_SET(pc->ptyfd, &infd);
if (pc->sock_count > 0) FD_SET(pc->ptyfd, &outfd); else FD_SET(pc->sockfd, &infd); } else FD_SET(pc->waitfd, &infd); } tv.tv_sec = 5; tv.tv_usec = 0; n = select(MaxFD+1, &infd, &outfd, &errfd, &tv); // cj_Errlog("select end of <%d>", n); if (n <= 0) { if (n < 0 && errno != EINTR) cj_Errlog("select return error:%d", errno); continue; } for (pc=ConfRoot;pc;pc=pc->next) { if (pc->status != IN_ACT && pc->status != WAIT_OK) continue; if (pc->status == IN_ACT){ BufPtr=pc->pty_buf;
if (FD_ISSET(pc->sockfd, &errfd)) { cj_Errlog("%s socket exception in errfd", pc->p_tty); lost_connection(pc); }
if (FD_ISSET(pc->ptyfd, &infd)) { pc->pty_count = read(pc->ptyfd, pc->pty_buf, BUFLEN); if (pc->pty_count<0) lost_connection(pc); // cj_Errlog("%s ptty in end<%d>", pc->p_tty, pc->pty_count); } if (FD_ISSET(pc->sockfd, &infd)) { pc->sock_count = read(pc->sockfd, pc->sock_buf, BUFLEN); if (pc->sock_count<=0) lost_connection(pc); // cj_Errlog("%s socket in end<%d>", pc->p_tty, pc->sock_count); }
if (FD_ISSET(pc->ptyfd, &outfd) || pc->sock_count>0) { // cj_Errlog("%s ptty out OK", pc->p_tty); if (write(pc->ptyfd, pc->sock_buf, pc->sock_count)<0) lost_connection(pc); pc->sock_count = 0; }
if (FD_ISSET(pc->ptyfd, &infd)) { if (pc->pty_count==0){ /* 描述字可读且读到0个字符 */ close(pc->ptyfd); sprintf(mesg, "/dev/p%s", &pc->p_tty[1]); pc->ptyfd = open(mesg, O_RDWR | O_NDELAY); if (pc->ptyfd<0) lost_connection(pc); else { ioctl(pc->ptyfd, TIOCPKT, &on); if (pc->ptyfd>MaxFD) MaxFD = pc->ptyfd; } } } if (FD_ISSET(pc->sockfd, &outfd) || pc->pty_count>0) { // cj_Errlog("%s socket out OK", pc->p_tty); if ( *BufPtr=='\0') { BufPtr++; if (write(pc->sockfd, BufPtr, --pc->pty_count)<0) lost_connection(pc); } else { if (send(pc->sockfd, BufPtr, 1, MSG_OOB)<0) lost_connection(pc); } pc->pty_count = 0; } } else{ if (FD_ISSET(pc->waitfd, &infd)) { /* 客户连接建立, 检查是否合法IP地址 */ // cj_Errlog("%s socket accept OK", pc->p_tty); len = sizeof(from); bzero((char *)&from,sizeof(from)); pc->sockfd = accept(pc->waitfd, (struct sockaddr *)&from, &len); // fcntl(pc->sockfd, F_SETFL, O_NDELAY); if (pc->sockfd<0) pc->status = SOCK_ERR; else{ if (from.sin_addr.s_addr != pc->ipaddr){ write(pc->sockfd, "Invalid custom address\r\n\7", 26); cj_Errlog("Remote address %s:%d denied", inet_ntoa(from.sin_addr), ntohs(pc->port)); pc->status = SOCK_ERR; } else{ sprintf(mesg, "Terminal ID: %s", pc->p_tty); write(pc->sockfd, mesg, strlen(mesg)+1); pc->status = SOCK_OK; cj_Errlog("Remote address %s:%d accepted at %s", inet_ntoa(from.sin_addr), ntohs(pc->port), pc->p_tty); if (pc->sockfd > MaxFD) MaxFD = pc->sockfd; } } AnyTimeout++; } } } } }
| | |
pc->status = SOCK_OK; cj_Errlog("Remote address %s:%d accepted at %s", inet_ntoa(from.sin_addr), ntohs(pc->port), pc->p_tty); if (pc->sockfd > MaxFD) MaxFD = pc->sockfd; } } AnyTimeout++; } } } } }
| | |