Пример #1
0
/* 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;
}
Пример #2
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);
}