Esempio n. 1
0
static void
ngx_procs_process_init(ngx_cycle_t *cycle, ngx_proc_module_t *module,
    ngx_int_t priority)
{
    sigset_t          set;
    ngx_int_t         n;
    ngx_uint_t        i;
    struct rlimit     rlmt;
    ngx_core_conf_t  *ccf;
    ngx_listening_t  *ls;

    if (ngx_set_environment(cycle, NULL) == NULL) {
        /* fatal */
        exit(2);
    }

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (priority != 0) {
        if (setpriority(PRIO_PROCESS, 0, (int) priority) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "process %V setpriority(%i) failed", &module->name,
                          priority);
        }
    }

    if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
        rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;

        if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "process %V setrlimit(RLIMIT_NOFILE, %i) failed",
                          &module->name, ccf->rlimit_nofile);
        }
    }

    if (ccf->rlimit_core != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
        rlmt.rlim_max = (rlim_t) ccf->rlimit_core;

        if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "process %V setrlimit(RLIMIT_CORE, %O) failed",
                          &module->name, ccf->rlimit_core);
        }
    }

#ifdef RLIMIT_SIGPENDING
    if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
        rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
        rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;

        if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "process %V setrlimit(RLIMIT_SIGPENDING, %i) failed",
                          &module->name, ccf->rlimit_sigpending);
        }
    }
#endif

    if (geteuid() == 0) {
        if (setgid(ccf->group) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "process %V setgid(%d) failed", &module->name,
                          ccf->group);
            /* fatal */
            exit(2);
        }

        if (initgroups(ccf->username, ccf->group) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "process %V initgroups(%s, %d) failed", &module->name,
                          ccf->username, ccf->group);
        }

        if (setuid(ccf->user) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "process %V setuid(%d) failed", &module->name,
                          ccf->user);
            /* fatal */
            exit(2);
        }
    }

#if (NGX_HAVE_PR_SET_DUMPABLE)

    /* allow coredump after setuid() in Linux 2.4.x */

    if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "process %V prctl(PR_SET_DUMPABLE) failed",
                      &module->name);
    }

#endif

    if (ccf->working_directory.len) {
        if (chdir((char *) ccf->working_directory.data) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "process %V chdir(\"%s\") failed", &module->name,
                          ccf->working_directory.data);
            /* fatal */
            exit(2);
        }
    }

    sigemptyset(&set);

    if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "process %V sigprocmask() failed", &module->name);
    }

    /*
     * disable deleting previous events for the listening sockets because
     * in the worker processes there are no events at all at this point
     */
    ls = cycle->listening.elts;

    for (i = 0; i < cycle->listening.nelts; i++) {
        ls[i].previous = NULL;
    }

    if (ngx_event_core_module.init_process(cycle) != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
                      "process %V init event error", &module->name);
        exit(2);
    }

    if (module->init) {
        if (module->init(cycle) != NGX_OK) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
                          "process %V process init error", &module->name);
            exit(2);
        }
    }


    for (n = 0; n < ngx_last_process; n++) {

        if (ngx_processes[n].pid == -1) {
            continue;
        }

        if (n == ngx_process_slot) {
            continue;
        }

        if (ngx_processes[n].channel[1] == -1) {
            continue;
        }

        if (close(ngx_processes[n].channel[1]) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "process %V close() channel failed", &module->name);
        }
    }

    if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "process %V close() channel failed", &module->name);
    }

#if 0
    ngx_last_process = 0;
#endif

    if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
                              ngx_procs_channel_handler)
        == NGX_ERROR)
    {
        /* fatal */
        exit(2);
    }
}
Esempio n. 2
0
File: child.c Progetto: xiu/child
int main(int argc, char **argv)
{
    startuptime = time(NULL);

    InitMem();

    int retval,mysql_lastconn,newfd,i,lastcheck,lastcheck2,nbfd;
    struct sockaddr_storage sa;
    socklen_t salen = sizeof(sa);
    Eclient *eclient;

    indata.nextline = indata.chunkbufentry = indata.chunkbuf;

    emerg = emerg_req = 0;

    eos = raws = verbose = vv = 0;
    int daemonize = 1;
    char op = 0;
    me.retry_attempts = me.nextretry = me.connected = 0;

    struct sigaction sig, old;
    memset(&sig,0,sizeof(sig));
    sig.sa_handler = sighandler;
    sigaction(SIGHUP,&sig,&old);
#ifdef USE_FILTER
    sigaction(SIGUSR1,&sig,&old);
#endif
    sigaction(SIGUSR2,&sig,&old);
    sigaction(SIGINT,&sig,&old);
    sigaction(SIGCHLD,&sig,&old);
    sigaction(SIGPIPE,&sig,&old);

    struct rlimit rlim;
    if ((getrlimit(RLIMIT_CORE, &rlim)) == -1) {
        perror("getrlimit");
        return -1;
    }
    rlim.rlim_cur = RLIM_INFINITY;
    if ((setrlimit(RLIMIT_CORE, &rlim)) == -1) {
        perror("setrlimit");
        return -1;
    }

    /* Setting default values */

    strcpy(me.nick,"C");
    strcpy(me.name,"services.geeknode.org");
    strcpy(me.ident,"cserve");
    strcpy(me.host,"geeknode.org");
    strcpy(me.linkpass,"f00p4ss");
    strcpy(me.mysql_host,"localhost");
    strcpy(me.mysql_db,"child");
    strcpy(me.mysql_login,"child");
    strcpy(me.mysql_passwd,"childp4ss");
    strcpy(me.logfile,"child.log");
    strcpy(me.guest_prefix,"Geek");
    strcpy(me.pl_logfile,"partyline.log");
    strcpy(me.sendmail,"/usr/sbin/sendmail -t");
    strcpy(me.sendfrom,"*****@*****.**");
    strcpy(me.usercloak,".users.geeknode.org");
    bzero(me.mysql_anope_host,32);
    bzero(me.mysql_anope_db,32);
    bzero(me.mysql_anope_login,32);
    bzero(me.mysql_anope_passwd,32);
    bzero(me.bindip,32);
    me.port = 4400;
    me.maxclones = 5;
    me.nick_expire = 45;
    me.chan_expire = 60;
    me.chanperuser = 10;
    me.level_oper = 100;
    me.level_admin = 500;
    me.level_root = 900;
    me.level_owner = 1000;
    me.limittime = 5;
    me.savedb_interval = 60;
    me.listen_port = 0;
#ifdef USE_GNUTLS
    me.ssl = 0;
#endif
    me.enable_exec = 0;
    me.anonymous_global = 0;
    me.maxmsgtime = 2;
    me.maxmsgnb = 5;
    me.ignoretime = 60;
    me.maxloginatt = 3;
    me.chlev_sadmin = 20;
    me.chlev_admin = 10;
    me.chlev_op = 5;
    me.chlev_halfop = 4;
    me.chlev_voice = 3;
    me.chlev_invite = 1;
    me.chlev_nostatus = -1;
    me.chlev_akick = -2;
    me.chlev_akb = -3;
    me.anopemd5 = 0;
#ifdef USE_FILTER
    me.filter = 0;
#endif
    me.emailreg = 0;

    /* -- */

    int ladb=0,cdb=0;

    while ((op = getopt(argc,argv,"acdhv")) != EOF) {
        switch(op) {
            case 'a':
                ladb = 1;
                break;
            case 'c':
                cdb = 1;
                break;
            case 'd':
                daemonize = 0;
                break;
            case 'v':
                if (verbose)
                    vv = 1;
                else
                    verbose = 1;
                break;
            case 'h':
            default:
                usage(argv[0]);
        }
    }

    loadconf(0);
#ifdef USE_FILTER
    if (me.filter)
        loadrulefile();
#endif

    if (ladb) {
        if (!connect_to_db()) {
            printf("Cannot connect to db\n");
            child_clean();
        }

        loadalldb();
        mysql_close(&mysql);

        if (!connect_to_anope_db()) {
            printf("Cannot connect to anope db\n");
            child_clean();
        }

        printf("Loading anope database... ");
        fflush(stdout);

        loadanopedb();
        mysql_close(&mysql2);
        printf("done.\n");
        printf("Saving databases... ");
        fflush(stdout);
        savealldb();
        printf("done.\n");
        printf("Anope database converted\n");
        child_clean();
    }

    if (cdb) {
        if (!connect_to_db()) {
            printf("Cannot connect to db\n");
            child_clean();
        }

        printf("Creating databases ... ");
        fflush(stdout);
        char tmp[512];
        sprintf(tmp,"CREATE TABLE IF NOT EXISTS `child_chans` (chname varchar(50) not null, founder varchar(50) not null, entrymsg blob not null, options int not null, mlock varchar(32) not null, autolimit int not null, lastseen int not null, regtime int not null, topic blob not null)");
        mysql_query(&mysql,tmp);

        sprintf(tmp,"CREATE TABLE IF NOT EXISTS `child_chan_access` (chname varchar(50) not null, username varchar(255) not null, level int not null, automode int not null default 1, suspended int not null, uflags int not null)");
        mysql_query(&mysql,tmp);

        sprintf(tmp,"CREATE TABLE IF NOT EXISTS `child_trusts` (hostname varchar(255) not null, clones int not null)");
        mysql_query(&mysql,tmp);

        sprintf(tmp,"CREATE TABLE IF NOT EXISTS `child_users` (username varchar(50) not null, authlevel int not null, seen int not null, vhost varchar(200) not null, md5_pass varchar(32) not null, options int not null, timeout int not null, email varchar(100) not null, regtime int not null)");
        mysql_query(&mysql,tmp);

        sprintf(tmp,"CREATE TABLE IF NOT EXISTS `child_links` (master varchar(50) not null, slave varchar(50) not null)");
        mysql_query(&mysql,tmp);

        sprintf(tmp,"CREATE TABLE IF NOT EXISTS `child_botserv_bots` (name varchar(50) not null, ident varchar(50) not null, host varchar(50) not null)");
        mysql_query(&mysql,tmp);

        sprintf(tmp,"CREATE TABLE IF NOT EXISTS `child_botserv_chans` (chan varchar(50) not null, bot varchar(50) not null)");
        mysql_query(&mysql,tmp);

        RunHooks(HOOK_CREATEDB,NULL,NULL,NULL,NULL);

        printf(" done.\n");
        mysql_close(&mysql);
        child_clean();
    }

    if (me.listen_port) {
        if (!Bind()) {
            fprintf(stderr,"Error while binding\n");
            child_clean();
        }
        pllog("Partyline created");
    }

    retval = ConnectToServer();
    switch(retval) {
        case -1:
            fprintf(stderr,"Failed to connect to %s:%d (connection timed out)\n",me.server,me.port);
            operlog("Failed to connect to %s:%d (connection timed out)",me.server,me.port);
            child_clean();
        case 0:
            fprintf(stderr,"Failed to connect to %s:%d",me.server,me.port);
            operlog("Failed to connect to %s:%d",me.server,me.port);
            child_clean();
    }

    if (verbose) printf("Connected to server\n");

    if (!connect_to_db()) {
        fprintf(stderr,"Cannot connect to mysql\n");
        operlog("Cannot connect to mysql db");
        child_clean();
    }

    if (verbose) printf("Connected to mysql DB\n");
    loadalldb();
    mysql_close(&mysql);
    if (verbose) printf("Logging in to server\n");
    SendInitToServer();
    me.connected = 1;
    if (verbose) printf("Logged in to server\n");

    SendRaw("EOS");

    lastcheck = lastcheck2 = mysql_lastconn = time(NULL);
    if (daemonize) daemon(1,0);
    write_pid();

    nbfd = build_poll();
    struct pollfd pfdout;
    pfdout.fd = sock;
    pfdout.events = POLLOUT;
    pfdout.revents = 0;

    while(1) {
        if (outdata.writebytes > 0) {
            retval = poll(&pfdout,1,1000);
            if (retval > 0 && (pfdout.revents & POLLOUT))
                flush_sendq();
        }
        retval = poll(ufds,nbfd,1000);
        if (retval > 0) {
            for (i=0;i<nbfd;i++) {
                if (ufds[i].revents & (POLLIN | POLLPRI)) {
                    switch(i) {
                        case 0:
                            if (!ReadChunk()) {
                                if (!me.connected || !eos) break;
                                operlog("Connection reset by peer");
                                savealldb();
                                eos = me.retry_attempts = me.connected = 0;
                                me.nextretry = time(NULL)+1;
                                cleanup_reconnect();
                                close(sock);
                                break;
                            }
                            while (GetLineFromChunk())
                                ParseLine();
                            break;
                        case 1:
                            if (!me.listen_port) break;
                            newfd = accept(esock,(struct sockaddr *)&sa,&salen);
                            if (eclient_list.size+1 >= ECL_MAXSOCK) {
                                close(newfd);
                                break;
                            }
                            fcntl(newfd,F_SETFL,O_NONBLOCK);
                            eclient = AddEclient(newfd,sa,salen);
                            sendto_all_butone(eclient,"*** Connection from %s (%s)",eclient->host,eclient->addr);
                            nbfd = build_poll(); i++;
                            break;
                        default:
                            eclient = find_eclient(ufds[i].fd);
                            if (!eclient) break;
                            int oldnbfd = nbfd;
                            int old_eclient_size = eclient_list.size;
                            if (!ReadPChunk(eclient)) {
                                if (eclient->authed == 1)
                                    sendto_all_butone(eclient,"*** User %s (%s) logged out (Connection reset by peer)",eclient->nick,eclient->host);
                                else
                                    sendto_all_butone(eclient,"*** Lost connection from %s",eclient->host);
                                close(eclient->fd);
                                DeleteEclient(eclient);
                                nbfd = build_poll();
                                i--;
                                break;
                            }
                            int tmpfd = eclient->fd;
                            while (GetLineFromPChunk(tmpfd))
                                ParseEclient(eclient);
                            if (old_eclient_size > eclient_list.size)
                                nbfd = build_poll();
                            if (nbfd < oldnbfd) i -= (oldnbfd - nbfd);
                            break;
                    }
                }
            }
        }

        int timenow = time(NULL);

        if (!me.connected && timenow - me.nextretry >= 0) {
            retval = ConnectToServer();
            if (retval == -1 || retval == 0) {
                me.retry_attempts++;
                operlog("Reconnecting attempt #%d failed (%s)",me.retry_attempts,retval ? "timeout" : "error");
                if (me.retry_attempts >= MAX_RECO_ATTEMPTS) {
                    operlog("Maximum reconnection attempts reached, exiting");
                    savealldb();
                    unloadallmod();
                    CloseAllSock();
                    child_clean();
                }
                me.nextretry = timenow + RECONNECT_DELAY;
            } else {
                SendInitToServer();
                me.connected = 1;
                me.nextretry = 0;
                SendRaw("EOS");
                operlog("Reconnected");
            }
            if (me.connected) continue;
        }

        if (timenow - mysql_lastconn >= 60*me.savedb_interval) {
            savealldb();
            mysql_lastconn = timenow;
        }

        if (timenow - lastcheck >= 1) {
            CheckGuests();
            CheckLimits();
            CheckTB();
            lastcheck = timenow;
        }

        if (timenow - lastcheck2 >= 60) {
            checkexpired();
            lastcheck2 = timenow;
        }
    }

    operlog("Program shouldn't reach this piece of code, WTF ? Saving DBs and exiting.");
    savealldb();
    unloadallmod();
    CloseAllSock();
    child_clean();

    return 0;
}
Esempio n. 3
0
static int startApp()
{
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    // Stop daemon and exit?
    if (args->isSet("s"))
    {
        KDEsuClient client;
        if (client.ping() == -1)
        {
            kError(1206) << "Daemon not running -- nothing to stop\n";
            exit(1);
        }
        if (client.stopServer() != -1)
        {
            kDebug(1206) << "Daemon stopped\n";
            exit(0);
        }
        kError(1206) << "Could not stop daemon\n";
        exit(1);
    }

    QString icon;
    if ( args->isSet("i"))
	icon = args->getOption("i");

    bool prompt = true;
    if ( args->isSet("d"))
	prompt = false;

    // Get target uid
    QByteArray user = args->getOption("u").toLocal8Bit();
    QByteArray auth_user = user;
    struct passwd *pw = getpwnam(user);
    if (pw == 0L)
    {
        kError(1206) << "User " << user << " does not exist\n";
        exit(1);
    }
    bool other_uid = (getuid() != pw->pw_uid);
    bool change_uid = other_uid;
    if (!change_uid) {
        char *cur_user = getenv("USER");
        if (!cur_user)
            cur_user = getenv("LOGNAME");
        change_uid = (!cur_user || user != cur_user);
    }

    // If file is writeable, do not change uid
    QString file = args->getOption("f");
    if (other_uid && !file.isEmpty())
    {
        if (file.at(0) != '/')
        {
            KStandardDirs dirs;
            file = dirs.findResource("config", file);
            if (file.isEmpty())
            {
                kError(1206) << "Config file not found: " << file << "\n";
                exit(1);
            }
        }
        QFileInfo fi(file);
        if (!fi.exists())
        {
            kError(1206) << "File does not exist: " << file << "\n";
            exit(1);
        }
        change_uid = !fi.isWritable();
    }

    // Get priority/scheduler
    QString tmp = args->getOption("p");
    bool ok;
    int priority = tmp.toInt(&ok);
    if (!ok || (priority < 0) || (priority > 100))
    {
        KCmdLineArgs::usageError(i18n("Illegal priority: %1", tmp));
        exit(1);
    }
    int scheduler = SuProcess::SchedNormal;
    if (args->isSet("r"))
        scheduler = SuProcess::SchedRealtime;
    if ((priority > 50) || (scheduler != SuProcess::SchedNormal))
    {
        change_uid = true;
        auth_user = "******";
    }

    // Get command
    if (args->isSet("c"))
    {
        command = args->getOption("c").toLocal8Bit();
        // Accepting additional arguments here is somewhat weird,
        // but one can conceive use cases: have a complex command with
        // redirections and additional file names which need to be quoted
        // safely.
    }
    else
    {
        if( args->count() == 0 )
        {
            KCmdLineArgs::usageError(i18n("No command specified."));
            exit(1);
        }
    }
    for (int i = 0; i < args->count(); i++)
    {
        command += ' ';
        command += QFile::encodeName(KShell::quoteArg(args->arg(i)));
    }

    // Don't change uid if we're don't need to.
    if (!change_uid)
    {
        int result = system(command);
        result = WEXITSTATUS(result);
        return result;
    }

    // Check for daemon and start if necessary
    bool just_started = false;
    bool have_daemon = true;
    KDEsuClient client;
    if (!client.isServerSGID())
    {
        kWarning(1206) << "Daemon not safe (not sgid), not using it.\n";
        have_daemon = false;
    }
    else if (client.ping() == -1)
    {
        if (client.startServer() == -1)
        {
            kWarning(1206) << "Could not start daemon, reduced functionality.\n";
            have_daemon = false;
        }
        just_started = true;
    }

    // Try to exec the command with kdesud.
    bool keep = !args->isSet("n") && have_daemon;
    bool terminal = args->isSet("t");
    bool withIgnoreButton = args->isSet("ignorebutton");
    int winid = -1;
    bool attach = args->isSet("attach");
    if(attach) {
        winid = args->getOption("attach").toInt(&attach, 0);  //C style parsing.  If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
        if(!attach)
            kWarning(1206) << "Specified winid to attach to is not a valid number";
    } else if(args->isSet("embed")) {
        /* KDialog originally used --embed for attaching the dialog box.  However this is misleading and so we changed to --attach.
         * For consistancy, we silently map --embed to --attach */
        attach = true;
        winid = args->getOption("embed").toInt(&attach, 0);  //C style parsing.  If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
        if(!attach)
            kWarning(1206) << "Specified winid to attach to is not a valid number";
    }


    QList<QByteArray> env;
    QByteArray options;
    env << ( "DESKTOP_STARTUP_ID=" + kapp->startupId());

    if (pw->pw_uid)
    {
       // Only propagate KDEHOME for non-root users,
       // root uses KDEROOTHOME

       // Translate the KDEHOME of this user to the new user.
       QString kdeHome = KGlobal::dirs()->relativeLocation("home", KGlobal::dirs()->localkdedir());
       if (kdeHome[0] != '/')
          kdeHome.prepend("~/");
       else
          kdeHome.clear(); // Use default

       env << ("KDEHOME="+ QFile::encodeName(kdeHome));
    }

    KUser u;
    env << (QByteArray) ("KDESU_USER="******"rlimit(): " << ERR << "\n";
        exit(1);
    }

    // Read configuration
    KConfigGroup config(KGlobal::config(), "Passwords");
    int timeout = config.readEntry("Timeout", defTimeout);

    // Check if we need a password
    SuProcess proc;
    proc.setUser(auth_user);
    int needpw = proc.checkNeedPassword();
    if (needpw < 0)
    {
        QString err = i18n("Su returned with an error.\n");
        KMessageBox::error(0L, err);
        exit(1);
    }
    if (needpw == 0)
    {
        keep = 0;
        kDebug() << "Don't need password!!\n";
    }

    // Start the dialog
    QString password;
    if (needpw)
    {
#ifdef Q_WS_X11
        KStartupInfoId id;
        id.initId( kapp->startupId());
        KStartupInfoData data;
        data.setSilent( KStartupInfoData::Yes );
        KStartupInfo::sendChange( id, data );
#endif
        KDEsuDialog dlg(user, auth_user, keep && !terminal, icon, withIgnoreButton);
        if (prompt)
            dlg.addCommentLine(i18n("Command:"), QFile::decodeName(command));
        if (defKeep)
            dlg.setKeepPassword(true);

        if ((priority != 50) || (scheduler != SuProcess::SchedNormal))
        {
            QString prio;
            if (scheduler == SuProcess::SchedRealtime)
                prio += i18n("realtime: ");
            prio += QString("%1/100").arg(priority);
            if (prompt)
                dlg.addCommentLine(i18n("Priority:"), prio);
        }

	//Attach dialog
#ifdef Q_WS_X11
	if(attach)
            KWindowSystem::setMainWindow(&dlg, (WId)winid);
#endif
        int ret = dlg.exec();
        if (ret == KDEsuDialog::Rejected)
        {
#ifdef Q_WS_X11
            KStartupInfo::sendFinish( id );
#endif
            exit(1);
        }
        if (ret == KDEsuDialog::AsUser)
            change_uid = false;
        password = dlg.password();
        keep = dlg.keepPassword();
#ifdef Q_WS_X11
        data.setSilent( KStartupInfoData::No );
        KStartupInfo::sendChange( id, data );
#endif
    }

    // Some events may need to be handled (like a button animation)
    kapp->processEvents();

    // Run command
    if (!change_uid)
    {
        int result = system(command);
        result = WEXITSTATUS(result);
        return result;
    }
    else if (keep && have_daemon)
    {
        client.setPass(password.toLocal8Bit(), timeout);
        client.setPriority(priority);
        client.setScheduler(scheduler);
        int result = client.exec(command, user, options, env);
        if (result == 0)
        {
            result = client.exitCode();
            return result;
        }
    } else
    {
        SuProcess proc;
        proc.setTerminal(terminal);
        proc.setErase(true);
        proc.setUser(user);
        proc.setEnvironment(env);
        proc.setPriority(priority);
        proc.setScheduler(scheduler);
        proc.setCommand(command);
        int result = proc.exec(password.toLocal8Bit());
        return result;
    }
    return -1;
}
Esempio n. 4
0
int main(int argc, char **argv)
{
	struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
	struct bpf_prog_load_attr prog_load_attr = {
		.prog_type	= BPF_PROG_TYPE_XDP,
	};
	int prog_fd, qidconf_map, xsks_map;
	struct bpf_object *obj;
	char xdp_filename[256];
	struct bpf_map *map;
	int i, ret, key = 0;
	pthread_t pt;

	parse_command_line(argc, argv);

	if (setrlimit(RLIMIT_MEMLOCK, &r)) {
		fprintf(stderr, "ERROR: setrlimit(RLIMIT_MEMLOCK) \"%s\"\n",
			strerror(errno));
		exit(EXIT_FAILURE);
	}

	snprintf(xdp_filename, sizeof(xdp_filename), "%s_kern.o", argv[0]);
	prog_load_attr.file = xdp_filename;

	if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
		exit(EXIT_FAILURE);
	if (prog_fd < 0) {
		fprintf(stderr, "ERROR: no program found: %s\n",
			strerror(prog_fd));
		exit(EXIT_FAILURE);
	}

	map = bpf_object__find_map_by_name(obj, "qidconf_map");
	qidconf_map = bpf_map__fd(map);
	if (qidconf_map < 0) {
		fprintf(stderr, "ERROR: no qidconf map found: %s\n",
			strerror(qidconf_map));
		exit(EXIT_FAILURE);
	}

	map = bpf_object__find_map_by_name(obj, "xsks_map");
	xsks_map = bpf_map__fd(map);
	if (xsks_map < 0) {
		fprintf(stderr, "ERROR: no xsks map found: %s\n",
			strerror(xsks_map));
		exit(EXIT_FAILURE);
	}

	if (bpf_set_link_xdp_fd(opt_ifindex, prog_fd, opt_xdp_flags) < 0) {
		fprintf(stderr, "ERROR: link set xdp fd failed\n");
		exit(EXIT_FAILURE);
	}

	ret = bpf_map_update_elem(qidconf_map, &key, &opt_queue, 0);
	if (ret) {
		fprintf(stderr, "ERROR: bpf_map_update_elem qidconf\n");
		exit(EXIT_FAILURE);
	}

	/* Create sockets... */
	xsks[num_socks++] = xsk_configure(NULL);

#if RR_LB
	for (i = 0; i < MAX_SOCKS - 1; i++)
		xsks[num_socks++] = xsk_configure(xsks[0]->umem);
#endif

	/* ...and insert them into the map. */
	for (i = 0; i < num_socks; i++) {
		key = i;
		ret = bpf_map_update_elem(xsks_map, &key, &xsks[i]->sfd, 0);
		if (ret) {
			fprintf(stderr, "ERROR: bpf_map_update_elem %d\n", i);
			exit(EXIT_FAILURE);
		}
	}

	signal(SIGINT, int_exit);
	signal(SIGTERM, int_exit);
	signal(SIGABRT, int_exit);

	setlocale(LC_ALL, "");

	ret = pthread_create(&pt, NULL, poller, NULL);
	lassert(ret == 0);

	prev_time = get_nsecs();

	if (opt_bench == BENCH_RXDROP)
		rx_drop_all();
	else if (opt_bench == BENCH_TXONLY)
		tx_only(xsks[0]);
	else
		l2fwd(xsks[0]);

	return 0;
}
Esempio n. 5
0
int
main(int argc, char **argv)
{
    SCAN_COLLECTION * volatile c;	/* Avoid longjmp clobbering */
    volatile int errs;
#ifdef RLIMIT_DATA
    struct rlimit dlim;

    if (getrlimit(RLIMIT_DATA, &dlim) == -1)
        goaway("Error getting resource limit (%s)",
               strerror(errno));
    if (dlim.rlim_cur != dlim.rlim_max) {
        dlim.rlim_cur = dlim.rlim_max;
        if (setrlimit(RLIMIT_DATA, &dlim) == -1)
            goaway("Error setting resource limit (%s)",
                   strerror(errno));
    }
#endif

    errs = init(argc, argv);	/* process arguments */
    if (errs) {
        fprintf(stderr, "supscan: %d collections had errors", errs);
        return 1;
    }
    for (c = firstC; c; c = c->Cnext) {
        collname = c->Cname;
        basedir = c->Cbase;
        prefix = c->Cprefix;
        if (chdir(basedir) < 0) {
            fprintf(stderr, "supscan: Can't chdir to %s (%s)",
                    basedir, strerror(errno));
            return 1;
        }
        scantime = time(NULL);
        if (!quiet)
            printf("SUP Scan for %s starting at %s", collname,
                   ctime(&scantime));
        (void) fflush(stdout);
        if (!setjmp(sjbuf)) {
            makescanlists();	/* record names in scan files */
            scantime = time(NULL);
            if (!quiet)
                printf("SUP Scan for %s completed at %s",
                       collname, ctime(&scantime));
        } else {
            fprintf(stderr,
                    "SUP: Scan for %s aborted at %s", collname,
                    ctime(&scantime));
            errs++;
        }
        if (!quiet)
            (void) fflush(stdout);
    }
    while ((c = firstC) != NULL) {
        firstC = firstC->Cnext;
        free(c->Cname);
        free(c->Cbase);
        if (c->Cprefix)
            free(c->Cprefix);
        free(c);
    }
    return errs ? 1 : 0;
}
Esempio n. 6
0
/*
 * Take the amount of memory to allocate in bytes as a command-line argument
 * and call test_malloc with that amount of memory.
 */
int
main(int argc, char *argv[])
{
    size_t size, max;
    size_t limit = 0;
    int willfail = 0;
    unsigned char code;

    if (argc < 3)
        die("Usage error.  Type, size, and limit must be given.");
    errno = 0;
    size = strtol(argv[2], 0, 10);
    if (size == 0 && errno != 0)
        sysdie("Invalid size");
    errno = 0;
    limit = strtol(argv[3], 0, 10);
    if (limit == 0 && errno != 0)
        sysdie("Invalid limit");

    /* If the code is capitalized, install our customized error handler. */
    code = argv[1][0];
    if (isupper(code)) {
        xmalloc_error_handler = test_handler;
        code = tolower(code);
    }

    /*
     * Decide if the allocation should fail.  If it should, set willfail to 2,
     * so that if it unexpectedly succeeds, we exit with a status indicating
     * that the test should be skipped.
     */
    max = size;
    if (code == 's' || code == 'n' || code == 'a' || code == 'v') {
        max += size;
        if (limit > 0)
            limit += size;
    }
    if (limit > 0 && max > limit)
        willfail = 2;

    /*
     * If a memory limit was given and we can set memory limits, set it.
     * Otherwise, exit 2, signalling to the driver that the test should be
     * skipped.  We do this here rather than in the driver due to some
     * pathological problems with Linux (setting ulimit in the shell caused
     * the shell to die).
     */
    if (limit > 0) {
#if HAVE_SETRLIMIT && defined(RLIMIT_AS)
        struct rlimit rl;
        void *tmp;
        size_t test_size;

        rl.rlim_cur = limit;
        rl.rlim_max = limit;
        if (setrlimit(RLIMIT_AS, &rl) < 0) {
            syswarn("Can't set data limit to %lu", (unsigned long) limit);
            exit(2);
        }
        if (size < limit || code == 'r' || code == 'y') {
            test_size = (code == 'r' || code == 'y') ? 10 : size;
            if (test_size == 0)
                test_size = 1;
            tmp = malloc(test_size);
            if (tmp == NULL) {
                syswarn("Can't allocate initial memory of %lu (limit %lu)",
                        (unsigned long) test_size, (unsigned long) limit);
                exit(2);
            }
            free(tmp);
        }
#else
        warn("Data limits aren't supported.");
        exit(2);
#endif
    }

    switch (code) {
    case 'c': exit(test_calloc(size) ? willfail : 1);
    case 'm': exit(test_malloc(size) ? willfail : 1);
    case 'r': exit(test_realloc(size) ? willfail : 1);
    case 'y': exit(test_reallocarray(4, size / 4) ? willfail : 1);
    case 's': exit(test_strdup(size) ? willfail : 1);
    case 'n': exit(test_strndup(size) ? willfail : 1);
    case 'a': exit(test_asprintf(size) ? willfail : 1);
    case 'v': exit(test_vasprintf(size) ? willfail : 1);
    default:
        die("Unknown mode %c", argv[1][0]);
        break;
    }
    exit(1);
}
Esempio n. 7
0
int
ulimitcmd(int argc, char **argv)
{
	int	c;
	rlim_t val = 0;
	enum limtype how = SOFT | HARD;
	const struct limits	*l;
	int		set, all = 0;
	int		optc, what;
	struct rlimit	limit;

	what = 'f';
	while ((optc = nextopt("HSa"
#ifdef RLIMIT_CPU
			       "t"
#endif
#ifdef RLIMIT_FSIZE
			       "f"
#endif
#ifdef RLIMIT_DATA
			       "d"
#endif
#ifdef RLIMIT_STACK
			       "s"
#endif
#ifdef RLIMIT_CORE
			       "c"
#endif
#ifdef RLIMIT_RSS
			       "m"
#endif
#ifdef RLIMIT_MEMLOCK
			       "l"
#endif
#ifdef RLIMIT_NPROC
			       "p"
#endif
#ifdef RLIMIT_NOFILE
			       "n"
#endif
#ifdef RLIMIT_AS
			       "v"
#endif
#ifdef RLIMIT_LOCKS
			       "w"
#endif
	)) != '\0')
		switch (optc) {
		case 'H':
			how = HARD;
			break;
		case 'S':
			how = SOFT;
			break;
		case 'a':
			all = 1;
			break;
		default:
			what = optc;
		}

	for (l = limits; l->option != what; l++)
		;

	set = *argptr ? 1 : 0;
	if (set) {
		char *p = *argptr;

		if (all || argptr[1])
			sh_error("too many arguments");
		if (strcmp(p, "unlimited") == 0)
			val = RLIM_INFINITY;
		else {
			val = (rlim_t) 0;

			while ((c = *p++) >= '0' && c <= '9')
			{
				val = (val * 10) + (long)(c - '0');
				if (val < (rlim_t) 0)
					break;
			}
			if (c)
				sh_error("bad number");
			val *= l->factor;
		}
	}
	if (all) {
		for (l = limits; l->name; l++) {
			getrlimit(l->cmd, &limit);
			out1fmt("%-20s ", l->name);
			printlim(how, &limit, l);
		}
		return 0;
	}

	getrlimit(l->cmd, &limit);
	if (set) {
		if (how & HARD)
			limit.rlim_max = val;
		if (how & SOFT)
			limit.rlim_cur = val;
		if (setrlimit(l->cmd, &limit) < 0)
			sh_error("error setting limit (%s)", strerror(errno));
	} else {
		printlim(how, &limit, l);
	}
	return 0;
}
Esempio n. 8
0
static int rlimit(int keep_open)
{
  int nitems, i;
  int *memchunk = NULL;
  char *fmt;
  struct rlimit rl;
  char strbuff[256];
  char strbuff1[81];
  char strbuff2[81];
  char fmt_u[] = "%u";
  char fmt_lu[] = "%lu";
#ifdef HAVE_LONGLONG
  char fmt_llu[] = "%llu";

  if (sizeof(rl.rlim_max) > sizeof(long))
    fmt = fmt_llu;
  else
#endif
    fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu;

  /* get initial open file limits */

  if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
    store_errmsg("getrlimit() failed", ERRNO);
    fprintf(stderr, "%s\n", msgbuff);
    return -1;
  }

  /* show initial open file limits */

#ifdef RLIM_INFINITY
  if (rl.rlim_cur == RLIM_INFINITY)
    strcpy(strbuff, "INFINITY");
  else
#endif
    sprintf(strbuff, fmt, rl.rlim_cur);
  fprintf(stderr, "initial soft limit: %s\n", strbuff);

#ifdef RLIM_INFINITY
  if (rl.rlim_max == RLIM_INFINITY)
    strcpy(strbuff, "INFINITY");
  else
#endif
    sprintf(strbuff, fmt, rl.rlim_max);
  fprintf(stderr, "initial hard limit: %s\n", strbuff);

  /* show our constants */

  fprintf(stderr, "test518 FD_SETSIZE: %d\n", FD_SETSIZE);
  fprintf(stderr, "test518 NUM_OPEN  : %d\n", NUM_OPEN);
  fprintf(stderr, "test518 NUM_NEEDED: %d\n", NUM_NEEDED);

  /*
   * if soft limit and hard limit are different we ask the
   * system to raise soft limit all the way up to the hard
   * limit. Due to some other system limit the soft limit
   * might not be raised up to the hard limit. So from this
   * point the resulting soft limit is our limit. Trying to
   * open more than soft limit file descriptors will fail.
   */

  if (rl.rlim_cur != rl.rlim_max) {

    fprintf(stderr, "raising soft limit up to hard limit\n");
    rl.rlim_cur = rl.rlim_max;
    if (setrlimit(RLIMIT_NOFILE, &rl) != 0) {
      store_errmsg("setrlimit() failed", ERRNO);
      fprintf(stderr, "%s\n", msgbuff);
      return -2;
    }

    /* get current open file limits */

    if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
      store_errmsg("getrlimit() failed", ERRNO);
      fprintf(stderr, "%s\n", msgbuff);
      return -3;
    }

    /* show current open file limits */

#ifdef RLIM_INFINITY
    if (rl.rlim_cur == RLIM_INFINITY)
      strcpy(strbuff, "INFINITY");
    else
#endif
      sprintf(strbuff, fmt, rl.rlim_cur);
    fprintf(stderr, "current soft limit: %s\n", strbuff);

#ifdef RLIM_INFINITY
    if (rl.rlim_max == RLIM_INFINITY)
      strcpy(strbuff, "INFINITY");
    else
#endif
      sprintf(strbuff, fmt, rl.rlim_max);
    fprintf(stderr, "current hard limit: %s\n", strbuff);

  } /* (rl.rlim_cur != rl.rlim_max) */

  /*
   * test 518 is all about testing libcurl functionality
   * when more than FD_SETSIZE file descriptors are open.
   * This means that if for any reason we are not able to
   * open more than FD_SETSIZE file descriptors then test
   * 518 should not be run.
   */

  /*
   * verify that soft limit is higher than NUM_NEEDED,
   * which is the number of file descriptors we would 
   * try to open plus SAFETY_MARGIN to not exhaust the
   * file descriptor pool
   */

  num_open.rlim_cur = NUM_NEEDED;

  if ((rl.rlim_cur > 0) &&
#ifdef RLIM_INFINITY
     (rl.rlim_cur != RLIM_INFINITY) &&
#endif
     (rl.rlim_cur <= num_open.rlim_cur)) {
    sprintf(strbuff2, fmt, rl.rlim_cur);
    sprintf(strbuff1, fmt, num_open.rlim_cur);
    sprintf(strbuff, "fds needed %s > system limit %s",
            strbuff1, strbuff2);
    store_errmsg(strbuff, 0);
    fprintf(stderr, "%s\n", msgbuff);
    return -4;
  }

  /*
   * reserve a chunk of memory before opening file descriptors to
   * avoid a low memory condition once the file descriptors are
   * open. System conditions that could make the test fail should
   * be addressed in the precheck phase. This chunk of memory shall
   * be always free()ed before exiting the rlimit() function so
   * that it becomes available to the test.
   */

  for (nitems = i = 1; nitems <= i; i *= 2)
    nitems = i;
  if (nitems > 0x7fff)
    nitems = 0x40000;
  do {
    num_open.rlim_max = sizeof(*memchunk) * (size_t)nitems;
    sprintf(strbuff, fmt, num_open.rlim_max);
    fprintf(stderr, "allocating memchunk %s byte array\n", strbuff);
    memchunk = malloc(sizeof(*memchunk) * (size_t)nitems);
    if (!memchunk) {
      fprintf(stderr, "memchunk, malloc() failed\n");
      nitems /= 2;
    }
  } while (nitems && !memchunk);
  if (!memchunk) {
    store_errmsg("memchunk, malloc() failed", ERRNO);
    fprintf(stderr, "%s\n", msgbuff);
    return -5;
  }

  /* initialize it to fight lazy allocation */

  fprintf(stderr, "initializing memchunk array\n");

  for (i = 0; i < nitems; i++)
    memchunk[i] = -1;

  /* set the number of file descriptors we will try to open */

  num_open.rlim_max = NUM_OPEN;

  /* verify that we won't overflow size_t in malloc() */

  if ((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) {
    sprintf(strbuff1, fmt, num_open.rlim_max);
    sprintf(strbuff, "unable to allocate an array for %s "
            "file descriptors, would overflow size_t", strbuff1);
    store_errmsg(strbuff, 0);
    fprintf(stderr, "%s\n", msgbuff);
    free(memchunk);
    return -6;
  }

  /* allocate array for file descriptors */

  sprintf(strbuff, fmt, num_open.rlim_max);
  fprintf(stderr, "allocating array for %s file descriptors\n", strbuff);

  fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max));
  if (!fd) {
    store_errmsg("fd, malloc() failed", ERRNO);
    fprintf(stderr, "%s\n", msgbuff);
    free(memchunk);
    return -7;
  }

  /* initialize it to fight lazy allocation */

  fprintf(stderr, "initializing fd array\n");

  for (num_open.rlim_cur = 0;
       num_open.rlim_cur < num_open.rlim_max;
       num_open.rlim_cur++)
    fd[num_open.rlim_cur] = -1;

  sprintf(strbuff, fmt, num_open.rlim_max);
  fprintf(stderr, "trying to open %s file descriptors\n", strbuff);

  /* open a dummy descriptor */

  fd[0] = open(DEV_NULL, O_RDONLY);
  if (fd[0] < 0) {
    sprintf(strbuff, "opening of %s failed", DEV_NULL);
    store_errmsg(strbuff, ERRNO);
    fprintf(stderr, "%s\n", msgbuff);
    free(fd);
    fd = NULL;
    free(memchunk);
    return -8;
  }

  /* create a bunch of file descriptors */

  for (num_open.rlim_cur = 1; 
       num_open.rlim_cur < num_open.rlim_max; 
       num_open.rlim_cur++) {

    fd[num_open.rlim_cur] = dup(fd[0]);

    if (fd[num_open.rlim_cur] < 0) {

      fd[num_open.rlim_cur] = -1;

      sprintf(strbuff1, fmt, num_open.rlim_cur);
      sprintf(strbuff, "dup() attempt %s failed", strbuff1);
      fprintf(stderr, "%s\n", strbuff);

      sprintf(strbuff1, fmt, num_open.rlim_cur);
      sprintf(strbuff, "fds system limit seems close to %s", strbuff1);
      fprintf(stderr, "%s\n", strbuff);

      num_open.rlim_max = NUM_NEEDED;

      sprintf(strbuff2, fmt, num_open.rlim_max);
      sprintf(strbuff1, fmt, num_open.rlim_cur);
      sprintf(strbuff, "fds needed %s > system limit %s",
              strbuff2, strbuff1);
      store_errmsg(strbuff, 0);
      fprintf(stderr, "%s\n", msgbuff);

      for (num_open.rlim_cur = 0;
           fd[num_open.rlim_cur] >= 0;
           num_open.rlim_cur++)
        close(fd[num_open.rlim_cur]);
      free(fd);
      fd = NULL;
      free(memchunk);
      return -9;

    }

  }

  sprintf(strbuff, fmt, num_open.rlim_max);
  fprintf(stderr, "%s file descriptors open\n", strbuff);

#if !defined(HAVE_POLL_FINE)    && \
    !defined(USE_WINSOCK)       && \
    !defined(TPF)

  /*
   * when using select() instead of poll() we cannot test
   * libcurl functionality with a socket number equal or
   * greater than FD_SETSIZE. In any case, macro VERIFY_SOCK
   * in lib/select.c enforces this check and protects libcurl
   * from a possible crash. The effect of this protection
   * is that test 518 will always fail, since the actual
   * call to select() never takes place. We skip test 518
   * with an indication that select limit would be exceeded.
   */

  num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
  if (num_open.rlim_max > num_open.rlim_cur) {
    sprintf(strbuff, "select limit is FD_SETSIZE %d", FD_SETSIZE);
    store_errmsg(strbuff, 0);
    fprintf(stderr, "%s\n", msgbuff);
    close_file_descriptors();
    free(memchunk);
    return -10;
  }

  num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
  for (rl.rlim_cur = 0;
       rl.rlim_cur < num_open.rlim_max;
       rl.rlim_cur++) {
    if (fd[rl.rlim_cur] > num_open.rlim_cur) {
      sprintf(strbuff, "select limit is FD_SETSIZE %d", FD_SETSIZE);
      store_errmsg(strbuff, 0);
      fprintf(stderr, "%s\n", msgbuff);
      close_file_descriptors();
      free(memchunk);
      return -11;
    }
  }

#endif /* using a FD_SETSIZE bound select() */

  /*
   * Old or 'backwards compatible' implementations of stdio do not allow
   * handling of streams with an underlying file descriptor number greater
   * than 255, even when allowing high numbered file descriptors for sockets.
   * At this point we have a big number of file descriptors which have been
   * opened using dup(), so lets test the stdio implementation and discover
   * if it is capable of fopen()ing some additional files.
   */

  if (!fopen_works()) {
    sprintf(strbuff1, fmt, num_open.rlim_max);
    sprintf(strbuff, "stdio fopen() fails with %s fds open()",
            strbuff1);
    fprintf(stderr, "%s\n", msgbuff);
    sprintf(strbuff, "stdio fopen() fails with lots of fds open()");
    store_errmsg(strbuff, 0);
    close_file_descriptors();
    free(memchunk);
    return -12;
  }

  /* free the chunk of memory we were reserving so that it
     becomes becomes available to the test */

  free(memchunk);

  /* close file descriptors unless instructed to keep them */

  if (!keep_open) {
    close_file_descriptors();
  }

  return 0;
}
[[noreturn]] void DummyUnixSandbox::box_inner(const std::string& command, const std::vector<std::string>& args) {
    // Set up IO redirection.
    if (!setup_io_redirect(stdin_, fileno(stdin), O_RDONLY)) exit(1);
    if (!setup_io_redirect(stdout_, fileno(stdout), O_RDWR)) exit(1);
    if (!setup_io_redirect(stderr_, fileno(stderr), O_RDWR)) exit(1);

    // Make the pipe close on the call to exec()
    fcntl(comm[1], F_SETFD, FD_CLOEXEC);

    // Build arguments for execve
    int trailing_slash_count = 0;
    while (command[trailing_slash_count] == '/') trailing_slash_count++;
    std::string executable = command.substr(trailing_slash_count);
    std::vector<char*> e_args;
    char* executable_c_str = new char[executable.size()+1];
    strcpy(executable_c_str, executable.c_str());
    e_args.push_back(executable_c_str);

    for (auto arg: args) {
        char* tmp = new char[arg.size()+1];
        strcpy(tmp, arg.c_str());
        e_args.push_back(tmp);
    }
    e_args.push_back(nullptr);

    // Change directory to box_root
    if (chdir(get_root().c_str()) != 0) {
        send_error(5, errno);
        exit(1);
    }

    // Set up limits
    struct rlimit rlim;
    rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
    if (setrlimit(RLIMIT_STACK, &rlim) == -1) send_error(-1, errno);
    if (mem_limit.bytes() != 0) {
        rlim.rlim_cur = rlim.rlim_max = mem_limit.bytes();
        if (setrlimit(RLIMIT_AS, &rlim) == -1) send_error(-2, errno);
    }
    if (time_limit.seconds() != 0) {
        rlim.rlim_cur = rlim.rlim_max = time_limit.seconds();
        if (setrlimit(RLIMIT_CPU, &rlim) == -1) send_error(-3, errno);
    }
    if (process_limit) {
        rlim.rlim_cur = rlim.rlim_max = process_limit;
        if (setrlimit(RLIMIT_NPROC, &rlim) == -1) send_error(-4, errno);
    }
    if (disk_limit.bytes()) {
        rlim.rlim_cur = rlim.rlim_max = disk_limit.bytes();
        if (setrlimit(RLIMIT_FSIZE, &rlim) == -1) send_error(-5, errno);
        rlim.rlim_cur = rlim.rlim_max = 0;
        if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) send_error(-5, errno);
    }
    if (!pre_exec_hook()) exit(1);
    // Set all privileges to the effective user id
    // ie. drop privileges if the program is setuid, do nothing otherwise
    setreuid(geteuid(), getuid());
    setuid(getuid());
    execv(executable.c_str(), &e_args[0]);
    send_error(4, errno);
    exit(1);
}
Esempio n. 10
0
int main(int argc, char *argv[])
{
#ifdef Q_OS_MAC
	// QTBUG-32789 - GUI widgets use the wrong font on OS X Mavericks
	QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
#endif

	SingleApplication theApp( argc, argv );

	if(!theApp.shouldContinue())return 0;

	QStringList args = theApp.arguments();

	QUrl proxy;
	int index = args.indexOf("-proxy");
	if ( index != -1 )
		proxy = QUrl( args.value(index + 1) );
	else
		proxy = QUrl( qgetenv( "http_proxy" ) );
	if ( !proxy.isEmpty() )
		setApplicationProxy( proxy );

	QByteArray encoding;
	index = args.indexOf( "-encoding" );
	if ( index != -1 )
		encoding = args.value( index + 1 ).toLocal8Bit();
	else if ( !qgetenv( "COMMUNI_ENCODING" ).isEmpty())
		encoding = qgetenv( "COMMUNI_ENCODING" );
	if ( !encoding.isEmpty() )
		SingleApplication::setEncoding( encoding );


// To enable this, run qmake with "DEFINES+=_SNAPSHOT_BUILD"
#ifdef _SNAPSHOT_BUILD
	QDate oExpire = QDate::fromString( Version::BUILD_DATE, Qt::ISODate ).addDays( 60 );

	if( QDate::currentDate() > oExpire )
	{
		QMessageBox::information( NULL,
								  QObject::tr( "Cool Software, but..." ),
								  QObject::tr( "This build is expired. If you wish to continue using this "
											   "Cool Software you must download either latest stable releas"
											   "e or latest snapshot build from http://quazaa.sf.net/.\n\n"
											   "The program will now terminate." ) );
		return 0;
	}

	if( !args.contains("--no-alpha-warning") )
	{
		int ret = QMessageBox::warning( NULL,
										QObject::tr("Snapshot/Debug Build Warning"),
										QObject::tr("WARNING: This is a SNAPSHOT BUILD of Quazaa. \n"
													"It is NOT meant for GENERAL USE, and is only for testi"
													"ng specific features in a controlled environment.\n"
													"It will frequently stop running, or will display debug"
													"information to assist testing.\n"
													"This build will expire on %1.\n\n"
													"Do you wish to continue?"
													).arg( oExpire.toString( Qt::SystemLocaleLongDate ) ),
									   QMessageBox::Yes | QMessageBox::No );
		if( ret == QMessageBox::No )
			return 0;
	}
#endif

	qsrand( time( 0 ) );

#ifdef Q_OS_LINUX

	rlimit sLimit;
	memset( &sLimit, 0, sizeof( rlimit ) );
	getrlimit( RLIMIT_NOFILE, &sLimit );

	sLimit.rlim_cur = sLimit.rlim_max;

	if( setrlimit( RLIMIT_NOFILE, &sLimit ) == 0 )
	{
		qDebug() << "Successfully raised resource limits";
	}
	else
	{
		qDebug() << "Cannot set resource limits";
	}

#endif // Q_OS_LINUX

	theApp.setApplicationName(    CQuazaaGlobals::APPLICATION_NAME() );
	theApp.setApplicationVersion( CQuazaaGlobals::APPLICATION_VERSION_STRING() );
	theApp.setOrganizationDomain( CQuazaaGlobals::APPLICATION_ORGANIZATION_DOMAIN() );
	theApp.setOrganizationName(   CQuazaaGlobals::APPLICATION_ORGANIZATION_NAME() );
	theApp.setApplicationSlogan( QObject::tr("World class file sharing.") );

	QIcon icon;
	icon.addFile( ":/Resource/Quazaa16.png" );
	icon.addFile( ":/Resource/Quazaa24.png" );
	icon.addFile( ":/Resource/Quazaa32.png" );
	icon.addFile( ":/Resource/Quazaa48.png" );
	icon.addFile( ":/Resource/Quazaa64.png" );
	icon.addFile( ":/Resource/Quazaa128.png" );
	qApp->setWindowIcon( icon );

	// Initialize system log component translations
	systemLog.start();

	// Setup Qt elements of signal queue necessary for operation
	signalQueue.setup();

	//Initialize multilanguage support
	quazaaSettings.loadLanguageSettings();
	quazaaSettings.translator.load( quazaaSettings.Language.File );
	qApp->installTranslator( &quazaaSettings.translator );

	// If the MainWindow object is not created and shown before any other dialogs,
	// the media player will break input event processing
	MainWindow = new CWinMain();
	MainWindow->show();
	MainWindow->hide();

	//Create splash window
	CDialogSplash* dlgSplash = new CDialogSplash();
	dlgSplash->show();
	qApp->processEvents();

	dlgSplash->updateProgress( 1, QObject::tr( "Loading settings..." ) );
	qApp->processEvents();

	//Initialize Settings
	quazaaSettings.loadSettings();

	//Check if this is Quazaa's first run
	dlgSplash->updateProgress( 8, QObject::tr( "Checking for first run..." ) );
	qApp->processEvents();
	bool bFirstRun = quazaaSettings.isFirstRun();
	if ( bFirstRun )
	{
		CDialogLanguage* dlgLanguage = new CDialogLanguage();
		dlgLanguage->exec();

		dlgSplash->updateProgress( 10, QObject::tr( "Running Quick Start wizard..." ) );
		quazaaSettings.saveFirstRun( false );
		quazaaSettings.saveSettings();
		quazaaSettings.saveProfile();

		CWizardQuickStart* wzrdQuickStart = new CWizardQuickStart();
		wzrdQuickStart->exec();
	}

	// Load Security Manager
	dlgSplash->updateProgress( 15, QObject::tr( "Loading Security Manager..." ) );
	qApp->processEvents();
	if ( !securityManager.start() )
		systemLog.postLog( LogSeverity::Information,
						   QObject::tr( "Security data file was not available." ) );

	// Load Discovery Services Manager
	dlgSplash->updateProgress( 22, QObject::tr( "Loading Discovery Services Manager..." ) );
	qApp->processEvents();
	discoveryManager.start();

	//Load profile
	dlgSplash->updateProgress( 25, QObject::tr( "Loading Profile..." ) );
	qApp->processEvents();
	quazaaSettings.loadProfile();

	//Load Host Cache
	dlgSplash->updateProgress( 30, QObject::tr( "Loading Host Cache..." ) );
	qApp->processEvents();
	hostCache.m_pSection.lock();
	hostCache.load();
	hostCache.m_pSection.unlock();

	//initialize geoip list
	geoIP.loadGeoIP();

	//Load the library
	dlgSplash->updateProgress( 38, QObject::tr( "Loading Library..." ) );
	qApp->processEvents();
	QueryHashMaster.create();
	ShareManager.start();

	// Load Download Manager
	dlgSplash->updateProgress( 60, QObject::tr( "Loading Transfer Manager..." ) );
	qApp->processEvents();
	Transfers.start();

	dlgSplash->updateProgress( 80, QObject::tr( "Loading User Interface..." ) );
	qApp->processEvents();

	if ( quazaaSettings.WinMain.Visible )
	{
		if(bFirstRun)
			MainWindow->showMaximized();
		else
			MainWindow->show();
	}

	dlgSplash->updateProgress( 90, QObject::tr( "Loading Tray Icon..." ) );
	qApp->processEvents();
	MainWindow->loadTrayIcon();

	dlgSplash->updateProgress( 100, QObject::tr( "Welcome to Quazaa!" ) );
	qApp->processEvents();

	dlgSplash->deleteLater();
	dlgSplash = 0;

	// Start networks if needed
	if ( quazaaSettings.System.ConnectOnStartup )
	{
		if ( quazaaSettings.Gnutella2.Enable )
		{
			Network.start();
		}
	}

	return theApp.exec();
}
Esempio n. 11
0
int main(int argc, char **argv)
{
    static struct cl_engine *engine = NULL;
    const struct optstruct *opt;
#ifndef	_WIN32
    struct passwd *user = NULL;
    struct sigaction sa;
    struct rlimit rlim;
#endif
    time_t currtime;
    const char *dbdir, *cfgfile;
    char *pua_cats = NULL, *pt;
    int ret, tcpsock = 0, localsock = 0, min_port, max_port;
    unsigned int sigs = 0;
    int *lsockets=NULL;
    unsigned int nlsockets = 0;
    unsigned int dboptions = 0;
    unsigned int i;
#ifdef C_LINUX
    STATBUF sb;
#endif

    if(check_flevel())
        exit(1);

#ifndef _WIN32
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = SIG_IGN;
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);
#endif

    if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) {
        mprintf("!Can't parse command line options\n");
        return 1;
    }

    if(optget(opts, "help")->enabled) {
        help();
        optfree(opts);
        return 0;
    }

    if(optget(opts, "debug")->enabled) {
#if defined(C_LINUX)
        /* [email protected]: create a dump if needed */
        rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
        if(setrlimit(RLIMIT_CORE, &rlim) < 0)
            perror("setrlimit");
#endif
        debug_mode = 1;
    }

    /* parse the config file */
    cfgfile = optget(opts, "config-file")->strarg;
    pt = strdup(cfgfile);
    if (pt == NULL) {
	fprintf(stderr, "ERROR: Unable to allocate memory for config file\n");
	return 1;
    }
    if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
        fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
        free(pt);
        return 1;
    }
    free(pt);

    if(optget(opts, "version")->enabled) {
        print_version(optget(opts, "DatabaseDirectory")->strarg);
        optfree(opts);
        return 0;
    }

    /* drop privileges */
#ifndef _WIN32
    if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
        if((user = getpwnam(opt->strarg)) == NULL) {
            fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
            optfree(opts);
            return 1;
        }

        if(optget(opts, "AllowSupplementaryGroups")->enabled) {
#ifdef HAVE_INITGROUPS
            if(initgroups(opt->strarg, user->pw_gid)) {
                fprintf(stderr, "ERROR: initgroups() failed.\n");
                optfree(opts);
                return 1;
            }
#else
            mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups in %s\n", cfgfile);
            optfree(opts);
            return 1;
#endif
        } else {
#ifdef HAVE_SETGROUPS
            if(setgroups(1, &user->pw_gid)) {
                fprintf(stderr, "ERROR: setgroups() failed.\n");
                optfree(opts);
                return 1;
            }
#endif
        }

        if(setgid(user->pw_gid)) {
            fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
            optfree(opts);
            return 1;
        }

        if(setuid(user->pw_uid)) {
            fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
            optfree(opts);
            return 1;
        }
    }
#endif

    /* initialize logger */
    logg_lock = !optget(opts, "LogFileUnlock")->enabled;
    logg_time = optget(opts, "LogTime")->enabled;
    logok = optget(opts, "LogClean")->enabled;
    logg_size = optget(opts, "LogFileMaxSize")->numarg;
    logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
    if (logg_size)
        logg_rotate = optget(opts, "LogRotate")->enabled;
    mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg;

    do { /* logger initialized */
        if((opt = optget(opts, "LogFile"))->enabled) {
            char timestr[32];
            logg_file = opt->strarg;
            if(!cli_is_abspath(logg_file)) {
                fprintf(stderr, "ERROR: LogFile requires full path.\n");
                ret = 1;
                break;
            }
            time(&currtime);
            if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
                fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
                ret = 1;
                break;
            }
        } else {
            logg_file = NULL;
        }

        if (optget(opts,"DevLiblog")->enabled)
            cl_set_clcb_msg(msg_callback);

        if((ret = cl_init(CL_INIT_DEFAULT))) {
            logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
            ret = 1;
            break;
        }

        if(optget(opts, "Debug")->enabled) {
            /* enable debug messages in libclamav */
            cl_debug();
            logg_verbose = 2;
        }

#if defined(USE_SYSLOG) && !defined(C_AIX)
        if(optget(opts, "LogSyslog")->enabled) {
            int fac = LOG_LOCAL6;

            opt = optget(opts, "LogFacility");
            if((fac = logg_facility(opt->strarg)) == -1) {
                logg("!LogFacility: %s: No such facility.\n", opt->strarg);
                ret = 1;
                break;
            }

            openlog("clamd", LOG_PID, fac);
            logg_syslog = 1;
        }
#endif

#ifdef C_LINUX
        procdev = 0;
        if(CLAMSTAT("/proc", &sb) != -1 && !sb.st_size)
            procdev = sb.st_dev;
#endif

        /* check socket type */

        if(optget(opts, "TCPSocket")->enabled)
            tcpsock = 1;

        if(optget(opts, "LocalSocket")->enabled)
            localsock = 1;

        if(!tcpsock && !localsock) {
            logg("!Please define server type (local and/or TCP).\n");
            ret = 1;
            break;
        }

        logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version());

#ifndef _WIN32
        if(user)
            logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
#endif

#if defined(RLIMIT_DATA) && defined(C_BSD)
        if (getrlimit(RLIMIT_DATA, &rlim) == 0) {
           /* bb #1941.
            * On 32-bit FreeBSD if you set ulimit -d to >2GB then mmap() will fail
            * too soon (after ~120 MB).
            * Set limit lower than 2G if on 32-bit */
           uint64_t lim = rlim.rlim_cur;
           if (sizeof(void*) == 4 &&
               lim > (1ULL << 31)) {
               rlim.rlim_cur = 1ULL << 31;
               if (setrlimit(RLIMIT_DATA, &rlim) < 0)
                   logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno));
               else
                   logg("Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n");
           }
        }
#endif


        if(logg_size)
            logg("#Log file size limited to %u bytes.\n", logg_size);
        else
            logg("#Log file size limit disabled.\n");

        min_port = optget(opts, "StreamMinPort")->numarg;
        max_port = optget(opts, "StreamMaxPort")->numarg;
        if (min_port < 1024 || min_port > max_port || max_port > 65535) {
            logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port);
            ret = 1;
            break;
        }

        if(!(engine = cl_engine_new())) {
            logg("!Can't initialize antivirus engine\n");
            ret = 1;
            break;
        }

        if (optget(opts, "disable-cache")->enabled)
            cl_engine_set_num(engine, CL_ENGINE_DISABLE_CACHE, 1);

        /* load the database(s) */
        dbdir = optget(opts, "DatabaseDirectory")->strarg;
        logg("#Reading databases from %s\n", dbdir);

        if(optget(opts, "DetectPUA")->enabled) {
            dboptions |= CL_DB_PUA;

            if((opt = optget(opts, "ExcludePUA"))->enabled) {
                dboptions |= CL_DB_PUA_EXCLUDE;
                i = 0;
                logg("#Excluded PUA categories:");

                while(opt) {
                    if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
                        logg("!Can't allocate memory for pua_cats\n");
                        cl_engine_free(engine);
                        ret = 1;
                        break;
                    }

                    logg("# %s", opt->strarg);

                    sprintf(pua_cats + i, ".%s", opt->strarg);
                    i += strlen(opt->strarg) + 1;
                    pua_cats[i] = 0;
                    opt = opt->nextarg;
                }

                if (ret)
                    break;

                logg("#\n");
                pua_cats[i] = '.';
                pua_cats[i + 1] = 0;
            }

            if((opt = optget(opts, "IncludePUA"))->enabled) {
                if(pua_cats) {
                    logg("!ExcludePUA and IncludePUA cannot be used at the same time\n");
                    free(pua_cats);
                    ret = 1;
                    break;
                }

                dboptions |= CL_DB_PUA_INCLUDE;
                i = 0;
                logg("#Included PUA categories:");
                while(opt) {
                    if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
                        logg("!Can't allocate memory for pua_cats\n");
                        ret = 1;
                        break;
                    }

                    logg("# %s", opt->strarg);

                    sprintf(pua_cats + i, ".%s", opt->strarg);
                    i += strlen(opt->strarg) + 1;
                    pua_cats[i] = 0;
                    opt = opt->nextarg;
                }

                if (ret)
                    break;

                logg("#\n");
                pua_cats[i] = '.';
                pua_cats[i + 1] = 0;
            }

            if(pua_cats) {
                if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
                    logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
                    free(pua_cats);
                    ret = 1;
                    break;
                }
                free(pua_cats);
            }
        } else {
            logg("#Not loading PUA signatures.\n");
        }

        if (optget(opts, "StatsEnabled")->enabled) {
            cl_engine_stats_enable(engine);
        }

        if (optget(opts, "StatsPEDisabled")->enabled) {
            cl_engine_set_num(engine, CL_ENGINE_DISABLE_PE_STATS, 1);
        }

        if (optget(opts, "StatsTimeout")->enabled) {
            cl_engine_set_num(engine, CL_ENGINE_STATS_TIMEOUT, optget(opts, "StatsTimeout")->numarg);
        }

        if (optget(opts, "StatsHostID")->enabled) {
            char *p = optget(opts, "StatsHostID")->strarg;

            if (strcmp(p, "default")) {
                if (!strcmp(p, "none")) {
                    cl_engine_set_clcb_stats_get_hostid(engine, NULL);
                } else if (!strcmp(p, "anonymous")) {
                    strcpy(hostid, STATS_ANON_UUID);
                } else {
                    if (strlen(p) > 36) {
                        logg("!Invalid HostID\n");
                        cl_engine_set_clcb_stats_submit(engine, NULL);
                        cl_engine_free(engine);
                        ret = 1;
                        break;
                    }

                    strcpy(hostid, p);
                }

                cl_engine_set_clcb_stats_get_hostid(engine, get_hostid);
            }
        }

        if(optget(opts, "OfficialDatabaseOnly")->enabled) {
            dboptions |= CL_DB_OFFICIAL_ONLY;
            logg("#Only loading official signatures.\n");
        }

        /* set the temporary dir */
        if((opt = optget(opts, "TemporaryDirectory"))->enabled) {
            if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
                logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
                ret = 1;
                break;
            }
        }

        cl_engine_set_clcb_hash(engine, hash_callback);

        cl_engine_set_clcb_virus_found(engine, clamd_virus_found_cb);

        if(optget(opts, "LeaveTemporaryFiles")->enabled)
            cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);

        if(optget(opts, "ForceToDisk")->enabled)
            cl_engine_set_num(engine, CL_ENGINE_FORCETODISK, 1);

        if(optget(opts, "PhishingSignatures")->enabled)
            dboptions |= CL_DB_PHISHING;
        else
            logg("#Not loading phishing signatures.\n");

        if(optget(opts,"Bytecode")->enabled) {
            dboptions |= CL_DB_BYTECODE;
            if((opt = optget(opts,"BytecodeSecurity"))->enabled) {
                enum bytecode_security s;

                if (!strcmp(opt->strarg, "TrustSigned")) {
                    s = CL_BYTECODE_TRUST_SIGNED;
                    logg("#Bytecode: Security mode set to \"TrustSigned\".\n");
                } else if (!strcmp(opt->strarg, "Paranoid")) {
                    s = CL_BYTECODE_TRUST_NOTHING;
                    logg("#Bytecode: Security mode set to \"Paranoid\".\n");
                } else {
                    logg("!Unable to parse bytecode security setting:%s\n",
                        opt->strarg);
                    ret = 1;
                    break;
                }

                if ((ret = cl_engine_set_num(engine, CL_ENGINE_BYTECODE_SECURITY, s))) {
                    logg("^Invalid bytecode security setting %s: %s\n", opt->strarg, cl_strerror(ret));
                    ret = 1;
                    break;
                }
            }
            if((opt = optget(opts,"BytecodeUnsigned"))->enabled) {
                dboptions |= CL_DB_BYTECODE_UNSIGNED;
                logg("#Bytecode: Enabled support for unsigned bytecode.\n");
            }

            if((opt = optget(opts,"BytecodeMode"))->enabled) {
                enum bytecode_mode mode;

                if (!strcmp(opt->strarg, "ForceJIT"))
                    mode = CL_BYTECODE_MODE_JIT;
                else if(!strcmp(opt->strarg, "ForceInterpreter"))
                    mode = CL_BYTECODE_MODE_INTERPRETER;
                else if(!strcmp(opt->strarg, "Test"))
                    mode = CL_BYTECODE_MODE_TEST;
                else
                    mode = CL_BYTECODE_MODE_AUTO;
                cl_engine_set_num(engine, CL_ENGINE_BYTECODE_MODE, mode);
            }

            if((opt = optget(opts,"BytecodeTimeout"))->enabled) {
                cl_engine_set_num(engine, CL_ENGINE_BYTECODE_TIMEOUT, opt->numarg);
            }
        } else {
            logg("#Bytecode support disabled.\n");
        }

        if(optget(opts,"PhishingScanURLs")->enabled)
            dboptions |= CL_DB_PHISHING_URLS;
        else
            logg("#Disabling URL based phishing detection.\n");

        if(optget(opts,"DevACOnly")->enabled) {
            logg("#Only using the A-C matcher.\n");
            cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);
        }

        if((opt = optget(opts, "DevACDepth"))->enabled) {
            cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg);
            logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg);
        }

        if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
            logg("!%s\n", cl_strerror(ret));
            ret = 1;
            break;
        }

        if((ret = statinidir_th(dbdir))) {
            logg("!%s\n", cl_strerror(ret));
            ret = 1;
            break;
        }

        if (optget(opts, "DisableCertCheck")->enabled)
            engine->dconf->pe |= PE_CONF_DISABLECERT;

        logg("#Loaded %u signatures.\n", sigs);

        if((ret = cl_engine_compile(engine)) != 0) {
            logg("!Database initialization error: %s\n", cl_strerror(ret));
            ret = 1;
            break;
        }

        if(tcpsock) {
            opt = optget(opts, "TCPAddr");
            if (opt->enabled) {
                int breakout = 0;

                while (opt && opt->strarg) {
                    char *ipaddr = (!strcmp(opt->strarg, "all") ? NULL : opt->strarg);

                    if (tcpserver(&lsockets, &nlsockets, ipaddr, opts) == -1) {
                        ret = 1;
                        breakout = 1;
                        break;
                    }

                    opt = opt->nextarg;
                }

                if (breakout)
                    break;
            } else {
                if (tcpserver(&lsockets, &nlsockets, NULL, opts) == -1) {
                    ret = 1;
                    break;
                }
            }
        }
#ifndef _WIN32
        if(localsock) {
            int *t;
            mode_t sock_mode, umsk = umask(0777); /* socket is created with 000 to avoid races */

            t = realloc(lsockets, sizeof(int) * (nlsockets + 1));
            if (!(t)) {
                ret = 1;
                break;
            }
            lsockets = t;

            if ((lsockets[nlsockets] = localserver(opts)) == -1) {
                ret = 1;
                umask(umsk);
                break;
            }
            umask(umsk); /* restore umask */

            if(optget(opts, "LocalSocketGroup")->enabled) {
                char *gname = optget(opts, "LocalSocketGroup")->strarg, *end;
                gid_t sock_gid = strtol(gname, &end, 10);

                if(*end) {
                    struct group *pgrp = getgrnam(gname);

                    if(!pgrp) {
                        logg("!Unknown group %s\n", gname);
                        ret = 1;
                        break;
                    }

                    sock_gid = pgrp->gr_gid;
                }
                if(chown(optget(opts, "LocalSocket")->strarg, -1, sock_gid)) {
                    logg("!Failed to change socket ownership to group %s\n", gname);
                    ret = 1;
                    break;
                }
            }
            if(optget(opts, "LocalSocketMode")->enabled) {
                char *end;

                sock_mode = strtol(optget(opts, "LocalSocketMode")->strarg, &end, 8);

                if(*end) {
                    logg("!Invalid LocalSocketMode %s\n", optget(opts, "LocalSocketMode")->strarg);
                    ret = 1;
                    break;
                }
            } else {
                sock_mode = 0777 /* & ~umsk*/; /* conservative default: umask was 0 in clamd < 0.96 */
            }

            if(chmod(optget(opts, "LocalSocket")->strarg, sock_mode & 0666)) {
                logg("!Cannot set socket permission to %s\n", optget(opts, "LocalSocketMode")->strarg);
                ret = 1;
                break;
            }

            nlsockets++;
        }

        /* fork into background */
        if(!optget(opts, "Foreground")->enabled) {
#ifdef C_BSD	    
            /* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
            for(ret=0;(unsigned int)ret<nlsockets;ret++) {
                if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK) == -1) {
                    logg("!fcntl for lsockets[] failed\n");
                    close(lsockets[ret]);
                    ret = 1;
                    break;
                }
            }
#endif
            gengine = engine;
            atexit(free_engine);
            if(daemonize() == -1) {
                logg("!daemonize() failed: %s\n", strerror(errno));
                ret = 1;
                break;
            }
            gengine = NULL;
#ifdef C_BSD
            for(ret=0;(unsigned int)ret<nlsockets;ret++) {
                if (fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK) == -1) {
                    logg("!fcntl for lsockets[] failed\n");
                    close(lsockets[ret]);
                    ret = 1;
                    break;
                }
            }
#endif
            if(!debug_mode)
                if(chdir("/") == -1)
                    logg("^Can't change current working directory to root\n");

        } else {
            foreground = 1;
        }
#endif

        if (nlsockets == 0) {
            logg("!Not listening on any interfaces\n");
            ret = 1;
            break;
        }

        ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts);

    } while (0);

    logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");

    for (i = 0; i < nlsockets; i++) {
        closesocket(lsockets[i]);
    }

#ifndef _WIN32
    if(nlsockets && localsock) {
        opt = optget(opts, "LocalSocket");

        if(unlink(opt->strarg) == -1)
            logg("!Can't unlink the socket file %s\n", opt->strarg);
        else
            logg("Socket file removed.\n");
    }
#endif

    free(lsockets);

    logg_close();
    optfree(opts);

    cl_cleanup_crypto();

    return ret;
}
Esempio n. 12
0
/*
 * This function parses the command line. Handles device-independent fields
 * and allows ddx to handle additional fields.  It is not allowed to modify
 * argc or any of the strings pointed to by argv.
 */
void
ProcessCommandLine(int argc, char *argv[])
{
    int i, skip;

    defaultKeyboardControl.autoRepeat = TRUE;

#ifdef NO_PART_NET
    PartialNetwork = FALSE;
#else
    PartialNetwork = TRUE;
#endif

    for ( i = 1; i < argc; i++ )
    {
	/* call ddx first, so it can peek/override if it wants */
        if((skip = ddxProcessArgument(argc, argv, i)))
	{
	    i += (skip - 1);
	}
	else if(argv[i][0] ==  ':')  
	{
	    /* initialize display */
	    display = argv[i];
	    display++;
            if( ! VerifyDisplayName( display ) ) {
                ErrorF("Bad display name: %s\n", display);
                UseMsg();
		FatalError("Bad display name, exiting: %s\n", display);
            }
	}
	else if ( strcmp( argv[i], "-a") == 0)
	{
	    if(++i < argc)
	        defaultPointerControl.num = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-ac") == 0)
	{
	    defeatAccessControl = TRUE;
	}
	else if ( strcmp( argv[i], "-audit") == 0)
	{
	    if(++i < argc)
	        auditTrailLevel = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-auth") == 0)
	{
	    if(++i < argc)
	        InitAuthorization (argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-br") == 0) ; /* default */
	else if ( strcmp( argv[i], "+bs") == 0)
	    enableBackingStore = TRUE;
	else if ( strcmp( argv[i], "-bs") == 0)
	    disableBackingStore = TRUE;
	else if ( strcmp( argv[i], "c") == 0)
	{
	    if(++i < argc)
	        defaultKeyboardControl.click = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-c") == 0)
	{
	    defaultKeyboardControl.click = 0;
	}
	else if ( strcmp( argv[i], "-cc") == 0)
	{
	    if(++i < argc)
	        defaultColorVisualClass = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-core") == 0)
	{
#if !defined(WIN32) || !defined(__MINGW32__)
	    struct rlimit   core_limit;
	    getrlimit (RLIMIT_CORE, &core_limit);
	    core_limit.rlim_cur = core_limit.rlim_max;
	    setrlimit (RLIMIT_CORE, &core_limit);
#endif
	    CoreDump = TRUE;
	}
        else if ( strcmp( argv[i], "-nocursor") == 0)
        {
            EnableCursor = FALSE;
        }
        else if ( strcmp( argv[i], "-dpi") == 0)
	{
	    if(++i < argc)
	        monitorResolution = atoi(argv[i]);
	    else
		UseMsg();
	}
#ifdef DPMSExtension
	else if ( strcmp( argv[i], "dpms") == 0)
	    /* ignored for compatibility */ ;
	else if ( strcmp( argv[i], "-dpms") == 0)
	    DPMSDisabledSwitch = TRUE;
#endif
	else if ( strcmp( argv[i], "-deferglyphs") == 0)
	{
	    if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
		UseMsg();
	}
	else if ( strcmp( argv[i], "-f") == 0)
	{
	    if(++i < argc)
	        defaultKeyboardControl.bell = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-fc") == 0)
	{
	    if(++i < argc)
	        defaultCursorFont = argv[i];
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-fn") == 0)
	{
	    if(++i < argc)
	        defaultTextFont = argv[i];
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-fp") == 0)
	{
	    if(++i < argc)
	    {
	        defaultFontPath = argv[i];
	    }
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-help") == 0)
	{
	    UseMsg();
	    exit(0);
	}
        else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
	    if (skip>0)
		 i+= skip-1;
	    else UseMsg();
	}
#ifdef RLIMIT_DATA
	else if ( strcmp( argv[i], "-ld") == 0)
	{
	    if(++i < argc)
	    {
	        limitDataSpace = atoi(argv[i]);
		if (limitDataSpace > 0)
		    limitDataSpace *= 1024;
	    }
	    else
		UseMsg();
	}
#endif
#ifdef RLIMIT_NOFILE
	else if ( strcmp( argv[i], "-lf") == 0)
	{
	    if(++i < argc)
	        limitNoFile = atoi(argv[i]);
	    else
		UseMsg();
	}
#endif
#ifdef RLIMIT_STACK
	else if ( strcmp( argv[i], "-ls") == 0)
	{
	    if(++i < argc)
	    {
	        limitStackSpace = atoi(argv[i]);
		if (limitStackSpace > 0)
		    limitStackSpace *= 1024;
	    }
	    else
		UseMsg();
	}
#endif
	else if ( strcmp ( argv[i], "-nolock") == 0)
	{
#if !defined(WIN32) && !defined(__CYGWIN__)
	  if (getuid() != 0)
	    ErrorF("Warning: the -nolock option can only be used by root\n");
	  else
#endif
	    nolock = TRUE;
	}
#ifndef NOLOGOHACK
	else if ( strcmp( argv[i], "-logo") == 0)
	{
	    logoScreenSaver = 1;
	}
	else if ( strcmp( argv[i], "nologo") == 0)
	{
	    logoScreenSaver = 0;
	}
#endif
	else if ( strcmp( argv[i], "-nolisten") == 0)
	{
            if(++i < argc) {
		if (_XSERVTransNoListen(argv[i])) 
		    FatalError ("Failed to disable listen for %s transport",
				argv[i]);
	   } else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-noreset") == 0)
	{
	    dispatchExceptionAtReset = 0;
	}
	else if ( strcmp( argv[i], "-reset") == 0)
	{
	    dispatchExceptionAtReset = DE_RESET;
	}
	else if ( strcmp( argv[i], "-p") == 0)
	{
	    if(++i < argc)
	        defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
					     MILLI_PER_MIN;
	    else
		UseMsg();
	}
	else if (strcmp(argv[i], "-pogo") == 0)
	{
	    dispatchException = DE_TERMINATE;
	}
	else if ( strcmp( argv[i], "-pn") == 0)
	    PartialNetwork = TRUE;
	else if ( strcmp( argv[i], "-nopn") == 0)
	    PartialNetwork = FALSE;
	else if ( strcmp( argv[i], "r") == 0)
	    defaultKeyboardControl.autoRepeat = TRUE;
	else if ( strcmp( argv[i], "-r") == 0)
	    defaultKeyboardControl.autoRepeat = FALSE;
	else if ( strcmp( argv[i], "-retro") == 0)
	    party_like_its_1989 = TRUE;
	else if ( strcmp( argv[i], "-s") == 0)
	{
	    if(++i < argc)
	        defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
					 MILLI_PER_MIN;
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-t") == 0)
	{
	    if(++i < argc)
	        defaultPointerControl.threshold = atoi(argv[i]);
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-terminate") == 0)
	{
	    dispatchExceptionAtReset = DE_TERMINATE;
	}
	else if ( strcmp( argv[i], "-to") == 0)
	{
	    if(++i < argc)
		TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-tst") == 0)
	{
	    noTestExtensions = TRUE;
	}
	else if ( strcmp( argv[i], "v") == 0)
	    defaultScreenSaverBlanking = PreferBlanking;
	else if ( strcmp( argv[i], "-v") == 0)
	    defaultScreenSaverBlanking = DontPreferBlanking;
	else if ( strcmp( argv[i], "-wm") == 0)
	    defaultBackingStore = WhenMapped;
        else if ( strcmp( argv[i], "-wr") == 0)
            whiteRoot = TRUE;
        else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
             if(++i < argc) {
                 long reqSizeArg = atol(argv[i]);

                 /* Request size > 128MB does not make much sense... */
                 if( reqSizeArg > 0L && reqSizeArg < 128L ) {
                     maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
                 }
                 else
                 {
                     UseMsg();
                 }
             }
             else
             {
                 UseMsg();
             }
         }
#ifdef PANORAMIX
	else if ( strcmp( argv[i], "+xinerama") == 0){
	    noPanoramiXExtension = FALSE;
	}
	else if ( strcmp( argv[i], "-xinerama") == 0){
	    noPanoramiXExtension = TRUE;
	}
	else if ( strcmp( argv[i], "-disablexineramaextension") == 0){
	    PanoramiXExtensionDisabledHack = TRUE;
	}
#endif
	else if ( strcmp( argv[i], "-I") == 0)
	{
	    /* ignore all remaining arguments */
	    break;
	}
	else if (strncmp (argv[i], "tty", 3) == 0)
	{
            /* init supplies us with this useless information */
	}
#ifdef XDMCP
	else if ((skip = XdmcpOptions(argc, argv, i)) != i)
	{
	    i = skip - 1;
	}
#endif
	else if ( strcmp( argv[i], "-dumbSched") == 0)
	{
	    SmartScheduleDisable = TRUE;
	}
	else if ( strcmp( argv[i], "-schedInterval") == 0)
	{
	    if (++i < argc)
	    {
		SmartScheduleInterval = atoi(argv[i]);
		SmartScheduleSlice = SmartScheduleInterval;
	    }
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-schedMax") == 0)
	{
	    if (++i < argc)
	    {
		SmartScheduleMaxSlice = atoi(argv[i]);
	    }
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-render" ) == 0)
	{
	    if (++i < argc)
	    {
		int policy = PictureParseCmapPolicy (argv[i]);

		if (policy != PictureCmapPolicyInvalid)
		    PictureCmapPolicy = policy;
		else
		    UseMsg ();
	    }
	    else
		UseMsg ();
	}
	else if ( strcmp( argv[i], "-sigstop") == 0)
	{
	    RunFromSigStopParent = TRUE;
	}
	else if ( strcmp( argv[i], "+extension") == 0)
	{
	    if (++i < argc)
	    {
		if (!EnableDisableExtension(argv[i], TRUE))
		    EnableDisableExtensionError(argv[i], TRUE);
	    }
	    else
		UseMsg();
	}
	else if ( strcmp( argv[i], "-extension") == 0)
	{
	    if (++i < argc)
	    {
		if (!EnableDisableExtension(argv[i], FALSE))
		    EnableDisableExtensionError(argv[i], FALSE);
	    }
	    else
		UseMsg();
	}
 	else
 	{
	    ErrorF("Unrecognized option: %s\n", argv[i]);
	    UseMsg();
	    FatalError("Unrecognized option: %s\n", argv[i]);
        }
    }
}
Esempio n. 13
0
static uintptr_t
get_rusage_data_via_setrlimit (void)
{
  uintptr_t result;

  struct rlimit orig_limit;

# ifdef __hpux
  /* On HP-UX 11.00, setrlimit() RLIMIT_DATA of does not work: It cannot
     restore the previous limits.
     On HP-UX 11.11, setrlimit() RLIMIT_DATA of does not work: It sometimes
     has no effect on the next sbrk() call.  */
  {
    struct utsname buf;

    if (uname (&buf) == 0
        && strlen (buf.release) >= 5
        && (strcmp (buf.release + strlen (buf.release) - 5, "11.00") == 0
            || strcmp (buf.release + strlen (buf.release) - 5, "11.11") == 0))
      return 0;
  }
# endif

  /* Record the original limit.  */
  if (getrlimit (RLIMIT_DATA, &orig_limit) < 0)
    return 0;

  if (orig_limit.rlim_max != RLIM_INFINITY
      && (orig_limit.rlim_cur == RLIM_INFINITY
          || orig_limit.rlim_cur > orig_limit.rlim_max))
    /* We may not be able to restore the current rlim_cur value.
       So bail out.  */
    return 0;

  {
    /* The granularity is a single page.  */
    const intptr_t pagesize = getpagesize ();

    uintptr_t low_bound = 0;
    uintptr_t high_bound;

    for (;;)
      {
        /* Here we know that the data segment size is >= low_bound.  */
        struct rlimit try_limit;
        uintptr_t try_next = 2 * low_bound + pagesize;

        if (try_next < low_bound)
          /* Overflow.  */
          try_next = ((uintptr_t) (~ 0) / pagesize) * pagesize;

        /* There's no point in trying a value > orig_limit.rlim_max, as
           setrlimit would fail anyway.  */
        if (orig_limit.rlim_max != RLIM_INFINITY
            && orig_limit.rlim_max < try_next)
          try_next = orig_limit.rlim_max;

        /* Avoid endless loop.  */
        if (try_next == low_bound)
          {
            /* try_next could not be increased.  */
            result = low_bound;
            goto done;
          }

        try_limit.rlim_max = orig_limit.rlim_max;
        try_limit.rlim_cur = try_next;
        if (setrlimit (RLIMIT_DATA, &try_limit) == 0)
          {
            /* Allocate a page of memory, to compare the current data segment
               size with try_limit.rlim_cur.  */
            void *new_page = sbrk (pagesize);

            if (new_page != (void *)(-1))
              {
                /* The page could be added successfully.  Free it.  */
                sbrk (- pagesize);
                /* We know that the data segment size is
                   < try_limit.rlim_cur.  */
                high_bound = try_next;
                break;
              }
            else
              {
                /* We know that the data segment size is
                   >= try_limit.rlim_cur.  */
                low_bound = try_next;
              }
          }
        else
          {
            /* Here we expect only EINVAL or (on AIX) EFAULT, not EPERM.  */
            if (! errno_expected ())
              abort ();
            /* We know that the data segment size is
               >= try_limit.rlim_cur.  */
            low_bound = try_next;
          }
      }

    /* Here we know that the data segment size is
       >= low_bound and < high_bound.  */
    while (high_bound - low_bound > pagesize)
      {
        struct rlimit try_limit;
        uintptr_t try_next =
          low_bound + (((high_bound - low_bound) / 2) / pagesize) * pagesize;

        /* Here low_bound <= try_next < high_bound.  */
        try_limit.rlim_max = orig_limit.rlim_max;
        try_limit.rlim_cur = try_next;
        if (setrlimit (RLIMIT_DATA, &try_limit) == 0)
          {
            /* Allocate a page of memory, to compare the current data segment
               size with try_limit.rlim_cur.  */
            void *new_page = sbrk (pagesize);

            if (new_page != (void *)(-1))
              {
                /* The page could be added successfully.  Free it.  */
                sbrk (- pagesize);
                /* We know that the data segment size is
                   < try_limit.rlim_cur.  */
                high_bound = try_next;
              }
            else
              {
                /* We know that the data segment size is
                   >= try_limit.rlim_cur.  */
                low_bound = try_next;
              }
          }
        else
          {
            /* Here we expect only EINVAL or (on AIX) EFAULT, not EPERM.  */
            if (! errno_expected ())
              abort ();
            /* We know that the data segment size is
               >= try_limit.rlim_cur.  */
            low_bound = try_next;
          }
      }

    result = low_bound;
  }

 done:
  /* Restore the original rlim_cur value.  */
  if (setrlimit (RLIMIT_DATA, &orig_limit) < 0)
    abort ();

  return result;
}
Esempio n. 14
0
struct rspamd_worker *
rspamd_fork_worker (struct rspamd_main *rspamd_main,
		struct rspamd_worker_conf *cf,
		guint index,
		struct event_base *ev_base)
{
	struct rspamd_worker *wrk;
	gint rc;
	struct rlimit rlim;

	/* Starting worker process */
	wrk = (struct rspamd_worker *) g_malloc0 (sizeof (struct rspamd_worker));

	if (!rspamd_socketpair (wrk->control_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	if (!rspamd_socketpair (wrk->srv_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	wrk->srv = rspamd_main;
	wrk->type = cf->type;
	wrk->cf = g_malloc (sizeof (struct rspamd_worker_conf));
	memcpy (wrk->cf, cf, sizeof (struct rspamd_worker_conf));
	wrk->index = index;
	wrk->ctx = cf->ctx;
	wrk->finish_actions = g_ptr_array_new ();

	wrk->pid = fork ();

	switch (wrk->pid) {
	case 0:
		/* Update pid for logging */
		rspamd_log_update_pid (cf->type, rspamd_main->logger);

		/* Init PRNG after fork */
		rc = ottery_init (rspamd_main->cfg->libs_ctx->ottery_cfg);
		if (rc != OTTERY_ERR_NONE) {
			msg_err_main ("cannot initialize PRNG: %d", rc);
			g_assert (0);
		}

		rspamd_random_seed_fast ();
		g_random_set_seed (ottery_rand_uint32 ());
#ifdef HAVE_EVUTIL_RNG_INIT
		evutil_secure_rng_init ();
#endif

		/* Remove the inherited event base */
		event_reinit (rspamd_main->ev_base);
		event_base_free (rspamd_main->ev_base);

		/* Drop privilleges */
		rspamd_worker_drop_priv (rspamd_main);
		/* Set limits */
		rspamd_worker_set_limits (rspamd_main, cf);
		/* Re-set stack limit */
		getrlimit (RLIMIT_STACK, &rlim);
		rlim.rlim_cur = 100 * 1024 * 1024;
		rlim.rlim_max = rlim.rlim_cur;
		setrlimit (RLIMIT_STACK, &rlim);

		setproctitle ("%s process", cf->worker->name);
		rspamd_pidfile_close (rspamd_main->pfh);
		/* Do silent log reopen to avoid collisions */
		rspamd_log_close (rspamd_main->logger);
		rspamd_log_open (rspamd_main->logger);
		wrk->start_time = rspamd_get_calendar_ticks ();

#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30))
# if (GLIB_MINOR_VERSION > 20)
		/* Ugly hack for old glib */
		if (!g_thread_get_initialized ()) {
			g_thread_init (NULL);
		}
# else
		g_thread_init (NULL);
# endif
#endif
		msg_info_main ("starting %s process %P (%d)", cf->worker->name,
				getpid (), index);
		/* Close parent part of socketpair */
		close (wrk->control_pipe[0]);
		close (wrk->srv_pipe[0]);
		rspamd_socket_nonblocking (wrk->control_pipe[1]);
		rspamd_socket_nonblocking (wrk->srv_pipe[1]);
		/* Execute worker */
		cf->worker->worker_start_func (wrk);
		exit (EXIT_FAILURE);
		break;
	case -1:
		msg_err_main ("cannot fork main process. %s", strerror (errno));
		rspamd_pidfile_remove (rspamd_main->pfh);
		exit (-errno);
		break;
	default:
		/* Close worker part of socketpair */
		close (wrk->control_pipe[1]);
		close (wrk->srv_pipe[1]);
		rspamd_socket_nonblocking (wrk->control_pipe[0]);
		rspamd_socket_nonblocking (wrk->srv_pipe[0]);
		rspamd_srv_start_watching (wrk, ev_base);
		/* Insert worker into worker's table, pid is index */
		g_hash_table_insert (rspamd_main->workers, GSIZE_TO_POINTER (
				wrk->pid), wrk);
		break;
	}

	return wrk;
}
Esempio n. 15
0
int main(int argc, char **argv)
{
	const struct optstruct *opt;
#ifndef	C_WINDOWS
        struct passwd *user = NULL;
#endif
	time_t currtime;
	const char *dbdir, *cfgfile;
	char *pua_cats = NULL, *pt;
	int ret, tcpsock = 0, localsock = 0, i, min_port, max_port;
	unsigned int sigs = 0;
	int lsockets[2], nlsockets = 0;
	unsigned int dboptions = 0;
#ifdef C_LINUX
	struct stat sb;
#endif

#ifdef C_WINDOWS
    if(!pthread_win32_process_attach_np()) {
	mprintf("!Can't start the win32 pthreads layer\n");
        return 1;
    }
#endif

    if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) {
	mprintf("!Can't parse command line options\n");
	return 1;
    }

    if(optget(opts, "help")->enabled) {
    	help();
	optfree(opts);
	return 0;
    }

    if(optget(opts, "debug")->enabled) {
#if defined(C_LINUX)
	    /* [email protected]: create a dump if needed */
	    struct rlimit rlim;

	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
	if(setrlimit(RLIMIT_CORE, &rlim) < 0)
	    perror("setrlimit");
#endif
	debug_mode = 1;
    }

    /* parse the config file */
    cfgfile = optget(opts, "config-file")->strarg;
    pt = strdup(cfgfile);
    if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) {
	fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt);
	free(pt);
	return 1;
    }
    free(pt);

    if(optget(opts, "version")->enabled) {
	print_version(optget(opts, "DatabaseDirectory")->strarg);
	optfree(opts);
	return 0;
    }

    umask(0);

    /* drop privileges */
#if (!defined(C_OS2)) && (!defined(C_WINDOWS))
    if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) {
	if((user = getpwnam(opt->strarg)) == NULL) {
	    fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg);
	    optfree(opts);
	    return 1;
	}

	if(optget(opts, "AllowSupplementaryGroups")->enabled) {
#ifdef HAVE_INITGROUPS
	    if(initgroups(opt->strarg, user->pw_gid)) {
		fprintf(stderr, "ERROR: initgroups() failed.\n");
		optfree(opts);
		return 1;
	    }
#else
	    mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups in %s\n", cfgfile);
	    optfree(opts);
	    return 1;
#endif
	} else {
#ifdef HAVE_SETGROUPS
	    if(setgroups(1, &user->pw_gid)) {
		fprintf(stderr, "ERROR: setgroups() failed.\n");
		optfree(opts);
		return 1;
	    }
#endif
	}

	if(setgid(user->pw_gid)) {
	    fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid);
	    optfree(opts);
	    return 1;
	}

	if(setuid(user->pw_uid)) {
	    fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid);
	    optfree(opts);
	    return 1;
	}
    }
#endif

    /* initialize logger */
    logg_lock = !optget(opts, "LogFileUnlock")->enabled;
    logg_time = optget(opts, "LogTime")->enabled;
    logok = optget(opts, "LogClean")->enabled;
    logg_size = optget(opts, "LogFileMaxSize")->numarg;
    logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled;
    mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg;

    do { /* logger initialized */

    if((opt = optget(opts, "LogFile"))->enabled) {
	char timestr[32];
	logg_file = opt->strarg;
	if(strlen(logg_file) < 2 || (logg_file[0] != '/' && logg_file[0] != '\\' && logg_file[1] != ':')) {
	    fprintf(stderr, "ERROR: LogFile requires full path.\n");
	    ret = 1;
	    break;
	}
	time(&currtime);
	if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
	    fprintf(stderr, "ERROR: Can't initialize the internal logger\n");
	    ret = 1;
	    break;
	}
    } else
	logg_file = NULL;

    if((ret = cl_init(CL_INIT_DEFAULT))) {
	logg("!Can't initialize libclamav: %s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    if(optget(opts, "Debug")->enabled) /* enable debug messages in libclamav */ {
	cl_debug();
	logg_verbose = 2;
    }

#if defined(USE_SYSLOG) && !defined(C_AIX)
    if(optget(opts, "LogSyslog")->enabled) {
	    int fac = LOG_LOCAL6;

	opt = optget(opts, "LogFacility");
	if((fac = logg_facility(opt->strarg)) == -1) {
	    logg("!LogFacility: %s: No such facility.\n", opt->strarg);
	    ret = 1;
	    break;
	}

	openlog("clamd", LOG_PID, fac);
	logg_syslog = 1;
    }
#endif

#ifdef C_LINUX
    procdev = 0;
    if(stat("/proc", &sb) != -1 && !sb.st_size)
	procdev = sb.st_dev;
#endif

    /* check socket type */

    if(optget(opts, "TCPSocket")->enabled)
	tcpsock = 1;

    if(optget(opts, "LocalSocket")->enabled)
	localsock = 1;

    if(!tcpsock && !localsock) {
	logg("!Please define server type (local and/or TCP).\n");
	ret = 1;
	break;
    }

    logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version());

#ifndef C_WINDOWS
    if(user)
	logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid);
#endif

    if(logg_size)
	logg("#Log file size limited to %d bytes.\n", logg_size);
    else
	logg("#Log file size limit disabled.\n");

    min_port = optget(opts, "StreamMinPort")->numarg;
    max_port = optget(opts, "StreamMaxPort")->numarg;
    if (min_port < 1024 || min_port > max_port || max_port > 65535) {
	logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port);
	ret = 1;
	break;
    }

    if(!(engine = cl_engine_new())) {
	logg("!Can't initialize antivirus engine\n");
	ret = 1;
	break;
    }

    /* load the database(s) */
    dbdir = optget(opts, "DatabaseDirectory")->strarg;
    logg("#Reading databases from %s\n", dbdir);

    if(optget(opts, "DetectPUA")->enabled) {
	dboptions |= CL_DB_PUA;

	if((opt = optget(opts, "ExcludePUA"))->enabled) {
	    dboptions |= CL_DB_PUA_EXCLUDE;
	    i = 0;
	    logg("#Excluded PUA categories:");
	    while(opt) {
		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
		    logg("!Can't allocate memory for pua_cats\n");
		    cl_engine_free(engine);
		    ret = 1;
		    break;
		}
		logg("# %s", opt->strarg);
		sprintf(pua_cats + i, ".%s", opt->strarg);
		i += strlen(opt->strarg) + 1;
		pua_cats[i] = 0;
		opt = opt->nextarg;
	    }
	    if (ret)
		break;
	    logg("#\n");
	    pua_cats[i] = '.';
	    pua_cats[i + 1] = 0;
	}

	if((opt = optget(opts, "IncludePUA"))->enabled) {
	    if(pua_cats) {
		logg("!ExcludePUA and IncludePUA cannot be used at the same time\n");
		free(pua_cats);
		ret = 1;
		break;
	    }
	    dboptions |= CL_DB_PUA_INCLUDE;
	    i = 0;
	    logg("#Included PUA categories:");
	    while(opt) {
		if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) {
		    logg("!Can't allocate memory for pua_cats\n");
		    ret = 1;
		    break;
		}
		logg("# %s", opt->strarg);
		sprintf(pua_cats + i, ".%s", opt->strarg);
		i += strlen(opt->strarg) + 1;
		pua_cats[i] = 0;
		opt = opt->nextarg;
	    }
	    if (ret)
		break;
	    logg("#\n");
	    pua_cats[i] = '.';
	    pua_cats[i + 1] = 0;
	}

	if(pua_cats) {
	    if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) {
		logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret));
		free(pua_cats);
		ret = 1;
		break;
	    }
	    free(pua_cats);
	}
    } else {
	logg("#Not loading PUA signatures.\n");
    }

    /* set the temporary dir */
    if((opt = optget(opts, "TemporaryDirectory"))->enabled) {
	if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) {
	    logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret));
	    ret = 1;
	    break;
	}
    }

    if(optget(opts, "LeaveTemporaryFiles")->enabled)
	cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1);

    if(optget(opts, "PhishingSignatures")->enabled)
	dboptions |= CL_DB_PHISHING;
    else
	logg("#Not loading phishing signatures.\n");

    if(optget(opts,"PhishingScanURLs")->enabled)
	dboptions |= CL_DB_PHISHING_URLS;
    else
	logg("#Disabling URL based phishing detection.\n");

    if(optget(opts,"DevACOnly")->enabled) {
	logg("#Only using the A-C matcher.\n");
	cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1);
    }

    if((opt = optget(opts, "DevACDepth"))->enabled) {
        cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg);
	logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg);
    }

    if((ret = cl_load(dbdir, engine, &sigs, dboptions))) {
	logg("!%s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    logg("#Loaded %u signatures.\n", sigs);
    if((ret = cl_engine_compile(engine)) != 0) {
	logg("!Database initialization error: %s\n", cl_strerror(ret));
	ret = 1;
	break;
    }

    if(tcpsock) {
#ifdef C_WINDOWS
	    WSADATA wsaData;

	if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) {
	    logg("!Error at WSAStartup(): %d\n", WSAGetLastError());
	    ret = 1;
	    break;
	}
#endif
	if ((lsockets[nlsockets] = tcpserver(opts)) == -1) {
	    ret = 1;
	    break;
	}
	nlsockets++;
    }

    if(localsock) {
	if ((lsockets[nlsockets] = localserver(opts)) == -1) {
	    ret = 1;
	    break;
	}
	nlsockets++;
    }

    /* fork into background */
    if(!optget(opts, "Foreground")->enabled) {
#ifdef C_BSD	    
	/* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
	for(ret=0;ret<nlsockets;ret++) {
		fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) | O_NONBLOCK);
	}
#endif
	if(daemonize() == -1) {
	    logg("!daemonize() failed\n");
	    ret = 1;
	    break;
	}
#ifdef C_BSD
	for(ret=0;ret<nlsockets;ret++) {
		fcntl(lsockets[ret], F_SETFL, fcntl(lsockets[ret], F_GETFL) & ~O_NONBLOCK);
	}
#endif
	if(!debug_mode)
	    if(chdir("/") == -1)
		logg("^Can't change current working directory to root\n");

    } else
        foreground = 1;

    ret = recvloop_th(lsockets, nlsockets, engine, dboptions, opts);

    } while (0);

    logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");

    for (i = 0; i < nlsockets; i++) {
	closesocket(lsockets[i]);
    }

#ifndef C_OS2
    if(nlsockets && localsock) {
	opt = optget(opts, "LocalSocket");
	if(unlink(opt->strarg) == -1)
	    logg("!Can't unlink the socket file %s\n", opt->strarg);
	else
	    logg("Socket file removed.\n");
    }
#endif

#ifdef C_WINDOWS
    if(tcpsock)
	WSACleanup();

    if(!pthread_win32_process_detach_np()) {
	logg("!Can't stop the win32 pthreads layer\n");
	logg_close();
	optfree(opts);
	return 1;
    }
#endif

    logg_close();
    optfree(opts);

    return ret;
}
Esempio n. 16
0
File: main.c Progetto: Ga-vin/MINIX3
/*-
 * main --
 *	The main function, for obvious reasons. Initializes variables
 *	and a few modules, then parses the arguments give it in the
 *	environment and on the command line. Reads the system makefile
 *	followed by either Makefile, makefile or the file given by the
 *	-f argument. Sets the .MAKEFLAGS PMake variable based on all the
 *	flags it has received by then uses either the Make or the Compat
 *	module to create the initial list of targets.
 *
 * Results:
 *	If -q was given, exits -1 if anything was out-of-date. Else it exits
 *	0.
 *
 * Side Effects:
 *	The program exits when done. Targets are created. etc. etc. etc.
 */
int
main(int argc, char **argv)
{
	Lst targs;	/* target nodes to create -- passed to Make_Init */
	Boolean outOfDate = FALSE; 	/* FALSE if all targets up to date */
	struct stat sb, sa;
	char *p1, *path, *pwd;
	char mdpath[MAXPATHLEN];
    	const char *machine = getenv("MACHINE");
	const char *machine_arch = getenv("MACHINE_ARCH");
	char *syspath = getenv("MAKESYSPATH");
	Lst sysMkPath;			/* Path of sys.mk */
	char *cp = NULL, *start;
					/* avoid faults on read-only strings */
	static char defsyspath[] = _PATH_DEFSYSPATH;
	char found_path[MAXPATHLEN + 1];	/* for searching for sys.mk */
	struct timeval rightnow;		/* to initialize random seed */
#ifdef MAKE_NATIVE
	struct utsname utsname;
#endif

	/* default to writing debug to stderr */
	debug_file = stderr;

#ifdef SIGINFO
	(void)bmake_signal(SIGINFO, siginfo);
#endif
	/*
	 * Set the seed to produce a different random sequence
	 * on each program execution.
	 */
	gettimeofday(&rightnow, NULL);
	srandom(rightnow.tv_sec + rightnow.tv_usec);
	
	if ((progname = strrchr(argv[0], '/')) != NULL)
		progname++;
	else
		progname = argv[0];
#if defined(RLIMIT_NOFILE) && !defined(__minix)
	/*
	 * get rid of resource limit on file descriptors
	 */
	{
		struct rlimit rl;
		if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
		    rl.rlim_cur != rl.rlim_max) {
			rl.rlim_cur = rl.rlim_max;
			(void)setrlimit(RLIMIT_NOFILE, &rl);
		}
	}
#endif

	/*
	 * Get the name of this type of MACHINE from utsname
	 * so we can share an executable for similar machines.
	 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
	 *
	 * Note that both MACHINE and MACHINE_ARCH are decided at
	 * run-time.
	 */
	if (!machine) {
#ifdef MAKE_NATIVE
	    if (uname(&utsname) == -1) {
		(void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
		    strerror(errno));
		exit(2);
	    }
	    machine = utsname.machine;
#else
#ifdef MAKE_MACHINE
	    machine = MAKE_MACHINE;
#else
	    machine = "unknown";
#endif
#endif
	}

	if (!machine_arch) {
#ifndef MACHINE_ARCH
#ifdef MAKE_MACHINE_ARCH
            machine_arch = MAKE_MACHINE_ARCH;
#else
	    machine_arch = "unknown";
#endif
#else
	    machine_arch = MACHINE_ARCH;
#endif
	}

	myPid = getpid();		/* remember this for vFork() */

	/*
	 * Just in case MAKEOBJDIR wants us to do something tricky.
	 */
	Var_Init();		/* Initialize the lists of variables for
				 * parsing arguments */
	Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
	Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
#ifdef MAKE_VERSION
	Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
#endif
	Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
	/*
	 * This is the traditional preference for makefiles.
	 */
#ifndef MAKEFILE_PREFERENCE_LIST
# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
#endif
	Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
		VAR_GLOBAL, 0);
	Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0);

	create = Lst_Init(FALSE);
	makefiles = Lst_Init(FALSE);
	printVars = FALSE;
	variables = Lst_Init(FALSE);
	beSilent = FALSE;		/* Print commands as executed */
	ignoreErrors = FALSE;		/* Pay attention to non-zero returns */
	noExecute = FALSE;		/* Execute all commands */
	noRecursiveExecute = FALSE;	/* Execute all .MAKE targets */
	keepgoing = FALSE;		/* Stop on error */
	allPrecious = FALSE;		/* Remove targets when interrupted */
	queryFlag = FALSE;		/* This is not just a check-run */
	noBuiltins = FALSE;		/* Read the built-in rules */
	touchFlag = FALSE;		/* Actually update targets */
	debug = 0;			/* No debug verbosity, please. */
	jobsRunning = FALSE;

	maxJobs = DEFMAXLOCAL;		/* Set default local max concurrency */
	maxJobTokens = maxJobs;
	compatMake = FALSE;		/* No compat mode */
	ignorePWD = FALSE;

	/*
	 * Initialize the parsing, directory and variable modules to prepare
	 * for the reading of inclusion paths and variable settings on the
	 * command line
	 */

	/*
	 * Initialize various variables.
	 *	MAKE also gets this name, for compatibility
	 *	.MAKEFLAGS gets set to the empty string just in case.
	 *	MFLAGS also gets initialized empty, for compatibility.
	 */
	Parse_Init();
	if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) {
	    /*
	     * Leave alone if it is an absolute path, or if it does
	     * not contain a '/' in which case we need to find it in
	     * the path, like execvp(3) and the shells do.
	     */
	    p1 = argv[0];
	} else {
	    /*
	     * A relative path, canonicalize it.
	     */
	    p1 = realpath(argv[0], mdpath);
	    if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
		p1 = argv[0];		/* realpath failed */
	    }
	}
	Var_Set("MAKE", p1, VAR_GLOBAL, 0);
	Var_Set(".MAKE", p1, VAR_GLOBAL, 0);
	Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
	Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
	Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
	Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);

	/*
	 * Set some other useful macros
	 */
	{
	    char tmp[64];
	    const char *ep;

	    if (!(ep = getenv(MAKE_LEVEL))) {
		ep = "0";
	    }
	    Var_Set(MAKE_LEVEL, ep, VAR_GLOBAL, 0);
	    snprintf(tmp, sizeof(tmp), "%u", myPid);
	    Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0);
	    snprintf(tmp, sizeof(tmp), "%u", getppid());
	    Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0);
	}
	Job_SetPrefix();

	/*
	 * First snag any flags out of the MAKE environment variable.
	 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
	 * in a different format).
	 */
#ifdef POSIX
	Main_ParseArgLine(getenv("MAKEFLAGS"));
#else
	Main_ParseArgLine(getenv("MAKE"));
#endif

	/*
	 * Find where we are (now).
	 * We take care of PWD for the automounter below...
	 */
	if (getcwd(curdir, MAXPATHLEN) == NULL) {
		(void)fprintf(stderr, "%s: getcwd: %s.\n",
		    progname, strerror(errno));
		exit(2);
	}

	MainParseArgs(argc, argv);

	/*
	 * Verify that cwd is sane.
	 */
	if (stat(curdir, &sa) == -1) {
	    (void)fprintf(stderr, "%s: %s: %s.\n",
		 progname, curdir, strerror(errno));
	    exit(2);
	}

	/*
	 * All this code is so that we know where we are when we start up
	 * on a different machine with pmake.
	 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
	 * since the value of curdir can vary depending on how we got
	 * here.  Ie sitting at a shell prompt (shell that provides $PWD)
	 * or via subdir.mk in which case its likely a shell which does
	 * not provide it.
	 * So, to stop it breaking this case only, we ignore PWD if
	 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
	 */
	if (!ignorePWD &&
	    (pwd = getenv("PWD")) != NULL &&
	    getenv("MAKEOBJDIRPREFIX") == NULL) {
		const char *makeobjdir = getenv("MAKEOBJDIR");

		if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
			if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
			    sa.st_dev == sb.st_dev)
				(void)strncpy(curdir, pwd, MAXPATHLEN);
		}
	}
	Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);

	/*
	 * Find the .OBJDIR.  If MAKEOBJDIRPREFIX, or failing that,
	 * MAKEOBJDIR is set in the environment, try only that value
	 * and fall back to .CURDIR if it does not exist.
	 *
	 * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
	 * finally _PATH_OBJDIRPREFIX`pwd`, in that order.  If none
	 * of these paths exist, just use .CURDIR.
	 */
	Dir_Init(curdir);
	(void)Main_SetObjdir(curdir);

	if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
		(void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
		(void)Main_SetObjdir(mdpath);
	} else if ((path = getenv("MAKEOBJDIR")) != NULL) {
		(void)Main_SetObjdir(path);
	} else {
		(void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
		if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
			(void)snprintf(mdpath, MAXPATHLEN, "%s%s", 
					_PATH_OBJDIRPREFIX, curdir);
			(void)Main_SetObjdir(mdpath);
		}
	}

	/*
	 * Be compatible if user did not specify -j and did not explicitly
	 * turned compatibility on
	 */
	if (!compatMake && !forceJobs) {
		compatMake = TRUE;
	}
	
	/*
	 * Initialize archive, target and suffix modules in preparation for
	 * parsing the makefile(s)
	 */
	Arch_Init();
	Targ_Init();
	Suff_Init();
	Trace_Init(tracefile);

	DEFAULT = NULL;
	(void)time(&now);

	Trace_Log(MAKESTART, NULL);
	
	/*
	 * Set up the .TARGETS variable to contain the list of targets to be
	 * created. If none specified, make the variable empty -- the parser
	 * will fill the thing in with the default or .MAIN target.
	 */
	if (!Lst_IsEmpty(create)) {
		LstNode ln;

		for (ln = Lst_First(create); ln != NULL;
		    ln = Lst_Succ(ln)) {
			char *name = (char *)Lst_Datum(ln);

			Var_Append(".TARGETS", name, VAR_GLOBAL);
		}
	} else
		Var_Set(".TARGETS", "", VAR_GLOBAL, 0);


	/*
	 * If no user-supplied system path was given (through the -m option)
	 * add the directories from the DEFSYSPATH (more than one may be given
	 * as dir1:...:dirn) to the system include path.
	 */
	if (syspath == NULL || *syspath == '\0')
		syspath = defsyspath;
	else
		syspath = bmake_strdup(syspath);

	for (start = syspath; *start != '\0'; start = cp) {
		for (cp = start; *cp != '\0' && *cp != ':'; cp++)
			continue;
		if (*cp == ':') {
			*cp++ = '\0';
		}
		/* look for magic parent directory search string */
		if (strncmp(".../", start, 4) != 0) {
			(void)Dir_AddDir(defIncPath, start);
		} else {
			if (Dir_FindHereOrAbove(curdir, start+4, 
			    found_path, sizeof(found_path))) {
				(void)Dir_AddDir(defIncPath, found_path);
			}
		}
	}
	if (syspath != defsyspath)
		free(syspath);

	/*
	 * Read in the built-in rules first, followed by the specified
	 * makefile, if it was (makefile != NULL), or the default
	 * makefile and Makefile, in that order, if it wasn't.
	 */
	if (!noBuiltins) {
		LstNode ln;

		sysMkPath = Lst_Init(FALSE);
		Dir_Expand(_PATH_DEFSYSMK,
			   Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
			   sysMkPath);
		if (Lst_IsEmpty(sysMkPath))
			Fatal("%s: no system rules (%s).", progname,
			    _PATH_DEFSYSMK);
		ln = Lst_Find(sysMkPath, NULL, ReadMakefile);
		if (ln == NULL)
			Fatal("%s: cannot open %s.", progname,
			    (char *)Lst_Datum(ln));
	}

	if (!Lst_IsEmpty(makefiles)) {
		LstNode ln;

		ln = Lst_Find(makefiles, NULL, ReadAllMakefiles);
		if (ln != NULL)
			Fatal("%s: cannot open %s.", progname, 
			    (char *)Lst_Datum(ln));
	} else {
	    p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
		VAR_CMD, 0);
	    if (p1) {
		(void)str2Lst_Append(makefiles, p1, NULL);
		(void)Lst_Find(makefiles, NULL, ReadMakefile);
		free(p1);
	    }
	}

	/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
	if (!noBuiltins || !printVars) {
	    makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
		VAR_CMD, 0);
	    doing_depend = TRUE;
	    (void)ReadMakefile(makeDependfile, NULL);
	    doing_depend = FALSE;
	}

	MakeMode(NULL);

	Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
	if (p1)
	    free(p1);

	if (!compatMake)
	    Job_ServerStart(maxJobTokens, jp_0, jp_1);
	if (DEBUG(JOB))
	    fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
		jp_0, jp_1, maxJobs, maxJobTokens, compatMake);

	Main_ExportMAKEFLAGS(TRUE);	/* initial export */

	Check_Cwd_av(0, NULL, 0);	/* initialize it */
	

	/*
	 * For compatibility, look at the directories in the VPATH variable
	 * and add them to the search path, if the variable is defined. The
	 * variable's value is in the same format as the PATH envariable, i.e.
	 * <directory>:<directory>:<directory>...
	 */
	if (Var_Exists("VPATH", VAR_CMD)) {
		char *vpath, savec;
		/*
		 * GCC stores string constants in read-only memory, but
		 * Var_Subst will want to write this thing, so store it
		 * in an array
		 */
		static char VPATH[] = "${VPATH}";

		vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
		path = vpath;
		do {
			/* skip to end of directory */
			for (cp = path; *cp != ':' && *cp != '\0'; cp++)
				continue;
			/* Save terminator character so know when to stop */
			savec = *cp;
			*cp = '\0';
			/* Add directory to search path */
			(void)Dir_AddDir(dirSearchPath, path);
			*cp = savec;
			path = cp + 1;
		} while (savec == ':');
		free(vpath);
	}

	/*
	 * Now that all search paths have been read for suffixes et al, it's
	 * time to add the default search path to their lists...
	 */
	Suff_DoPaths();

	/*
	 * Propagate attributes through :: dependency lists.
	 */
	Targ_Propagate();

	/* print the initial graph, if the user requested it */
	if (DEBUG(GRAPH1))
		Targ_PrintGraph(1);

	/* print the values of any variables requested by the user */
	if (printVars) {
		LstNode ln;

		for (ln = Lst_First(variables); ln != NULL;
		    ln = Lst_Succ(ln)) {
			char *var = (char *)Lst_Datum(ln);
			char *value;
			
			if (strchr(var, '$')) {
				value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
			} else {
				value = Var_Value(var, VAR_GLOBAL, &p1);
			}
			printf("%s\n", value ? value : "");
			if (p1)
				free(p1);
		}
	} else {
		/*
		 * Have now read the entire graph and need to make a list of
		 * targets to create. If none was given on the command line,
		 * we consult the parsing module to find the main target(s)
		 * to create.
		 */
		if (Lst_IsEmpty(create))
			targs = Parse_MainName();
		else
			targs = Targ_FindList(create, TARG_CREATE);

		if (!compatMake) {
			/*
			 * Initialize job module before traversing the graph
			 * now that any .BEGIN and .END targets have been read.
			 * This is done only if the -q flag wasn't given
			 * (to prevent the .BEGIN from being executed should
			 * it exist).
			 */
			if (!queryFlag) {
				Job_Init();
				jobsRunning = TRUE;
			}

			/* Traverse the graph, checking on all the targets */
			outOfDate = Make_Run(targs);
		} else {
			/*
			 * Compat_Init will take care of creating all the
			 * targets as well as initializing the module.
			 */
			Compat_Run(targs);
		}
	}

#ifdef CLEANUP
	Lst_Destroy(targs, NULL);
	Lst_Destroy(variables, NULL);
	Lst_Destroy(makefiles, NULL);
	Lst_Destroy(create, (FreeProc *)free);
#endif

	/* print the graph now it's been processed if the user requested it */
	if (DEBUG(GRAPH2))
		Targ_PrintGraph(2);

	Trace_Log(MAKEEND, 0);

	Suff_End();
        Targ_End();
	Arch_End();
	Var_End();
	Parse_End();
	Dir_End();
	Job_End();
	Trace_End();

	return outOfDate ? 1 : 0;
}
Esempio n. 17
0
bool w_start_listener(const char *path)
{
  pthread_t thr;
  pthread_attr_t attr;
  pthread_mutexattr_t mattr;
  struct sigaction sa;
  sigset_t sigset;
#ifdef HAVE_LIBGIMLI_H
  volatile struct gimli_heartbeat *hb = NULL;
#endif
  struct timeval tv;
  void *ignored;
  int n_clients = 0;

  listener_thread = pthread_self();

  pthread_mutexattr_init(&mattr);
  pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(&w_client_lock, &mattr);
  pthread_mutexattr_destroy(&mattr);

#ifdef HAVE_LIBGIMLI_H
  hb = gimli_heartbeat_attach();
#endif

#if defined(HAVE_KQUEUE) || defined(HAVE_FSEVENTS)
  {
    struct rlimit limit;
# ifndef __OpenBSD__
    int mib[2] = { CTL_KERN,
#  ifdef KERN_MAXFILESPERPROC
      KERN_MAXFILESPERPROC
#  else
      KERN_MAXFILES
#  endif
    };
# endif
    int maxperproc;

    getrlimit(RLIMIT_NOFILE, &limit);

# ifndef __OpenBSD__
    size_t len;

    len = sizeof(maxperproc);
    sysctl(mib, 2, &maxperproc, &len, NULL, 0);
    w_log(W_LOG_ERR, "file limit is %" PRIu64
        " kern.maxfilesperproc=%i\n",
        limit.rlim_cur, maxperproc);
# else
    maxperproc = limit.rlim_max;
    w_log(W_LOG_ERR, "openfiles-cur is %" PRIu64
        " openfiles-max=%i\n",
        limit.rlim_cur, maxperproc);
# endif

    if (limit.rlim_cur != RLIM_INFINITY &&
        maxperproc > 0 &&
        limit.rlim_cur < (rlim_t)maxperproc) {
      limit.rlim_cur = maxperproc;

      if (setrlimit(RLIMIT_NOFILE, &limit)) {
        w_log(W_LOG_ERR,
          "failed to raise limit to %" PRIu64 " (%s).\n",
          limit.rlim_cur,
          strerror(errno));
      } else {
        w_log(W_LOG_ERR,
            "raised file limit to %" PRIu64 "\n",
            limit.rlim_cur);
      }
    }

    getrlimit(RLIMIT_NOFILE, &limit);
#ifndef HAVE_FSEVENTS
    if (limit.rlim_cur < 10240) {
      w_log(W_LOG_ERR,
          "Your file descriptor limit is very low (%" PRIu64 "), "
          "please consult the watchman docs on raising the limits\n",
          limit.rlim_cur);
    }
#endif
  }
#endif

  proc_pid = (int)getpid();
  if (gettimeofday(&tv, NULL) == -1) {
    w_log(W_LOG_ERR, "gettimeofday failed: %s\n", strerror(errno));
    return false;
  }
  proc_start_time = (uint64_t)tv.tv_sec;

  signal(SIGPIPE, SIG_IGN);

  /* allow SIGUSR1 and SIGCHLD to wake up a blocked thread, without restarting
   * syscalls */
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = wakeme;
  sa.sa_flags = 0;
  sigaction(SIGUSR1, &sa, NULL);
  sigaction(SIGCHLD, &sa, NULL);

  // Block SIGCHLD everywhere
  sigemptyset(&sigset);
  sigaddset(&sigset, SIGCHLD);
  sigprocmask(SIG_BLOCK, &sigset, NULL);

  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  listener_fd = get_listener_socket(path);
  if (listener_fd == -1) {
    return false;
  }
  w_set_cloexec(listener_fd);

  if (pthread_create(&reaper_thread, NULL, child_reaper, NULL)) {
    w_log(W_LOG_FATAL, "pthread_create(reaper): %s\n",
        strerror(errno));
    return false;
  }

  if (!clients) {
    clients = w_ht_new(2, &client_hash_funcs);
  }

  w_state_load();

#ifdef HAVE_LIBGIMLI_H
  if (hb) {
    gimli_heartbeat_set(hb, GIMLI_HB_RUNNING);
  } else {
    w_setup_signal_handlers();
  }
#else
  w_setup_signal_handlers();
#endif
  w_set_nonblock(listener_fd);

  // Now run the dispatch
  while (!stopping) {
    int client_fd;
    struct watchman_client *client;
    struct pollfd pfd;
    int bufsize;

#ifdef HAVE_LIBGIMLI_H
    if (hb) {
      gimli_heartbeat_set(hb, GIMLI_HB_RUNNING);
    }
#endif

    pfd.events = POLLIN;
    pfd.fd = listener_fd;
    if (poll(&pfd, 1, 10000) < 1 || (pfd.revents & POLLIN) == 0) {
      continue;
    }

#ifdef HAVE_ACCEPT4
    client_fd = accept4(listener_fd, NULL, 0, SOCK_CLOEXEC);
#else
    client_fd = accept(listener_fd, NULL, 0);
#endif
    if (client_fd == -1) {
      continue;
    }
    w_set_cloexec(client_fd);
    bufsize = WATCHMAN_IO_BUF_SIZE;
    setsockopt(client_fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));

    client = calloc(1, sizeof(*client));
    client->fd = client_fd;
    w_log(W_LOG_DBG, "accepted client %p fd=%d\n", client, client_fd);

    if (!w_json_buffer_init(&client->reader)) {
      // FIXME: error handling
    }
    if (!w_json_buffer_init(&client->writer)) {
      // FIXME: error handling
    }
    if (pipe(client->ping)) {
      // FIXME: error handling
    }
    client->subscriptions = w_ht_new(2, &subscription_hash_funcs);
    w_set_cloexec(client->ping[0]);
    w_set_nonblock(client->ping[0]);
    w_set_cloexec(client->ping[1]);
    w_set_nonblock(client->ping[1]);

    pthread_mutex_lock(&w_client_lock);
    w_ht_set(clients, client->fd, w_ht_ptr_val(client));
    pthread_mutex_unlock(&w_client_lock);

    // Start a thread for the client.
    // We used to use libevent for this, but we have
    // a low volume of concurrent clients and the json
    // parse/encode APIs are not easily used in a non-blocking
    // server architecture.
    if (pthread_create(&thr, &attr, client_thread, client)) {
      // It didn't work out, sorry!
      pthread_mutex_lock(&w_client_lock);
      w_ht_del(clients, client->fd);
      pthread_mutex_unlock(&w_client_lock);
    }
  }

  pthread_attr_destroy(&attr);

  /* close out some resources to persuade valgrind to run clean */
  close(listener_fd);
  listener_fd = -1;

  // Wait for clients, waking any sleeping clients up in the process
  do {
    w_ht_iter_t iter;

    pthread_mutex_lock(&w_client_lock);
    n_clients = w_ht_size(clients);

    if (w_ht_first(clients, &iter)) do {
      struct watchman_client *client = w_ht_val_ptr(iter.value);
      ignore_result(write(client->ping[1], "a", 1));
    } while (w_ht_next(clients, &iter));

    pthread_mutex_unlock(&w_client_lock);

    w_log(W_LOG_ERR, "waiting for %d clients to terminate\n", n_clients);
    usleep(2000);
  } while (n_clients > 0);

  w_root_free_watched_roots();

  pthread_join(reaper_thread, &ignored);
  cfg_shutdown();

  return true;
}
Esempio n. 18
0
int main(int argc, char **argv) {
	UNUSED(argv);

//	dox_hooks_install();

	struct rlimit memlim;

	memlim.rlim_cur = 4 * GB;
	memlim.rlim_max = memlim.rlim_cur;
	setrlimit(RLIMIT_AS, &memlim);

	ppk_print_init();

	dox_texts_init(&texts);

	dox_store_t *store = dox_store_new("/home/dirk/tmp/dox");
	assert (store != NULL);

	dox_store_scan(store, iter_callback, NULL);

	if (texts.count == 0)
		goto unstore;

//	dox_mindex_t *mindex = dox_mindex_new_flags(DOX_MINDEX_DELTA);
	dox_mindex_t *mindex = dox_mindex_new_flags(DOX_MINDEX_ABSOLUTE);
//	dox_mindex_t *mindex = dox_mindex_new_flags(DOX_MINDEX_ABSOLUTE | DOX_MINDEX_DELTA);
//	dox_mindex_t *mindex = dox_mindex_new_flags(0);
	assert (mindex != NULL);

	uint32_t total_bit_widths = 0;

	int64_t time0 = ppk_time_get_ns();

	for (int i = 0; i < texts.count; i++) {
		const dox_text_t *text = texts.items + i;

		total_bit_widths += dox_text_bit_width(text);

		int ret = dox_mindex_add(mindex, text);

		if (ret != 0) {
			printf("Mindex now full\n\n");
			break;
		}
	}

	int64_t time1 = ppk_time_get_ns();

	printf("Indexed %lu MiB in %ld ms (%ld us per text)\n\n",
		(total_size * sizeof(dox_word_t)) / PPK_MiB,
		(long) ((time1 - time0) / PPK_MILLION),
		(long) ((time1 - time0) / (PPK_THOUSAND * texts.count)));

	printf("Average of %d bits per word\n",
		(int) (total_bit_widths / texts.count));


	dox_mindex_make_skip(mindex);

	dox_mindex_print_memory(mindex);



	dox_copies_t copies;
	dox_copies_init(&copies);
	unsigned long total_copies = 0;

	time0 = ppk_time_get_ns();

	for (int i = 0; i < texts.count; i++) {
		copies.count = 0;
		dox_mindex_get(mindex, &copies, texts.items + i, DOX_INDEX_SMART);

		total_copies += copies.count;
		if (total_copies < (unsigned long) copies.count)
			printf("\nCopy count wrapped after text %d\n", i);

		uint32_t done = i + 1;
		if ((texts.count - done) % 100 == 0) {
			time1 = ppk_time_get_ns();
			int64_t timed = time1 - time0;
			int64_t pertext = timed / (done * PPK_MILLION);

			printf("\r%d/%d (%d%%), %lu ms per text",
					done, texts.count, ppk_percent(done, texts.count),
					(unsigned long) pertext);
			fflush(stdout);
		}
	}

	printf("\n");

	time1 = ppk_time_get_ns();

	printf("\nSearched %d texts in %lu ms, %lu copies\n",
			texts.count,
			(unsigned long) ((time1 - time0) / PPK_MILLION),
			total_copies);

	printf(" (%lu ms per text, %lu us per word, %lu us per copy)\n",
			(unsigned long) ((time1 - time0) / (PPK_MILLION * texts.count)),
			(unsigned long) ((time1 - time0) / (PPK_THOUSAND * total_size)),
			(unsigned long) ((time1 - time0) / (PPK_THOUSAND * total_copies)));

	dox_copies_free(&copies);



	dox_mindex_free(mindex);

unstore:
	dox_texts_free(&texts);
	dox_store_free(store);

	ppk_print_free();

	dox_hooks_dump();

	return 0;
}
Esempio n. 19
0
static int
ksandbox_capsicum_init_worker(void *arg, int fd1, int fd2)
{
	int rc;
	struct rlimit	 rl_zero;
	cap_rights_t	 rights;

	cap_rights_init(&rights);

	/* 
	 * Test for EBADF because STDIN_FILENO is usually closed by the
	 * caller.
	 */
	cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_FSTAT);
	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && 
		 errno != ENOSYS && errno != EBADF) {
 		XWARN("cap_rights_limit: STDIN_FILENO");
		return(0);
	}

	cap_rights_init(&rights, CAP_EVENT, CAP_WRITE, CAP_FSTAT);
	if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && 
		 errno != ENOSYS) {
		XWARN("cap_rights_limit: STDERR_FILENO");
		return(0);
	}

	cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE, CAP_FSTAT);
	if (-1 != fd1 && cap_rights_limit(fd1, &rights) < 0 && 
		 errno != ENOSYS) {
		XWARN("cap_rights_limit: internal socket");
		return(0);
	}
	if (-1 != fd2 && cap_rights_limit(fd2, &rights) < 0 && 
		 errno != ENOSYS) {
		XWARN("cap_rights_limit: internal socket");
		return(0);
	}

	rl_zero.rlim_cur = rl_zero.rlim_max = 0;

	if (-1 == setrlimit(RLIMIT_NOFILE, &rl_zero)) {
		XWARNX("setrlimit: rlimit_fsize");
		return(0);
	} else if (-1 == setrlimit(RLIMIT_FSIZE, &rl_zero)) {
		XWARNX("setrlimit: rlimit_fsize");
		return(0);
	} else if (-1 == setrlimit(RLIMIT_NPROC, &rl_zero)) {
		XWARNX("setrlimit: rlimit_nproc");
		return(0);
	}

	rc = cap_enter();
	if (0 != rc && errno != ENOSYS) {
		XWARN("cap_enter");
		rc = 0;
	} else
		rc = 1;

	return(rc);
}
Esempio n. 20
0
/*
 * Main program for the ssh client.
 */
int
main(int ac, char **av)
{
	int i, r, opt, exit_status, use_syslog;
	char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile;
	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
	struct stat st;
	struct passwd *pw;
	int dummy, timeout_ms;
	extern int optind, optreset;
	extern char *optarg;

	struct servent *sp;
	Forward fwd;

	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
	sanitise_stdfd();

	__progname = ssh_get_progname(av[0]);

#ifndef HAVE_SETPROCTITLE
	/* Prepare for later setproctitle emulation */
	/* Save argv so it isn't clobbered by setproctitle() emulation */
	saved_av = xcalloc(ac + 1, sizeof(*saved_av));
	for (i = 0; i < ac; i++)
		saved_av[i] = xstrdup(av[i]);
	saved_av[i] = NULL;
	compat_init_setproctitle(ac, av);
	av = saved_av;
#endif

	/*
	 * Discard other fds that are hanging around. These can cause problem
	 * with backgrounded ssh processes started by ControlPersist.
	 */
	closefrom(STDERR_FILENO + 1);

	/*
	 * Save the original real uid.  It will be needed later (uid-swapping
	 * may clobber the real uid).
	 */
	original_real_uid = getuid();
	original_effective_uid = geteuid();

	/*
	 * Use uid-swapping to give up root privileges for the duration of
	 * option processing.  We will re-instantiate the rights when we are
	 * ready to create the privileged port, and will permanently drop
	 * them when the port has been created (actually, when the connection
	 * has been made, as we may need to create the port several times).
	 */
	PRIV_END;

#ifdef HAVE_SETRLIMIT
	/* If we are installed setuid root be careful to not drop core. */
	if (original_real_uid != original_effective_uid) {
		struct rlimit rlim;
		rlim.rlim_cur = rlim.rlim_max = 0;
		if (setrlimit(RLIMIT_CORE, &rlim) < 0)
			fatal("setrlimit failed: %.100s", strerror(errno));
	}
#endif
	/* Get user data. */
	pw = getpwuid(original_real_uid);
	if (!pw) {
		logit("No user exists for uid %lu", (u_long)original_real_uid);
		exit(255);
	}
	/* Take a copy of the returned structure. */
	pw = pwcopy(pw);

	/*
	 * Set our umask to something reasonable, as some files are created
	 * with the default umask.  This will make them world-readable but
	 * writable only by the owner, which is ok for all files for which we
	 * don't set the modes explicitly.
	 */
	umask(022);

	/*
	 * Initialize option structure to indicate that no values have been
	 * set.
	 */
	initialize_options(&options);

	/* Parse command-line arguments. */
	host = NULL;
	use_syslog = 0;
	logfile = NULL;
	argv0 = av[0];

 again:
	while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
	    "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
		switch (opt) {
		case '1':
			options.protocol = SSH_PROTO_1;
			break;
		case '2':
			options.protocol = SSH_PROTO_2;
			break;
		case '4':
			options.address_family = AF_INET;
			break;
		case '6':
			options.address_family = AF_INET6;
			break;
		case 'n':
			stdin_null_flag = 1;
			break;
		case 'f':
			fork_after_authentication_flag = 1;
			stdin_null_flag = 1;
			break;
		case 'x':
			options.forward_x11 = 0;
			break;
		case 'X':
			options.forward_x11 = 1;
			break;
		case 'y':
			use_syslog = 1;
			break;
		case 'E':
			logfile = xstrdup(optarg);
			break;
		case 'Y':
			options.forward_x11 = 1;
			options.forward_x11_trusted = 1;
			break;
		case 'g':
			options.gateway_ports = 1;
			break;
		case 'O':
			if (stdio_forward_host != NULL)
				fatal("Cannot specify multiplexing "
				    "command with -W");
			else if (muxclient_command != 0)
				fatal("Multiplexing command already specified");
			if (strcmp(optarg, "check") == 0)
				muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
			else if (strcmp(optarg, "forward") == 0)
				muxclient_command = SSHMUX_COMMAND_FORWARD;
			else if (strcmp(optarg, "exit") == 0)
				muxclient_command = SSHMUX_COMMAND_TERMINATE;
			else if (strcmp(optarg, "stop") == 0)
				muxclient_command = SSHMUX_COMMAND_STOP;
			else if (strcmp(optarg, "cancel") == 0)
				muxclient_command = SSHMUX_COMMAND_CANCEL_FWD;
			else
				fatal("Invalid multiplex command.");
			break;
		case 'P':	/* deprecated */
			options.use_privileged_port = 0;
			break;
		case 'Q':	/* deprecated */
			cp = NULL;
			if (strcasecmp(optarg, "cipher") == 0)
				cp = cipher_alg_list();
			else if (strcasecmp(optarg, "mac") == 0)
				cp = mac_alg_list();
			else if (strcasecmp(optarg, "kex") == 0)
				cp = kex_alg_list();
			else if (strcasecmp(optarg, "key") == 0)
				cp = key_alg_list();
			if (cp == NULL)
				fatal("Unsupported query \"%s\"", optarg);
			printf("%s\n", cp);
			free(cp);
			exit(0);
			break;
		case 'a':
			options.forward_agent = 0;
			break;
		case 'A':
			options.forward_agent = 1;
			break;
		case 'k':
			options.gss_deleg_creds = 0;
			break;
		case 'K':
			options.gss_authentication = 1;
			options.gss_deleg_creds = 1;
			break;
		case 'i':
			if (stat(optarg, &st) < 0) {
				fprintf(stderr, "Warning: Identity file %s "
				    "not accessible: %s.\n", optarg,
				    strerror(errno));
				break;
			}
			add_identity_file(&options, NULL, optarg, 1);
			break;
		case 'I':
#ifdef ENABLE_PKCS11
			options.pkcs11_provider = xstrdup(optarg);
#else
			fprintf(stderr, "no support for PKCS#11.\n");
#endif
			break;
		case 't':
			if (options.request_tty == REQUEST_TTY_YES)
				options.request_tty = REQUEST_TTY_FORCE;
			else
				options.request_tty = REQUEST_TTY_YES;
			break;
		case 'v':
			if (debug_flag == 0) {
				debug_flag = 1;
				options.log_level = SYSLOG_LEVEL_DEBUG1;
			} else {
				if (options.log_level < SYSLOG_LEVEL_DEBUG3)
					options.log_level++;
			}
			break;
		case 'V':
			if (options.version_addendum &&
			    *options.version_addendum != '\0')
				fprintf(stderr, "%s%s %s, %s\n", SSH_RELEASE,
				    options.hpn_disabled ? "" : SSH_VERSION_HPN,
				    options.version_addendum,
				    SSLeay_version(SSLEAY_VERSION));
			else
				fprintf(stderr, "%s%s, %s\n", SSH_RELEASE,
				    options.hpn_disabled ? "" : SSH_VERSION_HPN,
				    SSLeay_version(SSLEAY_VERSION));
			if (opt == 'V')
				exit(0);
			break;
		case 'w':
			if (options.tun_open == -1)
				options.tun_open = SSH_TUNMODE_DEFAULT;
			options.tun_local = a2tun(optarg, &options.tun_remote);
			if (options.tun_local == SSH_TUNID_ERR) {
				fprintf(stderr,
				    "Bad tun device '%s'\n", optarg);
				exit(255);
			}
			break;
		case 'W':
			if (stdio_forward_host != NULL)
				fatal("stdio forward already specified");
			if (muxclient_command != 0)
				fatal("Cannot specify stdio forward with -O");
			if (parse_forward(&fwd, optarg, 1, 0)) {
				stdio_forward_host = fwd.listen_host;
				stdio_forward_port = fwd.listen_port;
				free(fwd.connect_host);
			} else {
				fprintf(stderr,
				    "Bad stdio forwarding specification '%s'\n",
				    optarg);
				exit(255);
			}
			options.request_tty = REQUEST_TTY_NO;
			no_shell_flag = 1;
			options.clear_forwardings = 1;
			options.exit_on_forward_failure = 1;
			break;
		case 'q':
			options.log_level = SYSLOG_LEVEL_QUIET;
			break;
		case 'e':
			if (optarg[0] == '^' && optarg[2] == 0 &&
			    (u_char) optarg[1] >= 64 &&
			    (u_char) optarg[1] < 128)
				options.escape_char = (u_char) optarg[1] & 31;
			else if (strlen(optarg) == 1)
				options.escape_char = (u_char) optarg[0];
			else if (strcmp(optarg, "none") == 0)
				options.escape_char = SSH_ESCAPECHAR_NONE;
			else {
				fprintf(stderr, "Bad escape character '%s'.\n",
				    optarg);
				exit(255);
			}
			break;
		case 'c':
			if (ciphers_valid(optarg)) {
				/* SSH2 only */
				options.ciphers = xstrdup(optarg);
				options.cipher = SSH_CIPHER_INVALID;
			} else {
				/* SSH1 only */
				options.cipher = cipher_number(optarg);
				if (options.cipher == -1) {
					fprintf(stderr,
					    "Unknown cipher type '%s'\n",
					    optarg);
					exit(255);
				}
				if (options.cipher == SSH_CIPHER_3DES)
					options.ciphers = "3des-cbc";
				else if (options.cipher == SSH_CIPHER_BLOWFISH)
					options.ciphers = "blowfish-cbc";
				else
					options.ciphers = (char *)-1;
			}
			break;
		case 'm':
			if (mac_valid(optarg))
				options.macs = xstrdup(optarg);
			else {
				fprintf(stderr, "Unknown mac type '%s'\n",
				    optarg);
				exit(255);
			}
			break;
		case 'M':
			if (options.control_master == SSHCTL_MASTER_YES)
				options.control_master = SSHCTL_MASTER_ASK;
			else
				options.control_master = SSHCTL_MASTER_YES;
			break;
		case 'p':
			options.port = a2port(optarg);
			if (options.port <= 0) {
				fprintf(stderr, "Bad port '%s'\n", optarg);
				exit(255);
			}
			break;
		case 'l':
			options.user = optarg;
			break;

		case 'L':
			if (parse_forward(&fwd, optarg, 0, 0))
				add_local_forward(&options, &fwd);
			else {
				fprintf(stderr,
				    "Bad local forwarding specification '%s'\n",
				    optarg);
				exit(255);
			}
			break;

		case 'R':
			if (parse_forward(&fwd, optarg, 0, 1)) {
				add_remote_forward(&options, &fwd);
			} else {
				fprintf(stderr,
				    "Bad remote forwarding specification "
				    "'%s'\n", optarg);
				exit(255);
			}
			break;

		case 'D':
			if (parse_forward(&fwd, optarg, 1, 0)) {
				add_local_forward(&options, &fwd);
			} else {
				fprintf(stderr,
				    "Bad dynamic forwarding specification "
				    "'%s'\n", optarg);
				exit(255);
			}
			break;

		case 'C':
			options.compression = 1;
			break;
		case 'N':
			no_shell_flag = 1;
			options.request_tty = REQUEST_TTY_NO;
			break;
		case 'T':
			options.request_tty = REQUEST_TTY_NO;
#ifdef	NONE_CIPHER_ENABLED
			/*
			 * Ensure that the user does not try to backdoor a
			 * NONE cipher switch on an interactive session by
			 * explicitly disabling it if the user asks for a
			 * session without a tty.
			 */
			options.none_switch = 0;
#endif
			break;
		case 'o':
			dummy = 1;
			line = xstrdup(optarg);
			if (process_config_line(&options, host ? host : "",
			    line, "command-line", 0, &dummy, SSHCONF_USERCONF)
			    != 0)
				exit(255);
			free(line);
			break;
		case 's':
			subsystem_flag = 1;
			break;
		case 'S':
			if (options.control_path != NULL)
				free(options.control_path);
			options.control_path = xstrdup(optarg);
			break;
		case 'b':
			options.bind_address = optarg;
			break;
		case 'F':
			config = optarg;
			break;
		default:
			usage();
		}
	}

	ac -= optind;
	av += optind;

	if (ac > 0 && !host) {
		if (strrchr(*av, '@')) {
			p = xstrdup(*av);
			cp = strrchr(p, '@');
			if (cp == NULL || cp == p)
				usage();
			options.user = p;
			*cp = '\0';
			host = ++cp;
		} else
			host = *av;
		if (ac > 1) {
			optind = optreset = 1;
			goto again;
		}
		ac--, av++;
	}

	/* Check that we got a host name. */
	if (!host)
		usage();

	OpenSSL_add_all_algorithms();
	ERR_load_crypto_strings();

	/* Initialize the command to execute on remote host. */
	buffer_init(&command);

	/*
	 * Save the command to execute on the remote host in a buffer. There
	 * is no limit on the length of the command, except by the maximum
	 * packet size.  Also sets the tty flag if there is no command.
	 */
	if (!ac) {
		/* No command specified - execute shell on a tty. */
		if (subsystem_flag) {
			fprintf(stderr,
			    "You must specify a subsystem to invoke.\n");
			usage();
		}
	} else {
		/* A command has been specified.  Store it into the buffer. */
		for (i = 0; i < ac; i++) {
			if (i)
				buffer_append(&command, " ", 1);
			buffer_append(&command, av[i], strlen(av[i]));
		}
	}

	/* Cannot fork to background if no command. */
	if (fork_after_authentication_flag && buffer_len(&command) == 0 &&
	    !no_shell_flag)
		fatal("Cannot fork into background without a command "
		    "to execute.");

	/*
	 * Initialize "log" output.  Since we are the client all output
	 * goes to stderr unless otherwise specified by -y or -E.
	 */
	if (use_syslog && logfile != NULL)
		fatal("Can't specify both -y and -E");
	if (logfile != NULL) {
		log_redirect_stderr_to(logfile);
		free(logfile);
	}
	log_init(argv0,
	    options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
	    SYSLOG_FACILITY_USER, !use_syslog);

	if (debug_flag)
		logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION));

	/*
	 * Read per-user configuration file.  Ignore the system wide config
	 * file if the user specifies a config file on the command line.
	 */
	if (config != NULL) {
		if (strcasecmp(config, "none") != 0 &&
		    !read_config_file(config, host, &options, SSHCONF_USERCONF))
			fatal("Can't open user config file %.100s: "
			    "%.100s", config, strerror(errno));
	} else {
		r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
		    _PATH_SSH_USER_CONFFILE);
		if (r > 0 && (size_t)r < sizeof(buf))
			(void)read_config_file(buf, host, &options,
			     SSHCONF_CHECKPERM|SSHCONF_USERCONF);

		/* Read systemwide configuration file after user config. */
		(void)read_config_file(_PATH_HOST_CONFIG_FILE, host,
		    &options, 0);
	}

	/* Fill configuration defaults. */
	fill_default_options(&options);

	channel_set_af(options.address_family);

	/* reinit */
	log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);

	if (options.request_tty == REQUEST_TTY_YES ||
	    options.request_tty == REQUEST_TTY_FORCE)
		tty_flag = 1;

	/* Allocate a tty by default if no command specified. */
	if (buffer_len(&command) == 0)
		tty_flag = options.request_tty != REQUEST_TTY_NO;

	/* Force no tty */
	if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0)
		tty_flag = 0;
	/* Do not allocate a tty if stdin is not a tty. */
	if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
	    options.request_tty != REQUEST_TTY_FORCE) {
		if (tty_flag)
			logit("Pseudo-terminal will not be allocated because "
			    "stdin is not a terminal.");
		tty_flag = 0;
	}

	seed_rng();

	if (options.user == NULL)
		options.user = xstrdup(pw->pw_name);

	/* Get default port if port has not been set. */
	if (options.port == 0) {
		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
		options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
	}

	/* preserve host name given on command line for %n expansion */
	host_arg = host;
	if (options.hostname != NULL) {
		host = percent_expand(options.hostname,
		    "h", host, (char *)NULL);
	}

	if (gethostname(thishost, sizeof(thishost)) == -1)
		fatal("gethostname: %s", strerror(errno));
	strlcpy(shorthost, thishost, sizeof(shorthost));
	shorthost[strcspn(thishost, ".")] = '\0';
	snprintf(portstr, sizeof(portstr), "%d", options.port);

	if (options.local_command != NULL) {
		debug3("expanding LocalCommand: %s", options.local_command);
		cp = options.local_command;
		options.local_command = percent_expand(cp, "d", pw->pw_dir,
		    "h", host, "l", thishost, "n", host_arg, "r", options.user,
		    "p", portstr, "u", pw->pw_name, "L", shorthost,
		    (char *)NULL);
		debug3("expanded LocalCommand: %s", options.local_command);
		free(cp);
	}

	/* Find canonic host name. */
	if (strchr(host, '.') == 0) {
		struct addrinfo hints;
		struct addrinfo *ai = NULL;
		int errgai;
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = options.address_family;
		hints.ai_flags = AI_CANONNAME;
		hints.ai_socktype = SOCK_STREAM;
		errgai = getaddrinfo(host, NULL, &hints, &ai);
		if (errgai == 0) {
			if (ai->ai_canonname != NULL)
				host = xstrdup(ai->ai_canonname);
			freeaddrinfo(ai);
		}
	}

	/* force lowercase for hostkey matching */
	if (options.host_key_alias != NULL) {
		for (p = options.host_key_alias; *p; p++)
			if (isupper(*p))
				*p = (char)tolower(*p);
	}

	if (options.proxy_command != NULL &&
	    strcmp(options.proxy_command, "none") == 0) {
		free(options.proxy_command);
		options.proxy_command = NULL;
	}
	if (options.control_path != NULL &&
	    strcmp(options.control_path, "none") == 0) {
		free(options.control_path);
		options.control_path = NULL;
	}

	if (options.control_path != NULL) {
		cp = tilde_expand_filename(options.control_path,
		    original_real_uid);
		free(options.control_path);
		options.control_path = percent_expand(cp, "h", host,
		    "l", thishost, "n", host_arg, "r", options.user,
		    "p", portstr, "u", pw->pw_name, "L", shorthost,
		    (char *)NULL);
		free(cp);
	}
	if (muxclient_command != 0 && options.control_path == NULL)
		fatal("No ControlPath specified for \"-O\" command");
	if (options.control_path != NULL)
		muxclient(options.control_path);

	timeout_ms = options.connection_timeout * 1000;

	/* Open a connection to the remote host. */
	if (ssh_connect(host, &hostaddr, options.port,
	    options.address_family, options.connection_attempts, &timeout_ms,
	    options.tcp_keep_alive, 
#ifdef HAVE_CYGWIN
	    options.use_privileged_port,
#else
	    original_effective_uid == 0 && options.use_privileged_port,
#endif
	    options.proxy_command) != 0)
		exit(255);

	if (timeout_ms > 0)
		debug3("timeout: %d ms remain after connect", timeout_ms);

	/*
	 * If we successfully made the connection, load the host private key
	 * in case we will need it later for combined rsa-rhosts
	 * authentication. This must be done before releasing extra
	 * privileges, because the file is only readable by root.
	 * If we cannot access the private keys, load the public keys
	 * instead and try to execute the ssh-keysign helper instead.
	 */
	sensitive_data.nkeys = 0;
	sensitive_data.keys = NULL;
	sensitive_data.external_keysign = 0;
	if (options.rhosts_rsa_authentication ||
	    options.hostbased_authentication) {
		sensitive_data.nkeys = 7;
		sensitive_data.keys = xcalloc(sensitive_data.nkeys,
		    sizeof(Key));
		for (i = 0; i < sensitive_data.nkeys; i++)
			sensitive_data.keys[i] = NULL;

		PRIV_START;
		sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
		    _PATH_HOST_KEY_FILE, "", NULL, NULL);
		sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
		    _PATH_HOST_DSA_KEY_FILE, "", NULL);
#ifdef OPENSSL_HAS_ECC
		sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA,
		    _PATH_HOST_ECDSA_KEY_FILE, "", NULL);
#endif
		sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
		    _PATH_HOST_RSA_KEY_FILE, "", NULL);
		sensitive_data.keys[4] = key_load_private_type(KEY_DSA,
		    _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
#ifdef OPENSSL_HAS_ECC
		sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
		    _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
#endif
		sensitive_data.keys[6] = key_load_private_type(KEY_RSA,
		    _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
		PRIV_END;

		if (options.hostbased_authentication == 1 &&
		    sensitive_data.keys[0] == NULL &&
		    sensitive_data.keys[4] == NULL &&
		    sensitive_data.keys[5] == NULL &&
		    sensitive_data.keys[6] == NULL) {
			sensitive_data.keys[1] = key_load_cert(
			    _PATH_HOST_DSA_KEY_FILE);
#ifdef OPENSSL_HAS_ECC
			sensitive_data.keys[2] = key_load_cert(
			    _PATH_HOST_ECDSA_KEY_FILE);
#endif
			sensitive_data.keys[3] = key_load_cert(
			    _PATH_HOST_RSA_KEY_FILE);
			sensitive_data.keys[4] = key_load_public(
			    _PATH_HOST_DSA_KEY_FILE, NULL);
#ifdef OPENSSL_HAS_ECC
			sensitive_data.keys[5] = key_load_public(
			    _PATH_HOST_ECDSA_KEY_FILE, NULL);
#endif
			sensitive_data.keys[6] = key_load_public(
			    _PATH_HOST_RSA_KEY_FILE, NULL);
			sensitive_data.external_keysign = 1;
		}
	}
	/*
	 * Get rid of any extra privileges that we may have.  We will no
	 * longer need them.  Also, extra privileges could make it very hard
	 * to read identity files and other non-world-readable files from the
	 * user's home directory if it happens to be on a NFS volume where
	 * root is mapped to nobody.
	 */
	if (original_effective_uid == 0) {
		PRIV_START;
		permanently_set_uid(pw);
	}

	/*
	 * Now that we are back to our own permissions, create ~/.ssh
	 * directory if it doesn't already exist.
	 */
	if (config == NULL) {
		r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
		    strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
		if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) {
#ifdef WITH_SELINUX
			ssh_selinux_setfscreatecon(buf);
#endif
			if (mkdir(buf, 0700) < 0)
				error("Could not create directory '%.200s'.",
				    buf);
#ifdef WITH_SELINUX
			ssh_selinux_setfscreatecon(NULL);
#endif
		}
	}
	/* load options.identity_files */
	load_public_identity_files();

	/* Expand ~ in known host file names. */
	tilde_expand_paths(options.system_hostfiles,
	    options.num_system_hostfiles);
	tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);

	signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
	signal(SIGCHLD, main_sigchld_handler);

	/* Log into the remote system.  Never returns if the login fails. */
	ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
	    options.port, pw, timeout_ms);

	if (packet_connection_is_on_socket()) {
		verbose("Authenticated to %s ([%s]:%d).", host,
		    get_remote_ipaddr(), get_remote_port());
	} else {
		verbose("Authenticated to %s (via proxy).", host);
	}

	/* We no longer need the private host keys.  Clear them now. */
	if (sensitive_data.nkeys != 0) {
		for (i = 0; i < sensitive_data.nkeys; i++) {
			if (sensitive_data.keys[i] != NULL) {
				/* Destroys contents safely */
				debug3("clear hostkey %d", i);
				key_free(sensitive_data.keys[i]);
				sensitive_data.keys[i] = NULL;
			}
		}
		free(sensitive_data.keys);
	}
	for (i = 0; i < options.num_identity_files; i++) {
		free(options.identity_files[i]);
		options.identity_files[i] = NULL;
		if (options.identity_keys[i]) {
			key_free(options.identity_keys[i]);
			options.identity_keys[i] = NULL;
		}
	}

	exit_status = compat20 ? ssh_session2() : ssh_session();
	packet_close();

	if (options.control_path != NULL && muxserver_sock != -1)
		unlink(options.control_path);

	/* Kill ProxyCommand if it is running. */
	ssh_kill_proxy_command();

	return exit_status;
}
Esempio n. 21
0
File: pax.c Progetto: camomiles/eou
static int
gen_init(void)
{
	struct rlimit reslimit;
	struct sigaction n_hand;

	/*
	 * Really needed to handle large archives. We can run out of memory for
	 * internal tables really fast when we have a whole lot of files...
	 */
	if (getrlimit(RLIMIT_DATA , &reslimit) == 0){
		reslimit.rlim_cur = reslimit.rlim_max;
		(void)setrlimit(RLIMIT_DATA , &reslimit);
	}

	/*
	 * should file size limits be waived? if the os limits us, this is
	 * needed if we want to write a large archive
	 */
	if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){
		reslimit.rlim_cur = reslimit.rlim_max;
		(void)setrlimit(RLIMIT_FSIZE , &reslimit);
	}

	/*
	 * increase the size the stack can grow to
	 */
	if (getrlimit(RLIMIT_STACK , &reslimit) == 0){
		reslimit.rlim_cur = reslimit.rlim_max;
		(void)setrlimit(RLIMIT_STACK , &reslimit);
	}

	/*
	 * not really needed, but doesn't hurt
	 */
	if (getrlimit(RLIMIT_RSS , &reslimit) == 0){
		reslimit.rlim_cur = reslimit.rlim_max;
		(void)setrlimit(RLIMIT_RSS , &reslimit);
	}

	/*
	 * signal handling to reset stored directory times and modes. Since
	 * we deal with broken pipes via failed writes we ignore it. We also
	 * deal with any file size limit through failed writes. Cpu time
	 * limits are caught and a cleanup is forced.
	 */
	if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
	    (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) ||
	    (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) ||
	    (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)) {
		paxwarn(1, "Unable to set up signal mask");
		return(-1);
	}

	/* snag the fd to be used from the signal handler */
	listfd = fileno(listf);

	memset(&n_hand, 0, sizeof n_hand);
	n_hand.sa_mask = s_mask;
	n_hand.sa_flags = 0;
	n_hand.sa_handler = sig_cleanup;

	if (setup_sig(SIGHUP,  &n_hand) ||
	    setup_sig(SIGTERM, &n_hand) ||
	    setup_sig(SIGINT,  &n_hand) ||
	    setup_sig(SIGQUIT, &n_hand) ||
	    setup_sig(SIGXCPU, &n_hand))
		goto out;

	n_hand.sa_handler = SIG_IGN;
	if ((sigaction(SIGPIPE, &n_hand, NULL) < 0) ||
	    (sigaction(SIGXFSZ, &n_hand, NULL) < 0))
		goto out;
	return(0);

    out:
	syswarn(1, errno, "Unable to set up signal handler");
	return(-1);
}
Esempio n. 22
0
bool w_start_listener(const char *path)
{
  pthread_mutexattr_t mattr;
#ifndef _WIN32
  struct sigaction sa;
  sigset_t sigset;
#endif
  void *ignored;
#ifdef HAVE_LIBGIMLI_H
  volatile struct gimli_heartbeat *hb = NULL;
#endif
  struct timeval tv;

  listener_thread = pthread_self();

  pthread_mutexattr_init(&mattr);
  pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(&w_client_lock, &mattr);
  pthread_mutexattr_destroy(&mattr);

#ifdef HAVE_LIBGIMLI_H
  hb = gimli_heartbeat_attach();
#endif

#if defined(HAVE_KQUEUE) || defined(HAVE_FSEVENTS)
  {
    struct rlimit limit;
# ifndef __OpenBSD__
    int mib[2] = { CTL_KERN,
#  ifdef KERN_MAXFILESPERPROC
      KERN_MAXFILESPERPROC
#  else
      KERN_MAXFILES
#  endif
    };
# endif
    int maxperproc;

    getrlimit(RLIMIT_NOFILE, &limit);

# ifndef __OpenBSD__
    {
      size_t len;

      len = sizeof(maxperproc);
      sysctl(mib, 2, &maxperproc, &len, NULL, 0);
      w_log(W_LOG_ERR, "file limit is %" PRIu64
          " kern.maxfilesperproc=%i\n",
          limit.rlim_cur, maxperproc);
    }
# else
    maxperproc = limit.rlim_max;
    w_log(W_LOG_ERR, "openfiles-cur is %" PRIu64
        " openfiles-max=%i\n",
        limit.rlim_cur, maxperproc);
# endif

    if (limit.rlim_cur != RLIM_INFINITY &&
        maxperproc > 0 &&
        limit.rlim_cur < (rlim_t)maxperproc) {
      limit.rlim_cur = maxperproc;

      if (setrlimit(RLIMIT_NOFILE, &limit)) {
        w_log(W_LOG_ERR,
          "failed to raise limit to %" PRIu64 " (%s).\n",
          limit.rlim_cur,
          strerror(errno));
      } else {
        w_log(W_LOG_ERR,
            "raised file limit to %" PRIu64 "\n",
            limit.rlim_cur);
      }
    }

    getrlimit(RLIMIT_NOFILE, &limit);
#ifndef HAVE_FSEVENTS
    if (limit.rlim_cur < 10240) {
      w_log(W_LOG_ERR,
          "Your file descriptor limit is very low (%" PRIu64 "), "
          "please consult the watchman docs on raising the limits\n",
          limit.rlim_cur);
    }
#endif
  }
#endif

  proc_pid = (int)getpid();
  if (gettimeofday(&tv, NULL) == -1) {
    w_log(W_LOG_ERR, "gettimeofday failed: %s\n", strerror(errno));
    return false;
  }
  proc_start_time = (uint64_t)tv.tv_sec;

#ifndef _WIN32
  signal(SIGPIPE, SIG_IGN);

  /* allow SIGUSR1 and SIGCHLD to wake up a blocked thread, without restarting
   * syscalls */
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = wakeme;
  sa.sa_flags = 0;
  sigaction(SIGUSR1, &sa, NULL);
  sigaction(SIGCHLD, &sa, NULL);

  // Block SIGCHLD everywhere
  sigemptyset(&sigset);
  sigaddset(&sigset, SIGCHLD);
  sigprocmask(SIG_BLOCK, &sigset, NULL);

  listener_fd = get_listener_socket(path);
  if (listener_fd == -1) {
    return false;
  }
  w_set_cloexec(listener_fd);
#endif

  if (pthread_create(&reaper_thread, NULL, child_reaper, NULL)) {
    w_log(W_LOG_FATAL, "pthread_create(reaper): %s\n",
        strerror(errno));
    return false;
  }

  if (!clients) {
    clients = w_ht_new(2, NULL);
  }

  w_state_load();

#ifdef HAVE_LIBGIMLI_H
  if (hb) {
    gimli_heartbeat_set(hb, GIMLI_HB_RUNNING);
  } else {
    w_setup_signal_handlers();
  }
#else
  w_setup_signal_handlers();
#endif
  w_set_nonblock(listener_fd);

  // Now run the dispatch
#ifndef _WIN32
  accept_loop();
#else
  named_pipe_accept_loop(path);
#endif

#ifndef _WIN32
  /* close out some resources to persuade valgrind to run clean */
  close(listener_fd);
  listener_fd = -1;
#endif

  // Wait for clients, waking any sleeping clients up in the process
  {
    int interval = 2000;
    int last_count = 0, n_clients = 0;

    do {
      w_ht_iter_t iter;

      pthread_mutex_lock(&w_client_lock);
      n_clients = w_ht_size(clients);

      if (w_ht_first(clients, &iter)) do {
        struct watchman_client *client = w_ht_val_ptr(iter.value);
        w_event_set(client->ping);
      } while (w_ht_next(clients, &iter));

      pthread_mutex_unlock(&w_client_lock);

      if (n_clients != last_count) {
        w_log(W_LOG_ERR, "waiting for %d clients to terminate\n", n_clients);
      }
      usleep(interval);
      interval = MIN(interval * 2, 1000000);
    } while (n_clients > 0);
  }

  w_root_free_watched_roots();

  pthread_join(reaper_thread, &ignored);
  cfg_shutdown();

  return true;
}
Esempio n. 23
0
FILE *
spopen (const char *cmdstring)
{
	char *env[2];
	char *cmd = NULL;
	char **argv = NULL;
	char *str, *tmp;
	int argc;

	int i = 0, pfd[2], pfderr[2];
	pid_t pid;

#ifdef 	RLIMIT_CORE
	/* do not leave core files */
	struct rlimit limit;
	getrlimit (RLIMIT_CORE, &limit);
	limit.rlim_cur = 0;
	setrlimit (RLIMIT_CORE, &limit);
#endif

	env[0] = strdup("LC_ALL=C");
	env[1] = '\0';

	/* if no command was passed, return with no error */
	if (cmdstring == NULL)
		return (NULL);

	/* make copy of command string so strtok() doesn't silently modify it */
	/* (the calling program may want to access it later) */
	cmd = malloc (strlen (cmdstring) + 1);
	if (cmd == NULL)
		return NULL;
	strcpy (cmd, cmdstring);

	/* This is not a shell, so we don't handle "???" */
	if (strstr (cmdstring, "\""))
		return NULL;

	/* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
	if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''"))
		return NULL;

	/* there cannot be more args than characters */
	argc = strlen (cmdstring) + 1;	/* add 1 for NULL termination */
	argv = malloc (sizeof(char*)*argc);

	if (argv == NULL) {
		printf ("%s\n", _("Could not malloc argv array in popen()"));
		return NULL;
	}

	/* loop to get arguments to command */
	while (cmd) {
		str = cmd;
		str += strspn (str, " \t\r\n");	/* trim any leading whitespace */

		if (i >= argc - 2) {
			printf ("%s\n",_("CRITICAL - You need more args!!!"));
			return (NULL);
		}

		if (strstr (str, "'") == str) {	/* handle SIMPLE quoted strings */
			str++;
			if (!strstr (str, "'"))
				return NULL;						/* balanced? */
			cmd = 1 + strstr (str, "'");
			str[strcspn (str, "'")] = 0;
		}
		else if (strcspn(str,"'") < strcspn (str, " \t\r\n")) {
										/* handle --option='foo bar' strings */
			tmp = str + strcspn(str, "'") + 1;
			if (!strstr (tmp, "'"))
				return NULL;						/* balanced? */
			tmp += strcspn(tmp,"'") + 1;
			*tmp = 0;
			cmd = tmp + 1;
		} else {
			if (strpbrk (str, " \t\r\n")) {
				cmd = 1 + strpbrk (str, " \t\r\n");
				str[strcspn (str, " \t\r\n")] = 0;
			}
			else {
				cmd = NULL;
			}
		}

		if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n"))
			cmd = NULL;

		argv[i++] = str;

	}
	argv[i] = NULL;

	if (childpid == NULL) {				/* first time through */
		maxfd = open_max ();				/* allocate zeroed out array for child pids */
		if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL)
			return (NULL);
	}

	if (child_stderr_array == NULL) {	/* first time through */
		maxfd = open_max ();				/* allocate zeroed out array for child pids */
		if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL)
			return (NULL);
	}

	if (pipe (pfd) < 0)
		return (NULL);							/* errno set by pipe() */

	if (pipe (pfderr) < 0)
		return (NULL);							/* errno set by pipe() */

#ifdef REDHAT_SPOPEN_ERROR
	if (signal (SIGCHLD, popen_sigchld_handler) == SIG_ERR) {
		usage4 (_("Cannot catch SIGCHLD"));
	}
#endif

	if ((pid = fork ()) < 0)
		return (NULL);							/* errno set by fork() */
	else if (pid == 0) {					/* child */
		close (pfd[0]);
		if (pfd[1] != STDOUT_FILENO) {
			dup2 (pfd[1], STDOUT_FILENO);
			close (pfd[1]);
		}
		close (pfderr[0]);
		if (pfderr[1] != STDERR_FILENO) {
			dup2 (pfderr[1], STDERR_FILENO);
			close (pfderr[1]);
		}
		/* close all descriptors in childpid[] */
		for (i = 0; i < maxfd; i++)
			if (childpid[i] > 0)
				close (i);

		execve (argv[0], argv, env);
		_exit (0);
	}

	close (pfd[1]);								/* parent */
	if ((child_process = fdopen (pfd[0], "r")) == NULL)
		return (NULL);
	close (pfderr[1]);

	childpid[fileno (child_process)] = pid;	/* remember child pid for this fd */
	child_stderr_array[fileno (child_process)] = pfderr[0];	/* remember STDERR */
	return (child_process);
}
Esempio n. 24
0
static int
glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
{
        cmd_args_t    *cmd_args = NULL;
        struct rlimit  lim = {0, };
        call_pool_t   *pool = NULL;

        xlator_mem_acct_init (THIS, cli_mt_end);

        ctx->process_uuid = generate_glusterfs_ctx_id ();
        if (!ctx->process_uuid)
                return -1;

        ctx->page_size  = 128 * GF_UNIT_KB;

        ctx->iobuf_pool = iobuf_pool_new ();
        if (!ctx->iobuf_pool)
                return -1;

        ctx->event_pool = event_pool_new (DEFAULT_EVENT_POOL_SIZE);
        if (!ctx->event_pool)
                return -1;

        pool = GF_CALLOC (1, sizeof (call_pool_t),
                          cli_mt_call_pool_t);
        if (!pool)
                return -1;

        /* frame_mem_pool size 112 * 64 */
        pool->frame_mem_pool = mem_pool_new (call_frame_t, 32);
        if (!pool->frame_mem_pool)
                return -1;

        /* stack_mem_pool size 256 * 128 */
        pool->stack_mem_pool = mem_pool_new (call_stack_t, 16);

        if (!pool->stack_mem_pool)
                return -1;

        ctx->stub_mem_pool = mem_pool_new (call_stub_t, 16);
        if (!ctx->stub_mem_pool)
                return -1;

        ctx->dict_pool = mem_pool_new (dict_t, 32);
        if (!ctx->dict_pool)
                return -1;

        ctx->dict_pair_pool = mem_pool_new (data_pair_t, 512);
        if (!ctx->dict_pair_pool)
                return -1;

        ctx->dict_data_pool = mem_pool_new (data_t, 512);
        if (!ctx->dict_data_pool)
                return -1;

        INIT_LIST_HEAD (&pool->all_frames);
        LOCK_INIT (&pool->lock);
        ctx->pool = pool;

        pthread_mutex_init (&(ctx->lock), NULL);

        cmd_args = &ctx->cmd_args;

        INIT_LIST_HEAD (&cmd_args->xlator_options);

        lim.rlim_cur = RLIM_INFINITY;
        lim.rlim_max = RLIM_INFINITY;
        setrlimit (RLIMIT_CORE, &lim);

        return 0;
}
Esempio n. 25
0
static int
__sandbox_task_execute(task_t * ptask)
{
    FUNC_BEGIN("sandbox_task_execute(%p)", ptask);

    assert(ptask);

    /* Run the prisoner program in a separate process group */
    if (setsid() < 0)
    {
        WARNING("failed setting session id");
        return EXIT_FAILURE;
    }

    /* Close fd's not used by the prisoner program */
    int fd;
    for (fd = 0; fd < FILENO_MAX; fd++)
    {
        if ((fd == ptask->ifd) || (fd == ptask->ofd) || (fd == ptask->efd))
        {
            continue;
        }
        close(fd);
    }

    /* Redirect I/O channel */

    if (dup2(ptask->efd, STDERR_FILENO) < 0)
    {
        WARNING("failed redirecting error channel");
        return EXIT_FAILURE;
    }
    DBG("dup2: %d->%d", ptask->efd, STDERR_FILENO);

    if (dup2(ptask->ofd, STDOUT_FILENO) < 0)
    {
        WARNING("failed redirecting output channel(s)");
        return EXIT_FAILURE;
    }
    DBG("dup2: %d->%d", ptask->ofd, STDOUT_FILENO);

    if (dup2(ptask->ifd, STDIN_FILENO) < 0)
    {
        WARNING("failed redirecting input channel(s)");
        return EXIT_FAILURE;
    }
    DBG("dup2: %d->%d", ptask->ifd, STDIN_FILENO);

    /* Apply security restrictions */

    if (strcmp(ptask->jail, "/") != 0)
    {
        if (chdir(ptask->jail) < 0)
        {
            WARNING("failed switching to jail directory");
            return EXIT_FAILURE;
        }
        if (chroot(ptask->jail) < 0)
        {
            WARNING("failed chroot to jail directory");
            return EXIT_FAILURE;
        }
        DBG("jail: \"%s\"", ptask->jail);
    }

    /* Change identity before executing the targeted program */

    if (setgid(ptask->gid) < 0)
    {
        WARNING("changing group identity");
        return EXIT_FAILURE;
    }
    DBG("setgid: %lu", (unsigned long)ptask->gid);

    if (setuid(ptask->uid) < 0)
    {
        WARNING("changing owner identity");
        return EXIT_FAILURE;
    }
    DBG("setuid: %lu", (unsigned long)ptask->uid);

    /* Prepare argument arrray to be passed to execve() */
    char * argv [ARG_MAX] = {NULL};
    int argc = 0;
    while ((argc + 1 < ARG_MAX) && (ptask->comm.args[argc] >= 0))
    {
        argv[argc] = ptask->comm.buff + ptask->comm.args[argc];
        argc++;
    }
    if (strcmp(ptask->jail, "/") != 0)
    {
        argv[0] += strlen(ptask->jail);
    }
    argv[argc] = NULL;

    #ifndef NDEBUG
    argc = 0;
    while (argv[argc] != NULL)
    {
        DBG("argv[%d]: \"%s\"", argc, argv[argc]);
        argc++;
    }
    #endif /* !defined NDEBUG */

    /* Most kinds of resource restrictions are applied through the *setrlimit*
     * system call, with the exceptions of virtual memory limit and the cpu
     * usage limit.
     * Because we might have already changed identity by this time, the hard
     * limits should remain as they were. Thus we must invoke a *getrlimit*
     * ahead of time to load original hard limit value.
     * Also note that, cpu usage limit should be set LAST to reduce overhead. */
    struct rlimit rlimval;

    /* Do NOT produce core dump files at all. */
    if (getrlimit(RLIMIT_CORE, &rlimval) < 0)
    {
        return EXIT_FAILURE;
    }
    rlimval.rlim_cur = 0;
    if (setrlimit(RLIMIT_CORE, &rlimval) < 0)
    {
        return EXIT_FAILURE;
    }
    DBG("RLIMIT_CORE: %ld", rlimval.rlim_cur);

    /* Disk quota */
    if (getrlimit(RLIMIT_FSIZE, &rlimval) < 0)
    {
        return EXIT_FAILURE;
    }
    rlimval.rlim_cur = ptask->quota[S_QUOTA_DISK];
    if (setrlimit(RLIMIT_FSIZE, &rlimval) < 0)
    {
        return EXIT_FAILURE;
    }
    DBG("RLIMIT_FSIZE: %ld", rlimval.rlim_cur);

#ifdef DELETED
    /* Memory quota */
    if (getrlimit(RLIMIT_AS, &rlimval) < 0)
    {
        return EXIT_FAILURE;
    }
    rlimval.rlim_cur = ptask->quota[S_QUOTA_MEMORY];
    if (setrlimit(RLIMIT_AS, &rlimval) < 0)
    {
        return EXIT_FAILURE;
    }
    DBG("RLIMIT_AS: %ld", rlimval.rlim_cur);
#endif /* DELETED */

    /* Time resource limits, these should be set last to reduce overhead. Thus,
     * no debug information is produced on success. */
    struct itimerval timerval;

    /* Wallclock quota */
    timerval.it_interval.tv_sec = 0;
    timerval.it_interval.tv_usec = 0;
    timerval.it_value.tv_sec = ptask->quota[S_QUOTA_WALLCLOCK] / 1000;
    timerval.it_value.tv_usec = (ptask->quota[S_QUOTA_WALLCLOCK] % 1000) * 1000;
    if (setitimer(ITIMER_REAL, &timerval, NULL) < 0)
    {
        WARNING("setting ITIMER_REAL");
        return EXIT_FAILURE;
    }

    /* CPU quota */
    timerval.it_interval.tv_sec = 0;
    timerval.it_interval.tv_usec = 0;
    timerval.it_value.tv_sec = ptask->quota[S_QUOTA_CPU] / 1000;
    timerval.it_value.tv_usec = (ptask->quota[S_QUOTA_CPU] % 1000) * 1000;
    if (setitimer(ITIMER_PROF, &timerval, NULL) < 0)
    {
        WARNING("setting ITIMER_PROF");
        return EXIT_FAILURE;
    }

    /* Enter tracing mode */
    if (!trace_self())
    {
        WARNING("trace_self");
        return EXIT_FAILURE;
    }

    /* Execute the targeted program */
    if (execve(argv[0], argv, NULL) < 0)
    {
        WARNING("execve failed unexpectedly");
        return EXIT_FAILURE;
    }

    /* According to Linux manual, the execve() function will NEVER return on
     * success, thus we should not be able to reach to this line of code! */
    return EXIT_FAILURE;
}
Esempio n. 26
0
liProc* li_proc_new(liServer *srv, gchar **args, gchar **env, uid_t uid, gid_t gid, gchar *username, gint64 rlim_core, gint64 rlim_nofile, liProcSetupCB cb, gpointer ctx) {
    liProc *proc;
    pid_t pid;

    proc = g_slice_new0(liProc);
    proc->srv = srv;
    proc->child_pid = -1;
    proc->epipe = li_error_pipe_new(srv, proc_epipe_cb, proc);
    proc->appname = g_strdup(li_remove_path(args[0]));

    switch (pid = fork()) {
    case 0:
        li_error_pipe_use(proc->epipe, STDERR_FILENO);

        setsid();

#ifdef HAVE_GETRLIMIT
        {
            struct rlimit rlim;
            if (rlim_core >= 0) {
                rlim.rlim_cur = rlim.rlim_max = ((guint64) rlim_core >= RLIM_INFINITY) ? RLIM_INFINITY : (guint64) rlim_core;
                if (0 != setrlimit(RLIMIT_CORE, &rlim)) {
                    ERROR(srv, "couldn't set 'max core file size': %s", g_strerror(errno));
                }
            }
            if (rlim_nofile >= 0) {
                rlim.rlim_cur = rlim.rlim_max = ((guint64) rlim_nofile >= RLIM_INFINITY) ? RLIM_INFINITY : (guint64) rlim_nofile;
                if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
                    ERROR(srv, "couldn't set 'max filedescriptors': %s", g_strerror(errno));
                }
            }
        }
#endif

        if (gid != (gid_t) -1) {
            setgid(gid);
            setgroups(0, NULL);
            if (username) initgroups(username, gid);
        }

        if (cb) cb(ctx);

        if (uid != (uid_t) -1) {
            setuid(uid);
        }

        if (NULL == env)
            execv(args[0], args);
        else
            execve(args[0], args, env);

        g_printerr("exec('%s') failed: %s\n", args[0], g_strerror(errno));
        abort();

        break;
    case -1:
        ERROR(srv, "fork failed: %s", g_strerror(errno));
        li_proc_free(proc);
        return NULL;
    default:
        proc->child_pid = pid;
        li_error_pipe_activate(proc->epipe);
        break;
    }

    return proc;
}
Esempio n. 27
0
bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
{
    /*
     * Kill a process which corrupts its own heap (with ABRT)
     */
    if (setenv("MALLOC_CHECK_", "3", 1) == -1) {
        LOGMSG_P(l_ERROR, "setenv(MALLOC_CHECK_=3) failed");
        return false;
    }

    /*
     * Tell asan to ignore SEGVs
     */
    if (setenv
        ("ASAN_OPTIONS",
         "allow_user_segv_handler=1:handle_segv=0:abort_on_error=1:allocator_may_return_null=1",
         1) == -1) {
        LOGMSG_P(l_ERROR, "setenv(ASAN_OPTIONS) failed");
        return false;
    }

    /*
     * Kill the children when fuzzer dies (e.g. due to Ctrl+C)
     */
    if (prctl(PR_SET_PDEATHSIG, (long)SIGKILL, 0L, 0L, 0L) == -1) {
        LOGMSG_P(l_ERROR, "prctl(PR_SET_PDEATHSIG, SIGKILL) failed");
        return false;
    }

    /*
     * Disable ASLR
     */
    if (personality(ADDR_NO_RANDOMIZE) == -1) {
        LOGMSG_P(l_ERROR, "personality(ADDR_NO_RANDOMIZE) failed");
        return false;
    }
#define ARGS_MAX 512
    char *args[ARGS_MAX + 2];

    int x;

    for (x = 0; x < ARGS_MAX && hfuzz->cmdline[x]; x++) {
        if (!hfuzz->fuzzStdin && strcmp(hfuzz->cmdline[x], _HF_FILE_PLACEHOLDER) == 0) {
            args[x] = fileName;
        } else {
            args[x] = hfuzz->cmdline[x];
        }
    }

    args[x++] = NULL;

    LOGMSG(l_DEBUG, "Launching '%s' on file '%s'", args[0], fileName);

    /*
     * Set timeout (prof), real timeout (2*prof), and rlimit_cpu (2*prof)
     */
    if (hfuzz->tmOut) {
        /* 
         * Set the CPU rlimit to twice the value of the time-out
         */
        struct rlimit rl = {
            .rlim_cur = hfuzz->tmOut * 2,
            .rlim_max = hfuzz->tmOut * 2,
        };
        if (setrlimit(RLIMIT_CPU, &rl) == -1) {
            LOGMSG_P(l_ERROR, "Couldn't enforce the RLIMIT_CPU resource limit");
            return false;
        }
    }

    /*
     * The address space limit. If big enough - roughly the size of RAM used
     */
    if (hfuzz->asLimit) {
        struct rlimit rl = {
            .rlim_cur = hfuzz->asLimit * 1024UL * 1024UL,
            .rlim_max = hfuzz->asLimit * 1024UL * 1024UL,
        };
        if (setrlimit(RLIMIT_AS, &rl) == -1) {
            LOGMSG_P(l_DEBUG, "Couldn't encforce the RLIMIT_AS resource limit, ignoring");
        }
    }

    for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs) && hfuzz->envs[i]; i++) {
        putenv(hfuzz->envs[i]);
    }

    if (hfuzz->nullifyStdio) {
        util_nullifyStdio();
    }

    if (hfuzz->fuzzStdin) {
        /*
         * Uglyyyyyy ;)
         */
        if (!util_redirectStdin(fileName)) {
            return false;
        }
    }
    /*
     * Wait for the ptrace to attach
     */
    syscall(__NR_tkill, syscall(__NR_gettid), SIGSTOP);
    execvp(args[0], args);

    util_recoverStdio();
    LOGMSG(l_FATAL, "Failed to create new '%s' process", args[0]);
    return false;
}

static void arch_sigFunc(int signo, siginfo_t * si, void *dummy)
{
    if (signo != SIGALRM) {
        LOGMSG(l_ERROR, "Signal != SIGALRM (%d)", signo);
    }
    return;
    if (si == NULL) {
        return;
    }
    if (dummy == NULL) {
        return;
    }
}

static void arch_removeTimer(timer_t * timerid)
{
    timer_delete(*timerid);
}

static bool arch_setTimer(timer_t * timerid)
{
    struct sigevent sevp = {
        .sigev_value.sival_ptr = timerid,
        .sigev_signo = SIGALRM,
        .sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL,
        ._sigev_un._tid = syscall(__NR_gettid),
    };
    if (timer_create(CLOCK_REALTIME, &sevp, timerid) == -1) {
        LOGMSG_P(l_ERROR, "timer_create(CLOCK_REALTIME) failed");
        return false;
    }
    /* 
     * Kick in every 200ms, starting with the next second
     */
    const struct itimerspec ts = {
        .it_value = {.tv_sec = 1,.tv_nsec = 0},
        .it_interval = {.tv_sec = 0,.tv_nsec = 200000000,},
    };
    if (timer_settime(*timerid, 0, &ts, NULL) == -1) {
        LOGMSG_P(l_ERROR, "timer_settime() failed");
        timer_delete(*timerid);
        return false;
    }
    sigset_t smask;
    sigemptyset(&smask);
    struct sigaction sa = {
        .sa_handler = NULL,
        .sa_sigaction = arch_sigFunc,
        .sa_mask = smask,
        .sa_flags = SA_SIGINFO,
        .sa_restorer = NULL,
    };
    if (sigaction(SIGALRM, &sa, NULL) == -1) {
        LOGMSG_P(l_ERROR, "sigaciton(SIGALRM) failed");
        return false;
    }

    return true;
}

static void arch_checkTimeLimit(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
{
    int64_t curMillis = util_timeNowMillis();
    int64_t diffMillis = curMillis - fuzzer->timeStartedMillis;
    if (diffMillis > (hfuzz->tmOut * 1000)) {
        LOGMSG(l_WARN, "PID %d took too much time (limit %ld s). Sending SIGKILL",
               fuzzer->pid, hfuzz->tmOut);
        kill(fuzzer->pid, SIGKILL);
    }
}
Esempio n. 28
0
  int main(int argc, char *argv[])
  {
    int i, j;
    struct rlimit rlb;
    char *arg;
    pthread_t tid;
    pthread_attr_t pab;
    
    int yu_tmp_len;
    int depth = 0;
    argv0 = argv[0];

    //setlocale(LC_CTYPE, "");

    getrlimit(RLIMIT_NOFILE, &rlb);
    rlb.rlim_cur = rlb.rlim_max;
    setrlimit(RLIMIT_NOFILE, &rlb);

    signal(SIGPIPE, SIG_IGN);

    nworkers = 2;

    pthread_mutex_init(&print_lock, NULL);
    pthread_mutex_init(&aworker_lock, NULL);
    pthread_mutex_init(&matches_lock, NULL);
    
    pthread_cond_init(&aworker_cv, NULL);

    for (i = 1; i < argc && argv[i][0] == '-'; i++)
      for (j = 1; j > 0 && argv[i][j]; ++j)
        switch (argv[i][j])
      {
        case '-':  ++i; goto EndOptions;

        case 'V': print_version(stdout);  break;
        case 'd':   ++debug;    break;
        case 'i':   ignore_case = 1;    break;

        case 'v':
        ++verbose;
        break;

        case 'h':
        usage(stdout);
        exit(0);

        case 'l':
        ++line_f;
        break;

        case 'L':
        if (argv[i][2])  arg = argv[i]+2;
        else  arg = argv[++i];

        if (!arg || sscanf(arg, "%u", &maxlen) != 1){
          fprintf(stderr, "%s: Invalid length specification: %s\n", argv[0], arg ? arg : "<null>");
          exit(1);
        }
        j = -2;
        break;

        case 'n':
        if (argv[i][2])  arg = argv[i]+2;  else   arg = argv[++i];    
        if (!arg || sscanf(arg, "%u", &nworkers) != 1){
          fprintf(stderr,"%s: Invalid workers specification: %s\n",  argv[0], arg ? arg : "<null>");
          exit(1);
        }
        j = -2;
        break;

        default:
        fprintf(stderr, "%s: unknown command line switch: -%c\n",
          argv[0], argv[i][j]);
        exit(1);
      }

      EndOptions:

      yu_tmp_len = strlen(argv[i]) + 1;
      rstr = (unsigned char*) malloc( yu_tmp_len * sizeof(unsigned char));


    strcpy(rstr, argv[i]); //, yu_tmp_len);    
i++;

rlen = deslash(rstr);

if (bm_init(&bmb, rstr, rlen, ignore_case) < 0)
{
  fprintf(stderr, "%s: Failed search string setup: %s\n",
    argv[0], rstr);
  exit(1);
}

max_depth = rlb.rlim_max - nworkers - 16;

if (debug)
  fprintf(stderr, "max_depth = %d, nworkers = %d\n", max_depth,
    nworkers);

pqueue_init(&pqb, nworkers + 8);

pthread_attr_init(&pab);
pthread_attr_setscope(&pab, PTHREAD_SCOPE_SYSTEM);

aworkers = nworkers;

for (j = 0; j < nworkers; ++j)
  if (pthread_create(&tid, &pab, worker, NULL) != 0)
  {
    fprintf(stderr, "%s: pthread_create: failed to create worker thread\n",
      argv[0]);
    exit(1);
  }

    //while (i < argc && do_ftw(argv[i++]) == 0)
  //;
  for (; i < argc; i++) {
    scan_root(argv[i], argv[i], &depth, max_depth);
  }
  pqueue_close(&pqb);

  if (debug)
    fprintf(stderr, "Waiting for workers to finish...\n");

  pthread_mutex_lock(&aworker_lock);
  while (aworkers > 0)
    pthread_cond_wait(&aworker_cv, &aworker_lock);
  pthread_mutex_unlock(&aworker_lock);

  if (debug)
    fprintf(stderr, "n_files = %d, n_matches = %d, n_workers = %d, n_Mbytes = %d\n",
      n_files, n_matches, nworkers,
      (int) (n_bytes / 1000000));

    //pthread_exit(0);
  return n_matches;
}
Esempio n. 29
0
int
main(int argc, char **argv)
{
    int rc;
    int flag;
    int argerr = 0;

    int option_index = 0;
    gboolean shutdown = FALSE;

    uid_t pcmk_uid = 0;
    gid_t pcmk_gid = 0;
    struct rlimit cores;
    crm_ipc_t *old_instance = NULL;
    qb_ipcs_service_t *ipcs = NULL;
    const char *facility = daemon_option("logfacility");
    static crm_cluster_t cluster;

    setenv("LC_ALL", "C", 1);
    setenv("HA_LOGD", "no", 1);

    set_daemon_option("mcp", "true");
    set_daemon_option("use_logd", "off");

    crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
    crm_set_options(NULL, "mode [options]", long_options, "Start/Stop Pacemaker\n");

    /* Restore the original facility so that mcp_read_config() does the right thing */
    set_daemon_option("logfacility", facility);

    while (1) {
        flag = crm_get_option(argc, argv, &option_index);
        if (flag == -1)
            break;

        switch (flag) {
            case 'V':
                crm_bump_log_level(argc, argv);
                break;
            case 'f':
                /* Legacy */
                break;
            case 'p':
                pid_file = optarg;
                break;
            case '$':
            case '?':
                crm_help(flag, EX_OK);
                break;
            case 'S':
                shutdown = TRUE;
                break;
            case 'F':
                printf("Pacemaker %s (Build: %s)\n Supporting v%s: %s\n", VERSION, BUILD_VERSION,
                       CRM_FEATURE_SET, CRM_FEATURES);
                crm_exit(pcmk_ok);
            default:
                printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag);
                ++argerr;
                break;
        }
    }

    if (optind < argc) {
        printf("non-option ARGV-elements: ");
        while (optind < argc)
            printf("%s ", argv[optind++]);
        printf("\n");
    }
    if (argerr) {
        crm_help('?', EX_USAGE);
    }

    crm_debug("Checking for old instances of %s", CRM_SYSTEM_MCP);
    old_instance = crm_ipc_new(CRM_SYSTEM_MCP, 0);
    crm_ipc_connect(old_instance);

    if (shutdown) {
        crm_debug("Terminating previous instance");
        while (crm_ipc_connected(old_instance)) {
            xmlNode *cmd =
                create_request(CRM_OP_QUIT, NULL, NULL, CRM_SYSTEM_MCP, CRM_SYSTEM_MCP, NULL);

            crm_debug(".");
            crm_ipc_send(old_instance, cmd, 0, 0, NULL);
            free_xml(cmd);

            sleep(2);
        }
        crm_ipc_close(old_instance);
        crm_ipc_destroy(old_instance);
        crm_exit(pcmk_ok);

    } else if (crm_ipc_connected(old_instance)) {
        crm_ipc_close(old_instance);
        crm_ipc_destroy(old_instance);
        crm_err("Pacemaker is already active, aborting startup");
        crm_exit(DAEMON_RESPAWN_STOP);
    }

    crm_ipc_close(old_instance);
    crm_ipc_destroy(old_instance);

    if (mcp_read_config() == FALSE) {
        crm_notice("Could not obtain corosync config data, exiting");
        crm_exit(ENODATA);
    }

    crm_notice("Starting Pacemaker %s (Build: %s): %s", VERSION, BUILD_VERSION, CRM_FEATURES);
    mainloop = g_main_new(FALSE);

    rc = getrlimit(RLIMIT_CORE, &cores);
    if (rc < 0) {
        crm_perror(LOG_ERR, "Cannot determine current maximum core size.");
    } else {
        if (cores.rlim_max == 0 && geteuid() == 0) {
            cores.rlim_max = RLIM_INFINITY;
        } else {
            crm_info("Maximum core file size is: %lu", (unsigned long)cores.rlim_max);
        }
        cores.rlim_cur = cores.rlim_max;

        rc = setrlimit(RLIMIT_CORE, &cores);
        if (rc < 0) {
            crm_perror(LOG_ERR,
                       "Core file generation will remain disabled."
                       " Core files are an important diagnositic tool,"
                       " please consider enabling them by default.");
        }
#if 0
        /* system() is not thread-safe, can't call from here
         * Actually, its a pretty hacky way to try and achieve this anyway
         */
        if (system("echo 1 > /proc/sys/kernel/core_uses_pid") != 0) {
            crm_perror(LOG_ERR, "Could not enable /proc/sys/kernel/core_uses_pid");
        }
#endif
    }

    if (crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) < 0) {
        crm_err("Cluster user %s does not exist, aborting Pacemaker startup", CRM_DAEMON_USER);
        crm_exit(ENOKEY);
    }

    mkdir(CRM_STATE_DIR, 0750);
    mcp_chown(CRM_STATE_DIR, pcmk_uid, pcmk_gid);

    /* Used to store core files in */
    crm_build_path(CRM_CORE_DIR, 0775);
    mcp_chown(CRM_CORE_DIR, pcmk_uid, pcmk_gid);

    /* Used to store blackbox dumps in */
    crm_build_path(CRM_BLACKBOX_DIR, 0755);
    mcp_chown(CRM_BLACKBOX_DIR, pcmk_uid, pcmk_gid);

    /* Used to store policy engine inputs in */
    crm_build_path(PE_STATE_DIR, 0755);
    mcp_chown(PE_STATE_DIR, pcmk_uid, pcmk_gid);

    /* Used to store the cluster configuration */
    crm_build_path(CRM_CONFIG_DIR, 0755);
    mcp_chown(CRM_CONFIG_DIR, pcmk_uid, pcmk_gid);

    /* Resource agent paths are constructed by the lrmd */

    ipcs = mainloop_add_ipc_server(CRM_SYSTEM_MCP, QB_IPC_NATIVE, &mcp_ipc_callbacks);
    if (ipcs == NULL) {
        crm_err("Couldn't start IPC server");
        crm_exit(EIO);
    }

    /* Allows us to block shutdown */
    if (cluster_connect_cfg(&local_nodeid) == FALSE) {
        crm_err("Couldn't connect to Corosync's CFG service");
        crm_exit(ENOPROTOOPT);
    }

    cluster.destroy = mcp_cpg_destroy;
    cluster.cpg.cpg_deliver_fn = mcp_cpg_deliver;
    cluster.cpg.cpg_confchg_fn = mcp_cpg_membership;

    if(cluster_connect_cpg(&cluster) == FALSE) {
        crm_err("Couldn't connect to Corosync's CPG service");
        crm_exit(ENOPROTOOPT);
    }

    if (is_corosync_cluster()) {
        /* Keep the membership list up-to-date for crm_node to query */
        rc = cluster_connect_quorum(mcp_quorum_callback, mcp_quorum_destroy);
    }

    local_name = get_local_node_name();
    update_node_processes(local_nodeid, local_name, get_process_list());

    mainloop_add_signal(SIGTERM, pcmk_shutdown);
    mainloop_add_signal(SIGINT, pcmk_shutdown);

    find_and_track_existing_processes();
    init_children_processes();

    crm_info("Starting mainloop");

    g_main_run(mainloop);

    if (ipcs) {
        crm_trace("Closing IPC server");
        mainloop_del_ipc_server(ipcs);
        ipcs = NULL;
    }

    g_main_destroy(mainloop);

    cluster_disconnect_cpg(&cluster);
    cluster_disconnect_cfg();

    crm_info("Exiting %s", crm_system_name);

    crm_exit(pcmk_ok);
}
Esempio n. 30
0
/*
 * Main program.  Initialize us, disconnect us from the tty if necessary,
 * and loop waiting for I/O and/or timer expiries.
 */
int
ntpdmain(
	int argc,
	char *argv[]
	)
{
	l_fp now;
	struct recvbuf *rbuf;
#ifdef _AIX			/* HMS: ifdef SIGDANGER? */
	struct sigaction sa;
#endif

	progname = argv[0];
	initializing = 1;		/* mark that we are initializing */
	process_commandline_opts(&argc, &argv);
	init_logging(progname, 1);	/* Open the log file */

#ifdef HAVE_UMASK
	{
		mode_t uv;

		uv = umask(0);
		if(uv)
			(void) umask(uv);
		else
			(void) umask(022);
	}
#endif

#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
	{
		uid_t uid;

		uid = getuid();
		if (uid && !HAVE_OPT( SAVECONFIGQUIT )) {
			msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
			printf("must be run as root, not uid %ld\n", (long)uid);
			exit(1);
		}
	}
#endif

	/* getstartup(argc, argv); / * startup configuration, may set debug */

#ifdef DEBUG
	debug = DESC(DEBUG_LEVEL).optOccCt;
	DPRINTF(1, ("%s\n", Version));
#endif

	/* honor -l/--logfile option to log to a file */
	setup_logfile();

/*
 * Enable the Multi-Media Timer for Windows?
 */
#ifdef SYS_WINNT
	if (HAVE_OPT( MODIFYMMTIMER ))
		set_mm_timer(MM_TIMER_HIRES);
#endif

	if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT )
#ifdef DEBUG
	    || debug
#endif
	    || HAVE_OPT( SAVECONFIGQUIT ))
		nofork = 1;

	if (HAVE_OPT( NOVIRTUALIPS ))
		listen_to_virtual_ips = 0;

	/*
	 * --interface, listen on specified interfaces
	 */
	if (HAVE_OPT( INTERFACE )) {
		int		ifacect = STACKCT_OPT( INTERFACE );
		const char**	ifaces  = STACKLST_OPT( INTERFACE );
		sockaddr_u	addr;

		while (ifacect-- > 0) {
			add_nic_rule(
				is_ip_address(*ifaces, &addr)
					? MATCH_IFADDR
					: MATCH_IFNAME,
				*ifaces, -1, ACTION_LISTEN);
			ifaces++;
		}
	}

	if (HAVE_OPT( NICE ))
		priority_done = 0;

#if defined(HAVE_SCHED_SETSCHEDULER)
	if (HAVE_OPT( PRIORITY )) {
		config_priority = OPT_VALUE_PRIORITY;
		config_priority_override = 1;
		priority_done = 0;
	}
#endif

#ifdef SYS_WINNT
	/*
	 * Start interpolation thread, must occur before first
	 * get_systime()
	 */
	init_winnt_time();
#endif
	/*
	 * Initialize random generator and public key pair
	 */
	get_systime(&now);

	ntp_srandom((int)(now.l_i * now.l_uf));

#if !defined(VMS)
# ifndef NODETACH
	/*
	 * Detach us from the terminal.  May need an #ifndef GIZMO.
	 */
	if (!nofork) {

		/*
		 * Install trap handlers to log errors and assertion
		 * failures.  Default handlers print to stderr which 
		 * doesn't work if detached.
		 */
		isc_assertion_setcallback(assertion_failed);
		isc_error_setfatal(library_fatal_error);
		isc_error_setunexpected(library_unexpected_error);

#  ifndef SYS_WINNT
#   ifdef HAVE_DAEMON
		daemon(0, 0);
#   else /* not HAVE_DAEMON */
		if (fork())	/* HMS: What about a -1? */
			exit(0);

		{
#if !defined(F_CLOSEM)
			u_long s;
			int max_fd;
#endif /* !FCLOSEM */
			if (syslog_file != NULL) {
				fclose(syslog_file);
				syslog_file = NULL;
			}
#if defined(F_CLOSEM)
			/*
			 * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
			 * by Eric Agar (saves us from doing 32767 system
			 * calls)
			 */
			if (fcntl(0, F_CLOSEM, 0) == -1)
			    msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
#else  /* not F_CLOSEM */

# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
			max_fd = sysconf(_SC_OPEN_MAX);
# else /* HAVE_SYSCONF && _SC_OPEN_MAX */
			max_fd = getdtablesize();
# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
			for (s = 0; s < max_fd; s++)
				(void) close((int)s);
#endif /* not F_CLOSEM */
			(void) open("/", 0);
			(void) dup2(0, 1);
			(void) dup2(0, 2);

			init_logging(progname, 0);
			/* we lost our logfile (if any) daemonizing */
			setup_logfile();

#ifdef SYS_DOMAINOS
			{
				uid_$t puid;
				status_$t st;

				proc2_$who_am_i(&puid);
				proc2_$make_server(&puid, &st);
			}
#endif /* SYS_DOMAINOS */
#if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
# ifdef HAVE_SETSID
			if (setsid() == (pid_t)-1)
				msyslog(LOG_ERR, "ntpd: setsid(): %m");
# else
			if (setpgid(0, 0) == -1)
				msyslog(LOG_ERR, "ntpd: setpgid(): %m");
# endif
#else /* HAVE_SETPGID || HAVE_SETSID */
			{
# if defined(TIOCNOTTY)
				int fid;

				fid = open("/dev/tty", 2);
				if (fid >= 0)
				{
					(void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
					(void) close(fid);
				}
# endif /* defined(TIOCNOTTY) */
# ifdef HAVE_SETPGRP_0
				(void) setpgrp();
# else /* HAVE_SETPGRP_0 */
				(void) setpgrp(0, getpid());
# endif /* HAVE_SETPGRP_0 */
			}
#endif /* HAVE_SETPGID || HAVE_SETSID */
#ifdef _AIX
			/* Don't get killed by low-on-memory signal. */
			sa.sa_handler = catch_danger;
			sigemptyset(&sa.sa_mask);
			sa.sa_flags = SA_RESTART;

			(void) sigaction(SIGDANGER, &sa, NULL);
#endif /* _AIX */
		}
#   endif /* not HAVE_DAEMON */
#  endif /* SYS_WINNT */
	}
# endif /* NODETACH */
#endif /* VMS */

#ifdef SCO5_CLOCK
	/*
	 * SCO OpenServer's system clock offers much more precise timekeeping
	 * on the base CPU than the other CPUs (for multiprocessor systems),
	 * so we must lock to the base CPU.
	 */
	{
	    int fd = open("/dev/at1", O_RDONLY);
	    if (fd >= 0) {
		int zero = 0;
		if (ioctl(fd, ACPU_LOCK, &zero) < 0)
		    msyslog(LOG_ERR, "cannot lock to base CPU: %m");
		close( fd );
	    } /* else ...
	       *   If we can't open the device, this probably just isn't
	       *   a multiprocessor system, so we're A-OK.
	       */
	}
#endif

#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
# ifdef HAVE_SETRLIMIT
	/*
	 * Set the stack limit to something smaller, so that we don't lock a lot
	 * of unused stack memory.
	 */
	{
	    struct rlimit rl;

	    /* HMS: must make the rlim_cur amount configurable */
	    if (getrlimit(RLIMIT_STACK, &rl) != -1
		&& (rl.rlim_cur = 50 * 4096) < rl.rlim_max)
	    {
		    if (setrlimit(RLIMIT_STACK, &rl) == -1)
		    {
			    msyslog(LOG_ERR,
				"Cannot adjust stack limit for mlockall: %m");
		    }
	    }
#  ifdef RLIMIT_MEMLOCK
	    /*
	     * The default RLIMIT_MEMLOCK is very low on Linux systems.
	     * Unless we increase this limit malloc calls are likely to
	     * fail if we drop root privlege.  To be useful the value
	     * has to be larger than the largest ntpd resident set size.
	     */
	    rl.rlim_cur = rl.rlim_max = 32*1024*1024;
	    if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) {
		msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
	    }
#  endif /* RLIMIT_MEMLOCK */
	}
# endif /* HAVE_SETRLIMIT */
	/*
	 * lock the process into memory
	 */
	if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
		msyslog(LOG_ERR, "mlockall(): %m");
#else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
# ifdef HAVE_PLOCK
#  ifdef PROCLOCK
#   ifdef _AIX
	/*
	 * set the stack limit for AIX for plock().
	 * see get_aix_stack() for more info.
	 */
	if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
	{
		msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m");
	}
#   endif /* _AIX */
	/*
	 * lock the process into memory
	 */
	if (plock(PROCLOCK) < 0)
		msyslog(LOG_ERR, "plock(PROCLOCK): %m");
#  else /* not PROCLOCK */
#   ifdef TXTLOCK
	/*
	 * Lock text into ram
	 */
	if (plock(TXTLOCK) < 0)
		msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
#   else /* not TXTLOCK */
	msyslog(LOG_ERR, "plock() - don't know what to lock!");
#   endif /* not TXTLOCK */
#  endif /* not PROCLOCK */
# endif /* HAVE_PLOCK */
#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */

	/*
	 * Set up signals we pay attention to locally.
	 */
#ifdef SIGDIE1
	(void) signal_no_reset(SIGDIE1, finish);
#endif	/* SIGDIE1 */
#ifdef SIGDIE2
	(void) signal_no_reset(SIGDIE2, finish);
#endif	/* SIGDIE2 */
#ifdef SIGDIE3
	(void) signal_no_reset(SIGDIE3, finish);
#endif	/* SIGDIE3 */
#ifdef SIGDIE4
	(void) signal_no_reset(SIGDIE4, finish);
#endif	/* SIGDIE4 */

#ifdef SIGBUS
	(void) signal_no_reset(SIGBUS, finish);
#endif /* SIGBUS */

#if !defined(SYS_WINNT) && !defined(VMS)
# ifdef DEBUG
	(void) signal_no_reset(MOREDEBUGSIG, moredebug);
	(void) signal_no_reset(LESSDEBUGSIG, lessdebug);
# else
	(void) signal_no_reset(MOREDEBUGSIG, no_debug);
	(void) signal_no_reset(LESSDEBUGSIG, no_debug);
# endif /* DEBUG */
#endif /* !SYS_WINNT && !VMS */

	/*
	 * Set up signals we should never pay attention to.
	 */
#if defined SIGPIPE
	(void) signal_no_reset(SIGPIPE, SIG_IGN);
#endif	/* SIGPIPE */

	/*
	 * Call the init_ routines to initialize the data structures.
	 *
	 * Exactly what command-line options are we expecting here?
	 */
	init_auth();
	init_util();
	init_restrict();
	init_mon();
	init_timer();
	init_lib();
	init_request();
	init_control();
	init_peer();
#ifdef REFCLOCK
	init_refclock();
#endif
	set_process_priority();
	init_proto();		/* Call at high priority */
	init_io();
	init_loopfilter();
	mon_start(MON_ON);	/* monitor on by default now	  */
				/* turn off in config if unwanted */

	/*
	 * Get the configuration.  This is done in a separate module
	 * since this will definitely be different for the gizmo board.
	 */
	getconfig(argc, argv);
	report_event(EVNT_SYSRESTART, NULL, NULL);
	loop_config(LOOP_DRIFTCOMP, old_drift);
	initializing = 0;

#ifdef HAVE_DROPROOT
	if( droproot ) {
		/* Drop super-user privileges and chroot now if the OS supports this */

#ifdef HAVE_LINUX_CAPABILITIES
		/* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
		if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) {
			msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
			exit(-1);
		}
#else
		/* we need a user to switch to */
		if (user == NULL) {
			msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
			exit(-1);
		}
#endif /* HAVE_LINUX_CAPABILITIES */

		if (user != NULL) {
			if (isdigit((unsigned char)*user)) {
				sw_uid = (uid_t)strtoul(user, &endp, 0);
				if (*endp != '\0')
					goto getuser;

				if ((pw = getpwuid(sw_uid)) != NULL) {
					user = strdup(pw->pw_name);
					if (NULL == user) {
						msyslog(LOG_ERR, "strdup() failed: %m");
						exit (-1);
					}
					sw_gid = pw->pw_gid;
				} else {
					errno = 0;
					msyslog(LOG_ERR, "Cannot find user ID %s", user);
					exit (-1);
				}

			} else {
getuser:
				errno = 0;
				if ((pw = getpwnam(user)) != NULL) {
					sw_uid = pw->pw_uid;
					sw_gid = pw->pw_gid;
				} else {
					if (errno)
					    msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
					else
					    msyslog(LOG_ERR, "Cannot find user `%s'", user);
					exit (-1);
				}
			}
		}
		if (group != NULL) {
			if (isdigit((unsigned char)*group)) {
				sw_gid = (gid_t)strtoul(group, &endp, 0);
				if (*endp != '\0')
					goto getgroup;
			} else {
getgroup:
				if ((gr = getgrnam(group)) != NULL) {
					sw_gid = gr->gr_gid;
				} else {
					errno = 0;
					msyslog(LOG_ERR, "Cannot find group `%s'", group);
					exit (-1);
				}
			}
		}

		if (chrootdir ) {
			/* make sure cwd is inside the jail: */
			if (chdir(chrootdir)) {
				msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
				exit (-1);
			}
			if (chroot(chrootdir)) {
				msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
				exit (-1);
			}
			if (chdir("/")) {
				msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m");
				exit (-1);
			}
		}
		if (user && initgroups(user, sw_gid)) {
			msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
			exit (-1);
		}
		if (group && setgid(sw_gid)) {
			msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
			exit (-1);
		}
		if (group && setegid(sw_gid)) {
			msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
			exit (-1);
		}
		if (group)
			setgroups(1, &sw_gid);
		else
			initgroups(pw->pw_name, pw->pw_gid);
		if (user && setuid(sw_uid)) {
			msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
			exit (-1);
		}
		if (user && seteuid(sw_uid)) {
			msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
			exit (-1);
		}

#ifndef HAVE_LINUX_CAPABILITIES
		/*
		 * for now assume that the privilege to bind to privileged ports
		 * is associated with running with uid 0 - should be refined on
		 * ports that allow binding to NTP_PORT with uid != 0
		 */
		disable_dynamic_updates |= (sw_uid != 0);  /* also notifies routing message listener */
#endif

		if (disable_dynamic_updates && interface_interval) {
			interface_interval = 0;
			msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
		}

#ifdef HAVE_LINUX_CAPABILITIES
		do {
			/*
			 *  We may be running under non-root uid now, but we still hold full root privileges!
			 *  We drop all of them, except for the crucial one or two: cap_sys_time and
			 *  cap_net_bind_service if doing dynamic interface tracking.
			 */
			cap_t caps;
			char *captext = (interface_interval)
				? "cap_sys_time,cap_net_bind_service=ipe"
				: "cap_sys_time=ipe";
			if( ! ( caps = cap_from_text( captext ) ) ) {
				msyslog( LOG_ERR, "cap_from_text() failed: %m" );
				exit(-1);
			}
			if( cap_set_proc( caps ) == -1 ) {
				msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" );
				exit(-1);
			}
			cap_free( caps );
		} while(0);
#endif /* HAVE_LINUX_CAPABILITIES */

	}    /* if( droproot ) */
#endif /* HAVE_DROPROOT */

	/*
	 * Use select() on all on all input fd's for unlimited
	 * time.  select() will terminate on SIGALARM or on the
	 * reception of input.	Using select() means we can't do
	 * robust signal handling and we get a potential race
	 * between checking for alarms and doing the select().
	 * Mostly harmless, I think.
	 */
	/* On VMS, I suspect that select() can't be interrupted
	 * by a "signal" either, so I take the easy way out and
	 * have select() time out after one second.
	 * System clock updates really aren't time-critical,
	 * and - lacking a hardware reference clock - I have
	 * yet to learn about anything else that is.
	 */
#if defined(HAVE_IO_COMPLETION_PORT)

	for (;;) {
		GetReceivedBuffers();
#else /* normal I/O */

	BLOCK_IO_AND_ALARM();
	was_alarmed = 0;
	for (;;)
	{
# if !defined(HAVE_SIGNALED_IO)
		extern fd_set activefds;
		extern int maxactivefd;

		fd_set rdfdes;
		int nfound;
# endif

		if (alarm_flag)		/* alarmed? */
		{
			was_alarmed = 1;
			alarm_flag = 0;
		}

		if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE)
		{
			/*
			 * Nothing to do.  Wait for something.
			 */
# ifndef HAVE_SIGNALED_IO
			rdfdes = activefds;
#  if defined(VMS) || defined(SYS_VXWORKS)
			/* make select() wake up after one second */
			{
				struct timeval t1;

				t1.tv_sec = 1; t1.tv_usec = 0;
				nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
						(fd_set *)0, &t1);
			}
#  else
			nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
					(fd_set *)0, (struct timeval *)0);
#  endif /* VMS */
			if (nfound > 0)
			{
				l_fp ts;

				get_systime(&ts);

				(void)input_handler(&ts);
			}
			else if (nfound == -1 && errno != EINTR)
				msyslog(LOG_ERR, "select() error: %m");
#  ifdef DEBUG
			else if (debug > 5)
				msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
#  endif /* DEBUG */
# else /* HAVE_SIGNALED_IO */

			wait_for_signal();
# endif /* HAVE_SIGNALED_IO */
			if (alarm_flag)		/* alarmed? */
			{
				was_alarmed = 1;
				alarm_flag = 0;
			}
		}

		if (was_alarmed)
		{
			UNBLOCK_IO_AND_ALARM();
			/*
			 * Out here, signals are unblocked.  Call timer routine
			 * to process expiry.
			 */
			timer();
			was_alarmed = 0;
			BLOCK_IO_AND_ALARM();
		}

#endif /* ! HAVE_IO_COMPLETION_PORT */

#ifdef DEBUG_TIMING
		{
			l_fp pts;
			l_fp tsa, tsb;
			int bufcount = 0;

			get_systime(&pts);
			tsa = pts;
#endif
			rbuf = get_full_recv_buffer();
			while (rbuf != NULL)
			{
				if (alarm_flag)
				{
					was_alarmed = 1;
					alarm_flag = 0;
				}
				UNBLOCK_IO_AND_ALARM();

				if (was_alarmed)
				{	/* avoid timer starvation during lengthy I/O handling */
					timer();
					was_alarmed = 0;
				}

				/*
				 * Call the data procedure to handle each received
				 * packet.
				 */
				if (rbuf->receiver != NULL)	/* This should always be true */
				{
#ifdef DEBUG_TIMING
					l_fp dts = pts;

					L_SUB(&dts, &rbuf->recv_time);
					DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
					collect_timing(rbuf, "buffer processing delay", 1, &dts);
					bufcount++;
#endif
					(rbuf->receiver)(rbuf);
				} else {
					msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING");
					abort();
				}

				BLOCK_IO_AND_ALARM();
				freerecvbuf(rbuf);
				rbuf = get_full_recv_buffer();
			}
#ifdef DEBUG_TIMING
			get_systime(&tsb);
			L_SUB(&tsb, &tsa);
			if (bufcount) {
				collect_timing(NULL, "processing", bufcount, &tsb);
				DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
			}
		}
#endif

		/*
		 * Go around again
		 */

#ifdef HAVE_DNSREGISTRATION
		if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) {
			mdnsreg = current_time;
			msyslog(LOG_INFO, "Attempting to register mDNS");
			if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, 
			    htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
				if (!--mdnstries) {
					msyslog(LOG_ERR, "Unable to register mDNS, giving up.");
				} else {	
					msyslog(LOG_INFO, "Unable to register mDNS, will try later.");
				}
			} else {
				msyslog(LOG_INFO, "mDNS service registered.");
				mdnsreg = 0;
			}
		}
#endif /* HAVE_DNSREGISTRATION */

	}
	UNBLOCK_IO_AND_ALARM();
	return 1;
}


#ifdef SIGDIE2
/*
 * finish - exit gracefully
 */
static RETSIGTYPE
finish(
	int sig
	)
{
	msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
#ifdef HAVE_DNSREGISTRATION
	if (mdns != NULL)
		DNSServiceRefDeallocate(mdns);
#endif
	switch (sig) {
# ifdef SIGBUS
	case SIGBUS:
		printf("\nfinish(SIGBUS)\n");
		exit(0);
# endif
	case 0:			/* Should never happen... */
		return;

	default:
		exit(0);
	}
}