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 >
Wrap
C/C++ Source or Header
|
2003-08-12
|
10KB
|
380 lines
/*
telnetcpcd.c
Copyright (c) 2002,2003 Thomas J Pinkl <tom@pinkl.com>
Telnet Com Port Control (RFC 2217) daemon
*/
/* char *version = "Version 1.00 05/22/2002"; */
/* char *version = "Version 1.01 10/24/2002"; */ /* idle timer */
/* char *version = "Version 1.02 11/18/2002"; */ /* LOGOUT option */
/* char *version = "Version 1.03 11/25/2002"; */ /* removed LOGOUT option */
/* char *version = "Version 1.04 11/25/2002"; */ /* LOGOUT option is back */
/* char *version = "Version 1.05 12/03/2002"; */ /* LOGOUT option is configurable */
/* char *version = "Version 1.06 12/06/2002"; */ /* -n option */
/* char *version = "Version 1.07 12/12/2002"; */ /* -w option */
/* char *version = "Version 1.08 02/05/2003"; */ /* use port 3696 by default */
char *version = "Version 1.09 08/12/2003"; /* code cleanup */
#define INIT_KEYWORDS
#include "telnetcpcd.h"
/*
local functions
*/
int GetOpts(int, char **);
void usage(void);
void telnetcpcd_init(void);
void telnetcpcd_cleanup(void);
int sane_config(struct config_t *conf);
void creat_pidfile(void);
int is_dir(char *name);
int lookup_user(char *user,uid_t *uid);
int lookup_group(char *group,gid_t *gid);
/*
global variables
*/
char *progname = NULL; /* program name */
char *configfile = NULL; /* config file name */
int telnetcpcd_port = TELNETCPCD_SERVER_TCP_PORT;
/* tcp port number for server */
int Daemon = 0; /* become a daemon? */
int signo = 0; /* received signal number */
struct config_t conf; /* built from config file */
int noquote = 0; /* don't quote IAC chars from serial lines */
int useconds = 0; /* i/o wait in u-seconds */
/*
default config parameters
*/
char *def_servertype = "concurrent"; /* or "iterative" */
char *def_configfile = "/etc/telnetcpcd.conf";
char *def_pidfile = "/var/run/telnetcpcd.pid";
int def_timeout = 30;
char *def_directory = ".";
char *def_tmpdir = "/tmp";
int def_ms_pollinterval = 10;
int def_ls_pollinterval = 30;
int def_reply_purge_data = 0;
int def_idletimer = 0;
int def_send_logout = 0;
int main(int argc, char **argv)
{
progname = mybasename(argv[0]); /* set our program name */
if (GetOpts(argc,argv) != 0) {
usage();
exit(2);
}
if (Daemon) mydaemon(0,"."); /* become a daemon; handle SIGCLD */
umask(0066); /* no publicly readable files */
telnetcpcd_init(); /* read config file, etc... */
install_signal_handlers();
creat_pidfile(); /* write our pid to a file */
server(telnetcpcd_port); /* create server */
/* no return on success */
telnetcpcd_cleanup(); /* close everything */
exit(0);
return(0); /* not reached */
}
/*
initialize the parent process by reading the config
file.
if anything goes wrong here, we just exit.
returns nothing.
*/
void telnetcpcd_init(void)
{
extern struct cf_entry kw_table[]; /* keyword table */
extern char *progname; /* program name */
extern char *version; /* version string */
extern char *configfile; /* config file name */
extern char *def_configfile; /* default config file name */
extern struct config_t conf; /* built from config file */
extern int def_timeout;
extern int def_ms_pollinterval;
extern int def_ls_pollinterval;
extern int def_reply_purge_data;
extern int def_idletimer;
extern int def_send_logout;
openlog(progname,LOG_PID|LOG_CONS|LOG_NOWAIT,SYSLOG_FACILITY);
syslog(LOG_INFO,"restart, %s",version);
/*
build a hash table from our keyword table. this must be
done before reading the config file, since the hash table
is used to validate its entries.
*/
if (kw_init(kw_table) == -1)
exit(1);
/*
set defaults for config file
*/
memset(&conf,(int) '\0',sizeof(conf));
conf.timeout = def_timeout;
conf.ms_pollinterval = def_ms_pollinterval;
conf.ls_pollinterval = def_ls_pollinterval;
conf.reply_purge_data = def_reply_purge_data;
conf.idletimer = def_idletimer;
conf.send_logout = def_send_logout;
if (configfile == NULL)
configfile = def_configfile; /* use default */
if (read_config_file(configfile,&conf) != 0)
exit(1);
if (sane_config(&conf) != 0) /* insure config params are sane */
exit(1);
}
/*
insure config params are sane. if some items were not
specified in the config file, we can supply defaults.
returns 0 on success, 1 on failure
*/
int sane_config(struct config_t *conf)
{
extern char *def_servertype;
extern char *def_configfile;
extern char *def_pidfile;
extern int def_timeout;
extern char *def_directory;
extern char *def_tmpdir;
extern int def_ms_pollinterval;
extern int def_ls_pollinterval;
extern int def_reply_purge_data;
extern int def_idletimer;
extern int def_send_logout;
int i;
if (conf->user == NULL)
return(1);
if (lookup_user(conf->user,&conf->uid) != 0)
return(1);
if (conf->group == NULL)
return(1);
if (lookup_group(conf->group,&conf->gid) != 0)
return(1);
if (conf->servertype == NULL) {
conf->servertype = strdup(def_servertype);
} else { /* check specified server type */
if ((strcmp(conf->servertype,"concurrent") != 0) &&
(strcmp(conf->servertype,"iterative") != 0)) {
syslog(LOG_ERR,"config: unknown server type: %s",conf->servertype);
return(1);
}
}
if (conf->pidfile == NULL)
conf->pidfile = strdup(def_pidfile);
if (conf->timeout <= 0)
conf->timeout = def_timeout;
if (conf->ms_pollinterval <= 0)
conf->ms_pollinterval = def_ms_pollinterval;
if (conf->ls_pollinterval <= 0)
conf->ls_pollinterval = def_ls_pollinterval;
if (conf->reply_purge_data < 0)
conf->reply_purge_data = def_reply_purge_data;
if (conf->directory == NULL)
conf->directory = strdup(def_directory);
if (conf->tmpdir == NULL)
conf->tmpdir = strdup(def_tmpdir);
if (conf->lockdir == NULL)
conf->lockdir = strdup(UUCPLOCK_DIR);
if (conf->locktemplate == NULL)
conf->locktemplate = strdup(UUCPLOCK_TMPL);
if (conf->idletimer < 0)
conf->idletimer = def_idletimer;
if (conf->send_logout < 0)
conf->send_logout = def_send_logout;
/*
make sure configured directories exist
*/
if (is_dir(conf->directory) != 0) {
syslog(LOG_ERR,"%s is not a directory",conf->directory);
return(1);
}
if (is_dir(conf->tmpdir) != 0) {
syslog(LOG_ERR,"%s is not a directory",conf->tmpdir);
return(1);
}
if (is_dir(conf->lockdir) != 0) {
syslog(LOG_ERR,"%s is not a directory",conf->lockdir);
return(1);
}
/*
make sure we have one or more modems
*/
if (conf->nmodems < 1) {
syslog(LOG_ERR,"no modems were configured");
return(1);
}
return(0);
}
/*
returns 0 if name is a directory, otherwise it returns 1
*/
int is_dir(char *name)
{
struct stat st;
if (stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
return(0);
}
}
return(1);
}
/*
look up the uid value for the specified user name.
returns 0 and the uid on success, 1 on failure.
*/
int lookup_user(char *user,uid_t *uid)
{
struct passwd *pw;
pw = getpwnam(user);
if (pw == NULL) {
syslog(LOG_ERR,"no passwd entry for %s",user);
return(1);
}
*uid = pw->pw_uid;
return(0);
}
/*
look up the gid value for the specified group name.
returns 0 and the gid on success, 1 on failure.
*/
int lookup_group(char *group,gid_t *gid)
{
struct group *gr;
gr = getgrnam(group);
if (gr == NULL) {
syslog(LOG_ERR,"no group entry for %s",group);
return(1);
}
*gid = gr->gr_gid;
return(0);
}
/*
perform some clean up operations on the parent process
returns nothing.
*/
void telnetcpcd_cleanup(void)
{
extern struct config_t conf; /* built from config file */
closelog(); /* close the syslog */
/*
free the memory allocated for items in the config file
*/
if (conf.directory != NULL) free(conf.directory);
if (conf.tmpdir != NULL) free(conf.tmpdir);
if (conf.pidfile != NULL) free(conf.pidfile);
if (conf.user != NULL) free(conf.user);
if (conf.group != NULL) free(conf.group);
if (conf.servertype != NULL) free(conf.servertype);
if (conf.lockdir != NULL) free(conf.lockdir);
if (conf.locktemplate != NULL) free(conf.locktemplate);
free_all_modems(conf.modems);
kw_done(); /* destroy keyword hash table */
}
/*
write our process id to a file. this makes it easier for
external programs to send us a signal.
returns nothing.
*/
void creat_pidfile(void)
{
extern struct config_t conf; /* built from config file */
int ret;
ret = write_pidfile(conf.pidfile,O_WRONLY|O_CREAT|O_TRUNC,0644,getpid());
if (ret != 0)
syslog(LOG_ERR,"cannot create pid file %s",conf.pidfile);
}
/*
process command line options
*/
int GetOpts(int argc,char **argv)
{
extern char *configfile; /* configuration file */
extern int telnetcpcd_port; /* tcp port number for server */
extern int Daemon; /* flag; become a daemon */
extern int noquote; /* flag; don't quote IAC chars from serial lines */
extern int useconds; /* i/o wait in u-seconds */
extern char *optarg;
int c; /* option char */
int errflg = 0; /* error flag */
while ((c = getopt(argc,(GETOPT_CAST) argv,"udnc:p:w:")) != EOF) {
switch(c) {
case 'u':
errflg++;
break;
case 'd':
Daemon++;
break;
case 'n':
noquote++;
break;
case 'c':
configfile = malloc(strlen(optarg)+1);
if (configfile != NULL)
strcpy(configfile,optarg);
break;
case 'p':
telnetcpcd_port = atoi(optarg);
break;
case 'w':
useconds = atoi(optarg);
break;
case '?':
default:
errflg++;
break;
} /* switch */
} /* while */
return(errflg);
}
/*
display usage message
*/
void usage(void)
{
extern char *progname; /* program name */
extern char *version; /* version string */
fprintf(stderr,"%s %s\n\n",progname,version);
fprintf(stderr,"usage: %s [-dn] [-c file] [-p port] [-w u-seconds]\n",progname);
fprintf(stderr,"\n");
fprintf(stderr," -d become a daemon\n");
fprintf(stderr," -n no quoting of IAC char from serial lines\n");
fprintf(stderr," -c configuration file name. default is %s\n",def_configfile);
fprintf(stderr," -p tcp port number for server. default is %d\n",TELNETCPCD_SERVER_TCP_PORT);
fprintf(stderr," -w wait before reading socket and serial port, specified in u-seconds\n");
}