home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / sredird / telnetcpcd-1.09.tar.gz / telnetcpcd-1.09.tar / telnetcpcd.c < prev    next >
C/C++ Source or Header  |  2003-08-12  |  10KB  |  380 lines

  1. /*
  2.     telnetcpcd.c
  3.  
  4.     Copyright (c) 2002,2003 Thomas J Pinkl <tom@pinkl.com>
  5.  
  6.     Telnet Com Port Control (RFC 2217) daemon
  7. */
  8.  
  9. /* char *version = "Version 1.00 05/22/2002"; */
  10. /* char *version = "Version 1.01 10/24/2002"; */        /* idle timer */
  11. /* char *version = "Version 1.02 11/18/2002"; */        /* LOGOUT option */
  12. /* char *version = "Version 1.03 11/25/2002"; */        /* removed LOGOUT option */
  13. /* char *version = "Version 1.04 11/25/2002"; */        /* LOGOUT option is back */
  14. /* char *version = "Version 1.05 12/03/2002"; */        /* LOGOUT option is configurable */
  15. /* char *version = "Version 1.06 12/06/2002"; */        /* -n option */
  16. /* char *version = "Version 1.07 12/12/2002"; */        /* -w option */
  17. /* char *version = "Version 1.08 02/05/2003"; */        /* use port 3696 by default */
  18. char *version = "Version 1.09 08/12/2003";                /* code cleanup */
  19.  
  20. #define INIT_KEYWORDS
  21. #include "telnetcpcd.h"
  22.  
  23. /*
  24.     local functions 
  25. */
  26. int GetOpts(int, char **);
  27. void usage(void);
  28. void telnetcpcd_init(void);
  29. void telnetcpcd_cleanup(void);
  30. int sane_config(struct config_t *conf);
  31. void creat_pidfile(void);
  32. int is_dir(char *name);
  33. int lookup_user(char *user,uid_t *uid);
  34. int lookup_group(char *group,gid_t *gid);
  35.  
  36. /*
  37.     global variables
  38. */
  39. char *progname = NULL;                    /* program name */
  40. char *configfile = NULL;                /* config file name */
  41. int telnetcpcd_port = TELNETCPCD_SERVER_TCP_PORT;
  42.                                         /* tcp port number for server */
  43. int Daemon = 0;                            /* become a daemon? */
  44. int signo = 0;                            /* received signal number */
  45. struct config_t conf;                    /* built from config file */
  46. int noquote = 0;                        /* don't quote IAC chars from serial lines */
  47. int useconds = 0;                        /* i/o wait in u-seconds */
  48.  
  49. /*
  50.     default config parameters 
  51. */
  52. char *def_servertype       = "concurrent";    /* or "iterative" */
  53. char *def_configfile       = "/etc/telnetcpcd.conf";
  54. char *def_pidfile          = "/var/run/telnetcpcd.pid";
  55. int   def_timeout          = 30;
  56. char *def_directory        = ".";    
  57. char *def_tmpdir           = "/tmp";
  58. int   def_ms_pollinterval  = 10;
  59. int   def_ls_pollinterval  = 30;
  60. int   def_reply_purge_data = 0;
  61. int   def_idletimer        = 0;
  62. int   def_send_logout      = 0;
  63.  
  64. int main(int argc, char **argv)
  65. {
  66.     progname = mybasename(argv[0]);        /* set our program name */
  67.     if (GetOpts(argc,argv) != 0) {
  68.         usage();
  69.         exit(2);
  70.     }
  71.  
  72.     if (Daemon) mydaemon(0,".");        /* become a daemon; handle SIGCLD */
  73.     umask(0066);                        /* no publicly readable files */
  74.     telnetcpcd_init();                    /* read config file, etc... */
  75.     install_signal_handlers();
  76.     creat_pidfile();                    /* write our pid to a file */
  77.     server(telnetcpcd_port);            /* create server */
  78.                                         /*   no return on success */
  79.  
  80.     telnetcpcd_cleanup();                /* close everything */
  81.     exit(0);
  82.     return(0);                            /* not reached */
  83. }
  84.  
  85. /*
  86.     initialize the parent process by reading the config 
  87.     file.
  88.  
  89.     if anything goes wrong here, we just exit.
  90.  
  91.     returns nothing.
  92. */
  93. void telnetcpcd_init(void)
  94. {
  95.     extern struct cf_entry kw_table[];    /* keyword table */
  96.     extern char *progname;                /* program name */
  97.     extern char *version;                /* version string */
  98.     extern char *configfile;            /* config file name */
  99.     extern char *def_configfile;        /* default config file name */
  100.     extern struct config_t conf;        /* built from config file */
  101.     extern int def_timeout;
  102.     extern int def_ms_pollinterval;
  103.     extern int def_ls_pollinterval;
  104.     extern int def_reply_purge_data;
  105.     extern int def_idletimer;
  106.     extern int def_send_logout;
  107.  
  108.     openlog(progname,LOG_PID|LOG_CONS|LOG_NOWAIT,SYSLOG_FACILITY);
  109.     syslog(LOG_INFO,"restart, %s",version);
  110.  
  111.     /*
  112.         build a hash table from our keyword table.  this must be 
  113.         done before reading the config file, since the hash table 
  114.         is used to validate its entries.
  115.     */
  116.     if (kw_init(kw_table) == -1)
  117.         exit(1);
  118.  
  119.     /*
  120.         set defaults for config file
  121.     */
  122.     memset(&conf,(int) '\0',sizeof(conf));
  123.     conf.timeout = def_timeout;
  124.     conf.ms_pollinterval = def_ms_pollinterval;
  125.     conf.ls_pollinterval = def_ls_pollinterval;
  126.     conf.reply_purge_data = def_reply_purge_data;
  127.     conf.idletimer = def_idletimer;
  128.     conf.send_logout = def_send_logout;
  129.  
  130.     if (configfile == NULL)
  131.         configfile = def_configfile;    /* use default */
  132.     if (read_config_file(configfile,&conf) != 0)
  133.         exit(1);
  134.     if (sane_config(&conf) != 0)        /* insure config params are sane */
  135.         exit(1);
  136. }
  137.  
  138. /*
  139.     insure config params are sane.  if some items were not 
  140.     specified in the config file, we can supply defaults. 
  141.  
  142.     returns 0 on success, 1 on failure
  143. */
  144. int sane_config(struct config_t *conf)
  145. {
  146.     extern char *def_servertype;
  147.     extern char *def_configfile;
  148.     extern char *def_pidfile;
  149.     extern int def_timeout;
  150.     extern char *def_directory;
  151.     extern char *def_tmpdir;
  152.     extern int def_ms_pollinterval;
  153.     extern int def_ls_pollinterval;
  154.     extern int def_reply_purge_data;
  155.     extern int def_idletimer;
  156.     extern int def_send_logout;
  157.     int i;
  158.  
  159.     if (conf->user == NULL) 
  160.         return(1);
  161.     if (lookup_user(conf->user,&conf->uid) != 0)
  162.         return(1);
  163.     if (conf->group == NULL) 
  164.         return(1);
  165.     if (lookup_group(conf->group,&conf->gid) != 0)
  166.         return(1);
  167.     if (conf->servertype == NULL) {
  168.         conf->servertype = strdup(def_servertype);
  169.     } else {                            /* check specified server type */
  170.         if ((strcmp(conf->servertype,"concurrent") != 0) && 
  171.             (strcmp(conf->servertype,"iterative") != 0)) {
  172.             syslog(LOG_ERR,"config: unknown server type: %s",conf->servertype);
  173.             return(1);
  174.         }
  175.     }
  176.     if (conf->pidfile == NULL)
  177.         conf->pidfile = strdup(def_pidfile);
  178.     if (conf->timeout <= 0)
  179.         conf->timeout = def_timeout;
  180.     if (conf->ms_pollinterval <= 0)
  181.         conf->ms_pollinterval = def_ms_pollinterval;
  182.     if (conf->ls_pollinterval <= 0)
  183.         conf->ls_pollinterval = def_ls_pollinterval;
  184.     if (conf->reply_purge_data < 0)
  185.         conf->reply_purge_data = def_reply_purge_data;
  186.     if (conf->directory == NULL)
  187.         conf->directory = strdup(def_directory);
  188.     if (conf->tmpdir == NULL)
  189.         conf->tmpdir = strdup(def_tmpdir);
  190.     if (conf->lockdir == NULL)
  191.         conf->lockdir = strdup(UUCPLOCK_DIR);
  192.     if (conf->locktemplate == NULL)
  193.         conf->locktemplate = strdup(UUCPLOCK_TMPL);
  194.     if (conf->idletimer < 0)
  195.         conf->idletimer = def_idletimer;
  196.     if (conf->send_logout < 0)
  197.         conf->send_logout = def_send_logout;
  198.     /*
  199.         make sure configured directories exist
  200.     */
  201.     if (is_dir(conf->directory) != 0) {
  202.         syslog(LOG_ERR,"%s is not a directory",conf->directory);
  203.         return(1);
  204.     }
  205.     if (is_dir(conf->tmpdir) != 0) {
  206.         syslog(LOG_ERR,"%s is not a directory",conf->tmpdir);
  207.         return(1);
  208.     }
  209.     if (is_dir(conf->lockdir) != 0) {
  210.         syslog(LOG_ERR,"%s is not a directory",conf->lockdir);
  211.         return(1);
  212.     }
  213.     /*
  214.         make sure we have one or more modems
  215.     */
  216.     if (conf->nmodems < 1) {
  217.         syslog(LOG_ERR,"no modems were configured");
  218.         return(1);
  219.     }
  220.     return(0);
  221. }
  222.  
  223. /*
  224.     returns 0 if name is a directory, otherwise it returns 1
  225. */
  226. int is_dir(char *name)
  227. {
  228.     struct stat st;
  229.  
  230.     if (stat(name,&st) == 0) {
  231.         if (S_ISDIR(st.st_mode)) {
  232.             return(0);
  233.         }
  234.     }
  235.     return(1);
  236. }
  237.  
  238. /*
  239.     look up the uid value for the specified user name.
  240.  
  241.     returns 0 and the uid on success, 1 on failure.
  242. */
  243. int lookup_user(char *user,uid_t *uid)
  244. {
  245.     struct passwd *pw;
  246.  
  247.     pw = getpwnam(user);
  248.     if (pw == NULL) {
  249.         syslog(LOG_ERR,"no passwd entry for %s",user);
  250.         return(1);
  251.     }
  252.     *uid = pw->pw_uid;
  253.     return(0);
  254. }
  255.  
  256. /*
  257.     look up the gid value for the specified group name.
  258.  
  259.     returns 0 and the gid on success, 1 on failure.
  260. */
  261. int lookup_group(char *group,gid_t *gid)
  262. {
  263.     struct group *gr;
  264.  
  265.     gr = getgrnam(group);
  266.     if (gr == NULL) {
  267.         syslog(LOG_ERR,"no group entry for %s",group);
  268.         return(1);
  269.     }
  270.     *gid = gr->gr_gid;
  271.     return(0);
  272. }
  273.  
  274. /*
  275.     perform some clean up operations on the parent process 
  276.  
  277.     returns nothing.
  278. */
  279. void telnetcpcd_cleanup(void)
  280. {
  281.     extern struct config_t conf;        /* built from config file */
  282.  
  283.     closelog();                            /* close the syslog */
  284.  
  285.     /*
  286.         free the memory allocated for items in the config file
  287.     */
  288.     if (conf.directory != NULL)            free(conf.directory);
  289.     if (conf.tmpdir != NULL)            free(conf.tmpdir);
  290.     if (conf.pidfile != NULL)            free(conf.pidfile);
  291.     if (conf.user != NULL)                free(conf.user);
  292.     if (conf.group != NULL)                free(conf.group);
  293.     if (conf.servertype != NULL)        free(conf.servertype);
  294.     if (conf.lockdir != NULL)            free(conf.lockdir);
  295.     if (conf.locktemplate != NULL)        free(conf.locktemplate);
  296.     free_all_modems(conf.modems);
  297.  
  298.     kw_done();                            /* destroy keyword hash table */
  299. }
  300.  
  301. /*
  302.     write our process id to a file.  this makes it easier for 
  303.     external programs to send us a signal.
  304.  
  305.     returns nothing.
  306. */
  307. void creat_pidfile(void)
  308. {
  309.     extern struct config_t conf;        /* built from config file */
  310.     int ret;
  311.  
  312.     ret = write_pidfile(conf.pidfile,O_WRONLY|O_CREAT|O_TRUNC,0644,getpid());
  313.     if (ret != 0) 
  314.         syslog(LOG_ERR,"cannot create pid file %s",conf.pidfile);
  315. }
  316.  
  317. /* 
  318.    process command line options
  319. */
  320. int GetOpts(int argc,char **argv)
  321. {
  322.     extern char *configfile;            /* configuration file */
  323.     extern int telnetcpcd_port;            /* tcp port number for server */
  324.     extern int Daemon;                    /* flag; become a daemon */
  325.     extern int noquote;                    /* flag; don't quote IAC chars from serial lines */
  326.     extern int useconds;                /* i/o wait in u-seconds */
  327.     extern char *optarg;
  328.     int c;                                /* option char */
  329.     int errflg = 0;                        /* error flag */
  330.  
  331.     while ((c = getopt(argc,(GETOPT_CAST) argv,"udnc:p:w:")) != EOF) {
  332.         switch(c) {
  333.         case 'u':
  334.             errflg++;
  335.             break;
  336.         case 'd':
  337.             Daemon++;
  338.             break;
  339.         case 'n':
  340.             noquote++;
  341.             break;
  342.         case 'c':
  343.             configfile = malloc(strlen(optarg)+1);
  344.             if (configfile != NULL)
  345.                 strcpy(configfile,optarg);
  346.             break;
  347.         case 'p':
  348.             telnetcpcd_port = atoi(optarg);
  349.             break;
  350.         case 'w':
  351.             useconds = atoi(optarg);
  352.             break;
  353.         case '?':
  354.         default:
  355.             errflg++;
  356.             break;
  357.         } /* switch */
  358.     } /* while */
  359.  
  360.     return(errflg);
  361. }
  362.  
  363. /*
  364.     display usage message
  365. */
  366. void usage(void)
  367. {
  368.     extern char *progname;                /* program name */
  369.     extern char *version;                /* version string */
  370.  
  371.     fprintf(stderr,"%s %s\n\n",progname,version);
  372.     fprintf(stderr,"usage: %s [-dn] [-c file] [-p port] [-w u-seconds]\n",progname);
  373.     fprintf(stderr,"\n");
  374.     fprintf(stderr,"    -d  become a daemon\n");
  375.     fprintf(stderr,"    -n  no quoting of IAC char from serial lines\n");
  376.     fprintf(stderr,"    -c  configuration file name.  default is %s\n",def_configfile);
  377.     fprintf(stderr,"    -p  tcp port number for server.  default is %d\n",TELNETCPCD_SERVER_TCP_PORT);
  378.     fprintf(stderr,"    -w  wait before reading socket and serial port, specified in u-seconds\n");
  379. }
  380.