char * iniMerge( char *data, const char *newdata ) { const char *p, *cb, *ce; char *section = 0, *key, *value; if (!newdata) return data; for (p = newdata;;) { for (; *p == ' ' || *p == '\t'; p++); if (!*p) break; if (*p == '\n') { p++; continue; } if (*p == '#') { for (p++; *p != '\n'; p++) if (!*p) goto bail; p++; continue; } if (*p == '[') { cb = ++p; for (; *p != ']'; p++) if (!*p || *p == '\n') /* missing ] */ goto bail; if (!reStrN( §ion, cb, p - cb )) break; p++; } else { cb = p; for (; *p != '='; p++) if (!*p || *p == '\n') /* missing = */ goto bail; for (ce = p; ce != cb && (*(ce - 1) == ' ' || *(ce - 1) == '\t'); ce--); if (!strNDup( &key, cb, ce - cb )) break; for (p++; *p == ' ' || *p == '\t'; p++); cb = p; for (; *p && *p != '\n'; p++); for (ce = p; ce != cb && (*(ce - 1) == ' ' || *(ce - 1) == '\t'); ce--); if (!strNDup( &value, cb, ce - cb )) break; if (section) data = iniEntry( data, section, key, value ); free( value ); free( key ); } } bail: if (section) free( section ); return data; }
char * iniEntry( char *data, const char *section, const char *key, const char *value ) { char *p = data, *secinsert = 0, *pastinsert = 0, *cb, *ce, *ndata; const char *t; int insect = 0, ll, sl, kl, vl, len, nlen; if (p) { while (*p) { for (; *p == ' ' || *p == '\t'; p++); if (*p == '\n') { p++; continue; } if (*p == '[') { for (t = section; *++p == *t; t++); insect = !*t && *p == ']'; } else if (insect) { for (t = key; *p == *t; t++, p++); for (; *p == ' ' || *p == '\t'; p++); if (!*t && *p == '=') { for (p++; *p == ' ' || *p == '\t'; p++); cb = p; while (*p++ != '\n'); ce = p; if (value) { ll = sl = kl = 0; len = (ce - data) + strlen( ce ); goto insert; } else { for (ce--; ce != cb && (*(ce - 1) == ' ' || *(ce - 1) == '\t'); ce--); if (!strNDup( &p, cb, ce - cb )) return 0; return p; } } } for (; *p != '\n'; p++); p++; if (insect) secinsert = p; else pastinsert = p; } } if (!value) return 0; len = p - data; if (secinsert) { ce = cb = secinsert; sl = ll = 0; } else { sl = strlen( section ) + 3; if (pastinsert) { ce = cb = pastinsert; ll = 1; } else { ce = cb = data; ll = 0; } } kl = strlen( key ) + 1; insert: vl = strlen( value ); nlen = len - (ce - cb) + ll + sl + kl + vl + 1; if (!(p = ndata = Malloc( nlen + 1 ))) return data; apparr( p, data, cb - data ); /* zero length if data is null */ if (kl) { if (sl) { if (ll) appbyte( p, '\n' ); appbyte( p, '[' ); apparr( p, section, sl - 3 ); appbyte( p, ']' ); appbyte( p, '\n' ); } apparr( p, key, kl - 1 ); appbyte( p, '=' ); } apparr( p, value, vl ); appbyte( p, '\n' ); if (data) { apparr( p, ce, len - (ce - data) ); free( data ); } appbyte( p, 0 ); return ndata; }
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; }