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); }
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; }
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); } }