免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1658 | 回复: 0
打印 上一主题 下一主题

[SCO UNIX] 请教这个程序如何能正确运行? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-08-23 15:24 |只看该作者 |倒序浏览
这个程序能实现把主机当终端吗?如何运行,程序中提到的/etc/mypty.conf如何编写。
/*
* 伪终端主控程序 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 <stdio.h>;
#include <unistd.h>;
#include <errno.h>;
#include <string.h>;
#include <signal.h>;
#include <sys/types.h>;
#include <sys/wait.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;
#include <netdb.h>;
#include <fcntl.h>;
#include <time.h>;
#include <sys/ioctl.h>;
#include <sys/select.h>;
#include "varargs.h"

#if defined(INTER)
//struct tty { int x; };
#include <sys/pty.h>;
#endif

// int  LOGERR=1;

#define      SCO32

#if !defined(TIOCPKT)
#undef   FIONBIO
#include <sys/spt.h>;
#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=%d>;", 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=%d>;", 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++;
            }
         }
      }
   }
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP