/* test if section 'section' is available, and leaves the filepointer at the end of the section name */ unsigned short int iniparser_has_section(Tiniparser *ip, const char *section) { char buffer[256], *found; fseek(ip->fd,0,SEEK_SET); DEBUG_MSG("iniparser_has_section, looking for %s from position %d\n",section,0); while ((found = iniparser_next_section(ip, buffer, 256))) { DEBUG_MSG("comparing %s and %s\n",section,found); if (strcmp(found, section)==0) { DEBUG_MSG("iniparser_has_section, return 1\n"); return 1; } } return 0; }
int main(int argc, char**argv) { Tsocketlink *sl[MAX_SOCKETS]; /* struct timeval startround, endround;*/ unsigned int numsockets = 0; int outsocket; unsigned int i; unsigned short int nodetach = 0; char *m_socket = NULL; char *pidfile = NULL; FILE *pidfilefd = NULL; unsigned int m_base=511, m_peak=2048; float m_interval=10.0; /* signal(SIGINT, sigterm_handler); signal(SIGTERM, sigterm_handler);*/ { int c; while (1) { int option_index = 0; static struct option long_options[] = { {"pidfile", required_argument, NULL, 0}, {"nodetach", no_argument, NULL, 0}, {"help", no_argument, NULL, 0}, {"socket", required_argument, NULL, 0}, {"base", required_argument, NULL, 0}, {"interval", required_argument, NULL, 0}, {"peak", required_argument, NULL, 0}, {"peek", required_argument, NULL, 0}, {NULL, 0, NULL, 0} }; c = getopt_long(argc, argv, "p:nh",long_options, &option_index); if (c == -1) break; switch (c) { case 0: switch (option_index) { case 0: pidfile = strdup(optarg); break; case 1: nodetach = 1; break; case 2: usage(); exit(0); case 3: m_socket = strdup(optarg); break; case 4: m_base = atoi(optarg); break; case 5: m_interval = (float)atof(optarg); break; case 6: m_peak = atoi(optarg); break; case 7: /* for backwards compatibility */ m_peak = atoi(optarg); break; } break; case 'p': pidfile = strdup(optarg); break; case 'n': nodetach = 1; break; case 'h': usage(); exit(0); } } } openlog(PROGRAMNAME, LOG_PID, LOG_DAEMON); outsocket = socket(AF_UNIX, SOCK_DGRAM, 0); DEBUG_MSG("outsocket at %d\n", outsocket); { struct sockaddr client_addr; strncpy(client_addr.sa_data, "/dev/log", sizeof(client_addr.sa_data)); client_addr.sa_family = AF_UNIX; if (connect(outsocket, &client_addr, sizeof(client_addr)) != 0) { /*DEBUG_MSG("connect returned erno %d: %s\n",errno, strerror(errno));*/ outsocket = socket(AF_UNIX, SOCK_STREAM, 0); if (connect(outsocket, &client_addr, sizeof(client_addr)) != 0) { syslog(LOG_CRIT, "version "VERSION", while connecting to /dev/log: %s", strerror(errno)); if (nodetach) printf("version "VERSION", while connecting to /dev/log: %s\n",strerror(errno) ); exit(1); } } if (nodetach) printf("opened /dev/log\n"); } if (!m_socket) { char buf[1024], *tmp; Tiniparser *ip = new_iniparser(CONFIGFILE); if (!ip) { syslog(LOG_CRIT, "version "VERSION", abort, could not parse configfile "CONFIGFILE); if (nodetach) printf("version "VERSION", abort, could not parse configfile "CONFIGFILE"\n"); exit(11); } while ((tmp = iniparser_next_section(ip, buf, 1024))) { if (!have_socket(tmp, sl, numsockets)) { unsigned int base=511, peak=2048; float interval=5.0; long prevpos, secpos; if (numsockets == MAX_SOCKETS) { syslog(LOG_NOTICE, "Warning: jk_socketd is compiled to support maximum %d sockets and more sockets are requested, not all sockets are opened!",MAX_SOCKETS); if (nodetach) printf("Warning: jk_socketd is compiled to support maximum %d sockets and more sockets are requested, not all sockets are opened!\n",MAX_SOCKETS); break; } prevpos = iniparser_get_position(ip); secpos = prevpos - strlen(tmp)-4; DEBUG_MSG("secpos=%ld, prevpos=%ld\n",secpos,prevpos); base = iniparser_get_int_at_position(ip, tmp, "base", secpos); peak = iniparser_get_int_at_position(ip, tmp, "peak", secpos); interval = iniparser_get_float_at_position(ip, tmp, "interval", secpos); iniparser_set_position(ip, secpos); if (10 > base || base > 1000000) base = 511; if (100 > peak || peak > 10000000 || peak < base) { /* for backwards compatibility we check 'peek' */ peak = iniparser_get_int_at_position(ip, tmp, "peek", secpos); if (100 > peak || peak > 10000000 || peak < base) { peak = 2048; } } if (0.01 > interval || interval > 60.0) interval = 5.0; sl[numsockets] = new_socketlink(outsocket, tmp, base, peak, (int)(interval*1000000.0), nodetach); if (sl[numsockets]) { syslog(LOG_NOTICE, "version "VERSION", listening on socket %s with rates [%d:%d]/%f",tmp,base,peak,interval); if (nodetach) printf("version "VERSION", listening on socket %s with rates [%d:%d]/%f\n",tmp,base,peak,interval); numsockets++; } else { if (nodetach) printf("version "VERSION", failed to create socket %s\n",tmp); } DEBUG_MSG("setting position to %ld\n",prevpos); iniparser_set_position(ip, prevpos); } else { syslog(LOG_NOTICE, "version "VERSION", socket %s is mentioned multiple times in config file",tmp); if (nodetach) printf("version "VERSION", socket %s is mentioned multiple times in config file\n",tmp); } } } else { unsigned int base=m_base, peak=m_peak; float interval=m_interval; if (10 > base || base > 1000000) base = 511; if (100 > peak || peak > 10000000 || peak < base) peak = 2048; if (0.01 > interval || m_interval > 60.0) interval = 5.0; sl[numsockets] = new_socketlink(outsocket, m_socket, base, peak, (int)(interval*1000000.0), nodetach); if (sl[numsockets]) { syslog(LOG_NOTICE, "version "VERSION", listening on socket %s with rates [%d:%d]/%f",m_socket,base,peak,interval); if (nodetach) printf("version "VERSION", listening on socket %s with rates [%d:%d]/%f\n",m_socket,base,peak,interval); numsockets++; } else { if (nodetach) printf("version "VERSION",failed to create socket %s\n",m_socket); } } if (numsockets == 0) { printf("version "VERSION", no sockets specified in configfile "CONFIGFILE" or on commandline, nothing to do, exiting...\n"); syslog(LOG_ERR,"version "VERSION", no sockets specified in configfile "CONFIGFILE" or on commandline, nothing to do, exiting..."); exit(1); } if (pidfile) pidfilefd = fopen(pidfile, "w"); /* now chroot() to some root:root dir without binaries, and change to nobody:nogroup */ { struct passwd *pw = getpwnam("nobody"); int ret; char *path = INIPREFIX; if (!pw) { syslog(LOG_ERR, "cannot get UID and GID for user nobody"); if (nodetach) printf("cannot get UID and GID for user nobody"); } ret = testsafepath(path, 0,0); if (ret != 0) { syslog(LOG_ERR, "abort, path %s is not owned root:root or does not have 0644 permissions\n",path); exit(53); } if (!(chdir(path)==0 && chroot(path)==0)) { syslog(LOG_ERR, "failed to chroot to "INIPREFIX); if (nodetach) printf("failed to chroot to "INIPREFIX); } if (pw) { if (setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { syslog(LOG_ERR, "failed to change to user nobody (uid=%d, gid=%d)", pw->pw_uid, pw->pw_gid); if (nodetach) printf("failed to change to user nobody (uid=%d, gid=%d)\n", pw->pw_uid, pw->pw_gid); } } } if (!nodetach) { /* detach and set the detached process as the new process group leader */ if (fork() != 0) { DEBUG_MSG("exit process %d\n", getpid()); exit(0); } DEBUG_MSG("after fork(), process id %d continues\n", getpid()); setsid(); } if (pidfile) { if (pidfilefd) { /* we should do this using fscanf(pidfilefd,"%d", getpid()) */ char buf[32]; unsigned int size; size = snprintf(buf, 32, "%d", getpid()); fwrite(buf, size, sizeof(char), pidfilefd); fclose(pidfilefd); } else { syslog(LOG_NOTICE, "failed to write pid to %s", pidfile); } } /* use sl[0] for the main process */ for (i=1; i<numsockets; i++) { pthread_create(&sl[i]->thread, NULL,(void*)&socketlink_handle, (void*) sl[i]); DEBUG_MSG("created thread %i for %s\n",i,sl[i]->inpath); } DEBUG_MSG("main thread starting work on socket\n"); socketlink_handle(sl[0]); /* DEBUG_MSG("pause() for process %d\n",getpid()); pause(); DEBUG_MSG("before clean_exit\n"); clean_exit(numsockets,sl); DEBUG_MSG("after clean_exit\n"); if (nodetach) printf("caught signal, exiting\n");*/ exit(0); }