#ifndef LINT
static char *rcsid="$Id: whosond.c,v 1.24 2003/08/14 12:50:35 crosser Exp $";
#endif
/*
$Log: whosond.c,v $
Revision 1.24 2003/08/14 12:50:35 crosser
Memory leak in the client code (ilya@glas.net)
Changes to recent autoconf/automake (woods@weird.com)
use pidfile() if it exists (woods@weird.com)
Revision 1.23 2001/09/23 13:29:17 crosser
change gid to uid in setreuid
Revision 1.22 2001/09/21 21:31:38 crosser
even more paranoia added
Revision 1.21 2001/09/21 06:15:56 crosser
more cleanup in revoking privileges, warnings in configure, version change
Revision 1.20 2001/09/20 21:24:28 crosser
Some cleanup of security measures
Revision 1.19 2001/09/20 06:09:36 crosser
clear suppliementary groups in whosond
Revision 1.18 2001/09/20 05:56:39 crosser
chroot() for whosond
Revision 1.17 1999/12/28 13:25:34 crosser
check for setreuid; added getopt to cvs
Revision 1.16 1999/11/26 17:18:57 crosser
tune for sunos4
Revision 1.15 1999/10/06 11:19:52 crosser
Handle SIGPIPE in the server
Fix (kludge) for private fields in the config struct
Make beta3 version
Revision 1.14 1999/07/27 17:17:18 crosser
remove include version.h
Revision 1.13 1998/07/28 17:51:53 crosser
make 64bit architecure happy
Revision 1.12 1998/07/05 00:26:18 crosser
Change copyright
Revision 1.11 1998/07/05 00:01:27 crosser
add user and group set
Revision 1.10 1998/07/03 09:32:48 crosser
autoconf for signal and detach
Revision 1.9 1998/07/02 18:17:12 crosser
fix proc. of -v option
Revision 1.8 1998/07/02 18:01:15 crosser
change error reporting to syslog
Revision 1.7 1998/07/01 21:55:16 crosser
cosmetics
Revision 1.6 1998/07/01 13:39:18 crosser
make it work on Solaris
Revision 1.5 1998/07/01 05:18:09 crosser
minor warnings fix
Revision 1.4 1998/07/01 05:01:22 crosser
Big reorganization
*/
/*
WHAT IS IT:
Implementation of experimental "whoson" protocol
AUTHOR:
Eugene G. Crosser <crosser@average.org>
COPYRIGHT:
Public domain
*/
#include "config.h"
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#ifndef OPTARG_DEFINED
#include <getopt.h>
#endif
#include "whosond.h"
#include "serv_common.h"
#include "rtconfig.h"
#include "report.h"
int wso_verbose=0;
static void showver(char *name)
{
fprintf(stderr,"%s Version %s Build %s\n",name,VERSION,__DATE__);
}
static void showhelp(char *name)
{
fprintf(stderr,"Usage: %s -I configfile -V -v -h\n",name);
fprintf(stderr,"\t-I configfile\t- replacement config [default: %s]\n",DEFAULT_CONFIG);
fprintf(stderr,"\t-d\t\t- do not go to background\n");
fprintf(stderr,"\t-V\t\t- print version\n");
fprintf(stderr,"\t-v\t\t- increase verbosity\n");
fprintf(stderr,"\t-h\t\t- print this help message\n");
}
int main(int argc, char *argv[])
{
struct _evdesc (*evvec[FD_SETSIZE]) (int fd, void *priv);
void *priv[FD_SETSIZE];
struct _evdesc evdesc;
struct _servdesc *servdesc;
int i;
char *configfile=DEFAULT_CONFIG;
int daemon=1;
while ((i=getopt(argc,argv,"I:dvVh")) != EOF) switch (i) {
case 'I':
/* if someone decides to modify the name displayed in
the "ps" output it may be useful to copy the arg... */
configfile=(char *)malloc(strlen(optarg)+1);
strcpy(configfile,optarg);
break;
case 'd':
daemon=0;
break;
case 'V':
showver(argv[0]);
return 0;
case 'v':
wso_verbose++;
break;
case 'h':
showhelp(argv[0]);
return 0;
default:
showhelp(argv[0]);
return 1;
}
if (daemon) {
int child;
if ((child=fork()) > 0) {
sleep(1);
return 0;
} else if (child < 0) {
ERRLOG((LOG_ERR,"fork error: %m"))
return 1;
} else {
fflush(stdin);
fflush(stdout);
fflush(stderr);
setbuf(stdin,NULL);
setbuf(stdout,NULL);
setbuf(stderr,NULL);
close(0);
close(1);
close(2);
open("/dev/null",O_RDWR);
dup(0);
dup(0);
#ifdef HAVE_SETSID
setsid();
#else
#ifdef HAVE_SETPGRP
#ifdef SETPGRP_VOID
setpgrp();
#else
setpgrp(0,0);
#endif
#endif
#endif
#ifdef HAVE_PIDFILE
pidfile((char *) NULL);
#endif
}
}
#ifdef HAVE_SYSLOG
tzset(); /* will not work automatically from chrooted environment */
openlog("whosond",LOG_CONS|LOG_PID
#ifdef LOG_NDELAY
|LOG_NDELAY
#endif
,LOG_DAEMON);
#endif
for (i=0;i<FD_SETSIZE;i++) {
evvec[i]=0;
priv[i]=0;
}
if (!(servdesc=wso_read_config(configfile,1))) {
ERRLOG((LOG_ERR,"No configured servers\n"))
return 1;
}
i=0;
for (;servdesc;servdesc=servdesc->next) {
evdesc=(servdesc->root.init)(servdesc->priv);
if (evdesc.fd >= 0) {
evvec[evdesc.fd]=evdesc.evproc;
priv[evdesc.fd]=evdesc.priv;
i++;
}
}
if (i == 0) {
ERRLOG((LOG_ERR,"No initialized servers\n"))
return 1;
}
if (newroot) {
#ifdef HAVE_CHROOT
if (chdir(newroot) == 0) {
if (chroot(newroot)) {
ERRLOG((LOG_ERR,"chroot(%s): %m\n",newroot))
return 1;
}
} else {
ERRLOG((LOG_ERR,"chdir(%s): %m\n",newroot))
return 1;
}
#else
ERRLOG((LOG_ERR,"function chroot() not present,\n"))
ERRLOG((LOG_ERR,"remove it from the config file\n"))
return 1;
#endif
}
if (rungid) {
#ifdef HAVE_SETGROUPS
/* Solar Designer says (quoting DJB) that there are
systems where you cannot set null list of supplementary
groups, and also there are systems where gid_t is
short but setgroups accepts array of int-s. Weird.
BTW I suspect that we may run into SIGBUS in the latter
case... */
gid_t groups[2];
groups[0]=groups[1]=rungid;
if (setgroups(1,groups) == -1) {
ERRLOG((LOG_ERR,"setgroups() failed: %m\n"))
return 1;
}
#endif
#ifdef HAVE_SETREUID
setregid(rungid,rungid);
#else
setegid(rungid);
setgid(rungid);
#endif
}
if (runuid) {
#ifdef HAVE_SETREUID
setreuid(runuid,runuid);
#else
seteuid(runuid);
setuid(runuid);
#endif
}
/* In case the client disconnects before reading our responce */
(void)signal(SIGPIPE,SIG_IGN);
/* is this setting saved after raising the signal on SysV?
User signal handlers are reset to SIG_DFL. Let us hope
that SIG_IGN is a special setting and is kept forever. */
mainloop(evvec,priv);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1