Esempio n. 1
0
static void
acceptSock(CtrlRec *cr)
{
    struct cmdsock *cs;
    int fd;

    if ((fd = accept(cr->fd, 0, 0)) < 0) {
      bust:
        logError("Error accepting command connection\n");
        return;
    }
    if (!(cs = Malloc(sizeof(*cs)))) {
        close(fd);
        goto bust;
    }
    cs->sock.fd = fd;
    cs->sock.buffer = 0;
    cs->sock.buflen = 0;
    cs->next = cr->css;
    cr->css = cs;
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
    registerCloseOnFork(fd);
    registerInput(fd);
}
Esempio n. 2
0
int
main(int argc, char **argv)
{
    int oldpid, oldumask, fd, parentPid;
    char *pt, *errorLogFile, **opts;

    /* make sure at least world write access is disabled */
    if (((oldumask = umask(022)) & 002) == 002)
        (void)umask(oldumask);

    /* give /dev/null as stdin */
    if ((fd = open("/dev/null", O_RDONLY)) > 0) {
        dup2(fd, 0);
        close(fd);
    }
    if (fcntl(1, F_GETFD) < 0)
        dup2(0, 1);
    if (fcntl(2, F_GETFD) < 0)
        dup2(0, 2);

#ifndef nowMonotonic
    nowMonotonic = sysconf(_SC_MONOTONIC_CLOCK) >= 200112L;
#endif

#if KDM_LIBEXEC_STRIP == -1
    prog = strrchr(argv[0], '/');
    progname = prog = prog ? prog + 1 : argv[0];
#else
    if (argv[0][0] == '/') {
        if (!strDup(&progpath, argv[0]))
            panic("Out of memory");
    } else
# ifdef __linux__
    {
        /* note that this will resolve symlinks ... */
        int len;
        char fullpath[PATH_MAX];
        if ((len = readlink("/proc/self/exe", fullpath, sizeof(fullpath))) < 0)
            panic("Invoke with full path specification or mount /proc");
        if (!strNDup(&progpath, fullpath, len))
            panic("Out of memory");
    }
# else
#  if 0
        panic("Must be invoked with full path specification");
#  else
    {
        char directory[PATH_MAX+1];
        if (!getcwd(directory, sizeof(directory)))
            panic("Can't find myself (getcwd failed)");
        if (strchr(argv[0], '/')) {
            strApp(&progpath, directory, "/", argv[0], (char *)0);
        } else {
            int len;
            char *path, *pathe, *name, *thenam, nambuf[PATH_MAX+1];

            if (!(path = getenv("PATH")))
                panic("Can't find myself (no PATH)");
            len = strlen(argv[0]);
            name = nambuf + PATH_MAX - len;
            memcpy(name, argv[0], len + 1);
            *--name = '/';
            do {
                if (!(pathe = strchr(path, ':')))
                    pathe = path + strlen(path);
                len = pathe - path;
                if (!len || (len == 1 && *path == '.')) {
                    len = strlen(directory);
                    path = directory;
                }
                thenam = name - len;
                if (thenam >= nambuf) {
                    memcpy(thenam, path, len);
                    if (!access(thenam, X_OK))
                        goto found;
                }
                path = pathe;
            } while (*path++ != '\0');
            panic("Can't find myself (not in PATH)");
          found:
            if (!strDup(&progpath, thenam))
                panic("Out of memory");
        }
    }
#  endif
# endif
    prog = strrchr(progpath, '/') + 1;
# if KDM_LIBEXEC_STRIP
    for (progname = pt = prog, fd = 0; fd < KDM_LIBEXEC_STRIP + 1; fd++) {
        for (;;) {
            pt--;
            if (pt == progpath)
                panic("Executable is obviously located outside BINDIR");
            if (*pt == '/')
                break;
        }
    }
    *pt = 0;
# endif
#endif

#if !defined(HAVE_SETPROCTITLE) && !defined(NOXDMTITLE)
    title = argv[0];
    titleLen = (argv[argc - 1] + strlen(argv[argc - 1])) - title;
#endif

    /*
     * Parse command line options
     */
    parentPid = getppid();
    errorLogFile = 0;
    if (!(opts = Malloc(2 * sizeof(char *))))
        return 1;
    opts[0] = (char *)"";
    opts[1] = 0;
    while (*++argv) {
        if (**argv != '-')
            break;
        pt = *argv + 1;
        if (*pt == '-')
            pt++;
        if (!strcmp(pt, "help") || !strcmp(pt, "h")) {
            printf("Usage: %s [options] [tty]\n"
"  -daemon\t  - Daemonize even when started by init\n"
"  -nodaemon\t  - Do not daemonize even when started from command line\n"
"  -config <file>  - Use alternative master configuration file\n"
"  -xrm <res>\t  - Override frontend-specific resource\n"
"  -error <file>\t  - Use alternative log file\n"
"  -debug <num>\t  - Debug option bitfield:\n"
"\t\t\t0x1 - core log\n"
"\t\t\t0x2 - config reader log\n"
"\t\t\t0x4 - greeter log\n"
"\t\t\t0x8 - IPC log\n"
"\t\t\t0x10 - session sub-daemon post-fork delay\n"
"\t\t\t0x20 - config reader post-start delay\n"
"\t\t\t0x40 - greeter post-start delay\n"
"\t\t\t0x80 - do not use syslog\n"
"\t\t\t0x100 - core Xauth log\n"
"\t\t\t0x200 - debug greeter theming\n"
"\t\t\t0x400 - valgrind config reader and greeter\n"
"\t\t\t0x800 - strace config reader and greeter\n"
                    , prog);
            exit(0);
        } else if (!strcmp(pt, "daemon")) {
            parentPid = 0;
        } else if (!strcmp(pt, "nodaemon")) {
            parentPid = 1;
        } else if (argv[1] && !strcmp(pt, "config")) {
            strDup(opts, *++argv);
        } else if (argv[1] && !strcmp(pt, "xrm")) {
            opts = addStrArr(opts, *++argv, -1);
        } else if (argv[1] && !strcmp(pt, "debug")) {
            sscanf(*++argv, "%i", &debugLevel);
        } else if (argv[1] && (!strcmp(pt, "error") || !strcmp(pt, "logfile"))) {
            errorLogFile = *++argv;
        } else {
            fprintf(stderr, "\"%s\" is an unknown option or is missing a parameter\n", *argv);
            exit(1);
        }
    }

    /*
     * Only allow root to run in non-debug mode to avoid problems
     */
    if (!debugLevel && getuid()) {
        fprintf(stderr, "Only root wants to run %s\n", prog);
        exit(1);
    }

    initErrorLog(errorLogFile);

    if (parentPid != 1)
        becomeDaemon();

    /*
     * Step 1 - load configuration parameters
     */
    if (!initResources(opts) || scanConfigs(False) < 0)
        logPanic("Config reader failed. Aborting ...\n");

    /* SUPPRESS 560 */
    if ((oldpid = storePid())) {
        if (oldpid == -1)
            logError("Cannot create/lock pid file %s\n", pidFile);
        else
            logError("Cannot lock pid file %s, another xdm is running (pid %d)\n",
                     pidFile, oldpid);
        exit(1);
    }

#ifdef NEED_ENTROPY
    addOtherEntropy();
#endif

    /*
     * We used to clean up old authorization files here. As authDir is
     * supposed to be /var/run/xauth or /tmp, we needn't to care for it.
     */

#ifdef XDMCP
    initXdmcp();
#else
    debug("not compiled for XDMCP\n");
#endif
    if (pipe(signalFds))
        logPanic("Unable to create signal notification pipe.\n");
    registerInput(signalFds[0]);
    registerCloseOnFork(signalFds[0]);
    registerCloseOnFork(signalFds[1]);
    (void)Signal(SIGTERM, sigHandler);
    (void)Signal(SIGINT, sigHandler);
    (void)Signal(SIGHUP, sigHandler);
    (void)Signal(SIGCHLD, sigHandler);
    (void)Signal(SIGUSR1, sigHandler);

    /*
     * Step 2 - run a sub-daemon for each entry
     */
    openCtrl(0);
#ifdef XDMCP
    updateListenSockets();
#endif
    mainLoop();
    closeCtrl(0);
    if (sdRec.how) {
        int pid;
        commitBootOption();
        if (Fork(&pid) <= 0) {
            char *cmd = sdRec.how == SHUT_HALT ? cmdHalt : cmdReboot;
            execute(parseArgs((char **)0, cmd), (char **)0);
            logError("Failed to execute shutdown command %\"s\n", cmd);
            exit(1);
        } else {
            sigset_t mask;
            sigemptyset(&mask);
            sigaddset(&mask, SIGCHLD);
            sigaddset(&mask, SIGHUP);
            sigsuspend(&mask);
        }
    }
    debug("nothing left to do, exiting\n");
    return 0;
}
Esempio n. 3
0
void
openCtrl(struct display *d)
{
    CtrlRec *cr;
    const char *dname;
    char *sockdir;
    struct sockaddr_un sa;

    if (!*fifoDir)
        return;
    if (d)
        cr = &d->ctrl, dname = displayName(d);
    else
        cr = &ctrl, dname = 0;
    if (cr->fd < 0) {
        if (mkdir(fifoDir, 0755)) {
            if (errno != EEXIST) {
                logError("mkdir %\"s failed: %m; no control sockets will be available\n",
                         fifoDir);
                return;
            }
        } else {
            chmod(fifoDir, 0755); /* override umask */
        }
        sockdir = 0;
        strApp(&sockdir, fifoDir, dname ? "/dmctl-" : "/dmctl",
               dname, (char *)0);
        if (sockdir) {
            strApp(&cr->path, sockdir, "/socket", (char *)0);
            if (cr->path) {
                if (strlen(cr->path) >= sizeof(sa.sun_path)) {
                    logError("path %\"s too long; control socket will not be available\n",
                             cr->path);
#ifdef HONORS_SOCKET_PERMS
                } else if (mkdir(sockdir, 0700) && errno != EEXIST) {
                    logError("mkdir %\"s failed: %m; control socket will not be available\n",
                             sockdir);
                } else if (unlink(cr->path) && errno != ENOENT) {
                    logError("unlink %\"s failed: %m; control socket will not be available\n",
                             cr->path);
                } else {
#else
                } else if (unlink(sockdir) && errno != ENOENT) {
                    logError("unlink %\"s failed: %m; control socket will not be available\n",
                             sockdir);
                } else if (!strApp(&cr->realdir, sockdir, "-XXXXXX", (char *)0)) {
                } else if (!mkTempDir(cr->realdir)) {
                    logError("mkdir %\"s failed: %m; control socket will not be available\n",
                             cr->realdir);
                    free(cr->realdir);
                    cr->realdir = 0;
                } else if (symlink(cr->realdir, sockdir)) {
                    logError("symlink %\"s => %\"s failed: %m; control socket will not be available\n",
                             sockdir, cr->realdir);
                    rmdir(cr->realdir);
                    free(cr->realdir);
                    cr->realdir = 0;
                } else {
                    chown(sockdir, 0, d ? 0 : fifoGroup);
                    chmod(sockdir, 0750);
#endif
                    if ((cr->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
                        logError("Cannot create control socket: %m\n");
                    } else {
                        sa.sun_family = AF_UNIX;
                        strcpy(sa.sun_path, cr->path);
                        if (!bind(cr->fd, (struct sockaddr *)&sa, sizeof(sa))) {
                            if (!listen(cr->fd, 5)) {
#ifdef HONORS_SOCKET_PERMS
                                chmod(cr->path, 0660);
                                if (!d)
                                    chown(cr->path, -1, fifoGroup);
                                chmod(sockdir, 0755);
#else
                                chmod(cr->path, 0666);
#endif
                                registerCloseOnFork(cr->fd);
                                registerInput(cr->fd);
                                free(sockdir);
                                return;
                            }
                            unlink(cr->path);
                            logError("Cannot listen on control socket %\"s: %m\n",
                                     cr->path);
                        } else {
                            logError("Cannot bind control socket %\"s: %m\n",
                                     cr->path);
                        }
                        close(cr->fd);
                        cr->fd = -1;
                    }
#ifdef HONORS_SOCKET_PERMS
                    rmdir(sockdir);
#else
                    unlink(sockdir);
                    rmdir(cr->realdir);
                    free(cr->realdir);
                    cr->realdir = 0;
#endif
                }
                free(cr->path);
                cr->path = 0;
            }
            free(sockdir);
        }
    }