void WDMRedirectStderr(int level) { int errpipe[2]; int exitstatus; if (pipe(errpipe) == -1) WDMError("cannot create pipe. " "all stderr messages will go to stderr\n"); childpid = fork(); if (childpid == -1) { WDMError("fork failed. " "all stderr messages will go to stderr\n"); close(errpipe[0]); close(errpipe[1]); } else if (childpid != 0) { /* parent, will read all messages from stderr and * redirect it to log */ Signal(SIGTERM, WDMRedirectSignals); Signal(SIGINT, WDMRedirectSignals); Signal(SIGHUP, WDMRedirectSignals); close(errpipe[1]); exitstatus = WDMRedirectFileToLog(WDM_LEVEL_ERROR, childpid, errpipe[0]); close(errpipe[0]); exit(exitstatus); } /* child, will close read end of pipe and dup2 * write end of pipe to stderr */ close(errpipe[0]); RegisterCloseOnFork(errpipe[1]); dup2(errpipe[1], 2); }
static int StorePid(void) { int oldpid; if (pidFile[0] != '\0') { pidFd = open(pidFile, O_RDWR); if (pidFd == -1 && errno == ENOENT) pidFd = open(pidFile, O_RDWR | O_CREAT, 0666); if (pidFd == -1 || !(pidFilePtr = fdopen(pidFd, "r+"))) { WDMError("process-id file %s cannot be opened\n", pidFile); return -1; } if (fscanf(pidFilePtr, "%d\n", &oldpid) != 1) oldpid = -1; fseek(pidFilePtr, 0l, 0); if (lockPidFile.i) { #ifdef F_SETLK #ifndef SEEK_SET #define SEEK_SET 0 #endif struct flock lock_data; lock_data.l_type = F_WRLCK; lock_data.l_whence = SEEK_SET; lock_data.l_start = lock_data.l_len = 0; if (fcntl(pidFd, F_SETLK, &lock_data) == -1) { if (errno == EAGAIN) return oldpid; else return -1; } #else #ifdef LOCK_EX if (flock(pidFd, LOCK_EX | LOCK_NB) == -1) { if (errno == EWOULDBLOCK) return oldpid; else return -1; } #else if (lockf(pidFd, F_TLOCK, 0) == -1) { if (errno == EACCES) return oldpid; else return -1; } #endif #endif } fprintf(pidFilePtr, "%5ld\n", (long)getpid()); (void)fflush(pidFilePtr); RegisterCloseOnFork(pidFd); } return 0; }
int WaitForServer (struct display *d) { static int i; for (i = 0; i < (d->openRepeat > 0 ? d->openRepeat : 1); i++) { (void) Signal (SIGALRM, abortOpen); (void) alarm ((unsigned) d->openTimeout); if (!Setjmp (openAbort)) { Debug ("Before XOpenDisplay(%s)\n", d->name); errno = 0; (void) XSetIOErrorHandler (openErrorHandler); dpy = XOpenDisplay (d->name); #ifdef STREAMSCONN { /* For some reason, the next XOpenDisplay we do is going to fail, so we might as well get that out of the way. There is something broken here. */ Display *bogusDpy = XOpenDisplay (d->name); Debug ("bogus XOpenDisplay %s\n", bogusDpy ? "succeeded" : "failed"); if (bogusDpy) XCloseDisplay(bogusDpy); /* just in case */ } #endif (void) alarm ((unsigned) 0); (void) Signal (SIGALRM, SIG_DFL); (void) XSetIOErrorHandler ((int (*)(Display *)) 0); Debug ("After XOpenDisplay(%s)\n", d->name); if (dpy) { #ifdef XDMCP if (d->displayType.location == Foreign) GetRemoteAddress (d, ConnectionNumber (dpy)); #endif RegisterCloseOnFork (ConnectionNumber (dpy)); (void) fcntl (ConnectionNumber (dpy), F_SETFD, 0); return 1; } else { Debug ("OpenDisplay failed %d (%s) on \"%s\"\n", errno, strerror (errno), d->name); } Debug ("waiting for server to start %d\n", i); sleep ((unsigned) d->openDelay); } else { Debug ("hung in open, aborting\n"); LogError ("Hung in XOpenDisplay(%s), aborting\n", d->name); (void) Signal (SIGALRM, SIG_DFL); break; } } Debug ("giving up on server\n"); LogError ("server open failed for %s, giving up\n", d->name); return 0; }
static int CreateListeningSocket( struct sockaddr *sock_addr, int salen ) { int fd; #if defined(IPv6) && defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) int on = 0; #endif const char *addrstring = "unknown"; #if defined(IPv6) && defined(AF_INET6) char addrbuf[INET6_ADDRSTRLEN]; #endif if (!request_port) return -1; if (debugLevel & DEBUG_CORE) { #if defined(IPv6) && defined(AF_INET6) void *ipaddr; if (sock_addr->sa_family == AF_INET6) ipaddr = & ((struct sockaddr_in6 *)sock_addr)->sin6_addr; else ipaddr = & ((struct sockaddr_in *)sock_addr)->sin_addr; addrstring = inet_ntop( sock_addr->sa_family, ipaddr, addrbuf, sizeof(addrbuf) ); #else addrstring = inet_ntoa( ((struct sockaddr_in *)sock_addr)->sin_addr ); #endif Debug( "creating socket to listen on port %d of address %s\n", request_port, addrstring ); } if ((fd = socket( sock_addr->sa_family, SOCK_DGRAM, 0 )) == -1) { LogError( "XDMCP socket creation failed, errno %d\n", errno ); return -1; } #if defined(IPv6) && defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) setsockopt( fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on) ); #endif if (bind( fd, sock_addr, salen ) == -1) { LogError( "error %d binding socket address %d\n", errno, request_port ); close( fd ); return -1; } RegisterCloseOnFork( fd ); RegisterInput( fd ); return fd; }
CreateWellKnownSockets () { struct sockaddr_in sock_addr; char *name, *localHostname(); if (request_port == 0) return; Debug ("creating socket %d\n", request_port); xdmcpFd = socket (AF_INET, SOCK_DGRAM, 0); if (xdmcpFd == -1) { LogError (ReadCatalog(MC_LOG_SET,MC_LOG_FAIL_SOCK,MC_DEF_LOG_FAIL_SOCK), request_port); return; } name = localHostname (); registerHostname (name, strlen (name)); RegisterCloseOnFork (xdmcpFd); /* zero out the entire structure; this avoids 4.4 incompatibilities */ bzero ((char *) &sock_addr, sizeof (sock_addr)); #ifdef BSD44SOCKETS sock_addr.sin_len = sizeof(sock_addr); #endif sock_addr.sin_family = AF_INET; sock_addr.sin_port = htons ((short) request_port); sock_addr.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (xdmcpFd, (struct sockaddr *)&sock_addr, sizeof (sock_addr)) == -1) { LogError (ReadCatalog(MC_LOG_SET,MC_LOG_ERR_BIND,MC_DEF_LOG_ERR_BIND), request_port, errno); close (xdmcpFd); xdmcpFd = -1; return; } WellKnownSocketsMax = xdmcpFd; FD_SET (xdmcpFd, &WellKnownSocketsMask); chooserFd = socket (AF_INET, SOCK_STREAM, 0); Debug ("Created chooser socket %d\n", chooserFd); if (chooserFd == -1) { LogError ((unsigned char *)"chooser socket creation failed, errno %d\n", errno); return; } listen (chooserFd, 5); if (chooserFd > WellKnownSocketsMax) WellKnownSocketsMax = chooserFd; FD_SET (chooserFd, &WellKnownSocketsMask); }
CreateWellKnownSockets () { struct sockaddr_in sock_addr; char *name, *localHostname(); if (request_port == 0) return; Debug ("creating socket %d\n", request_port); xdmcpFd = socket (AF_INET, SOCK_DGRAM, 0); if (xdmcpFd == -1) { LogError ("socket creation failed\n"); return; } name = localHostname (); registerHostname (name, strlen (name)); RegisterCloseOnFork (xdmcpFd); /* zero out the entire structure; this avoids 4.4 incompatibilities */ bzero ((char *) &sock_addr, sizeof (sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_port = htons ((short) request_port); sock_addr.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (xdmcpFd, &sock_addr, sizeof (sock_addr)) == -1) { LogError ("error binding socket address %d\n", request_port); close (xdmcpFd); xdmcpFd = -1; return; } WellKnownSocketsMax = xdmcpFd; FD_SET (xdmcpFd, &WellKnownSocketsMask); chooserFd = socket (AF_INET, SOCK_STREAM, 0); Debug ("Created chooser socket %d\n", chooserFd); if (chooserFd == -1) { LogError ("chooser socket creation failed\n"); return; } listen (chooserFd, 5); if (chooserFd > WellKnownSocketsMax) WellKnownSocketsMax = chooserFd; FD_SET (chooserFd, &WellKnownSocketsMask); }
int WaitForServer (struct display *d) { static int i; for (i = 0; i < (d->openRepeat > 0 ? d->openRepeat : 1); i++) { (void) Signal (SIGALRM, abortOpen); (void) alarm ((unsigned) d->openTimeout); if (!Setjmp (openAbort)) { Debug ("Before XOpenDisplay(%s)\n", d->name); errno = 0; (void) XSetIOErrorHandler (openErrorHandler); d->dpy = XOpenDisplay (d->name); (void) alarm ((unsigned) 0); (void) Signal (SIGALRM, SIG_DFL); (void) XSetIOErrorHandler ((int (*)(Display *)) 0); Debug ("After XOpenDisplay(%s)\n", d->name); if (d->dpy) { #ifdef XDMCP if (d->displayType.location == Foreign) GetRemoteAddress (d, ConnectionNumber (d->dpy)); #endif RegisterCloseOnFork (ConnectionNumber (d->dpy)); (void) fcntl (ConnectionNumber (d->dpy), F_SETFD, 0); return 1; } else { Debug ("OpenDisplay failed %d (%s) on \"%s\"\n", errno, strerror (errno), d->name); } Debug ("waiting for server to start %d\n", i); sleep ((unsigned) d->openDelay); } else { Debug ("hung in open, aborting\n"); LogError ("Hung in XOpenDisplay(%s), aborting\n", d->name); (void) Signal (SIGALRM, SIG_DFL); break; } } Debug ("giving up on server\n"); LogError ("server open failed for %s, giving up\n", d->name); return 0; }
int main( int argc, char **argv ) { int oldpid, oldumask, fd, noDaemonMode; 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 ); 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 !defined(HAVE_SETPROCTITLE) && !defined(NOXDMTITLE) Title = argv[0]; TitleLen = (argv[argc - 1] + strlen( argv[argc - 1] )) - Title; #endif /* * Parse command line options */ noDaemonMode = 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 - Don't 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 - don't use syslog\n" "\t\t\t0x100 - core Xauth log\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" )) noDaemonMode = 0; else if (!strcmp( pt, "nodaemon" )) noDaemonMode = 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 (noDaemonMode != 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( "Can't create/lock pid file %s\n", pidFile ); else LogError( "Can't 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 init_session_id(); #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 */ #ifdef XDMCP UpdateListenSockets(); #endif openCtrl( 0 ); MainLoop(); closeCtrl( 0 ); if (sdRec.how) { commitBootOption(); if (Fork() <= 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; }
CreateWellKnownSockets () { struct t_bind bind_addr; struct netconfig *nconf; struct nd_hostserv service; struct nd_addrlist *servaddrs; char *name, *localHostname(); char bindbuf[15]; int it; if (request_port == 0) return; Debug ("creating UDP stream %d\n", request_port); nconf = getnetconfigent("udp"); if (!nconf) { t_error("getnetconfigent udp"); return; } xdmcpFd = t_open(nconf->nc_device, O_RDWR, NULL); if (xdmcpFd == -1) { LogError ("XDMCP stream creation failed\n"); t_error ("t_open"); return; } name = localHostname (); registerHostname (name, strlen (name)); RegisterCloseOnFork (xdmcpFd); service.h_host = HOST_SELF; sprintf(bindbuf, "%d", request_port); service.h_serv = bindbuf; netdir_getbyname(nconf, &service, &servaddrs); freenetconfigent(nconf); bind_addr.qlen = 5; bind_addr.addr.buf = servaddrs->n_addrs[0].buf; bind_addr.addr.len = servaddrs->n_addrs[0].len; it = t_bind(xdmcpFd, &bind_addr, &bind_addr); netdir_free(servaddrs, ND_ADDRLIST); if (it < 0) { LogError ("error binding STREAMS address %d\n", request_port); t_error("t_bind"); /* also goes to log file */ t_close (xdmcpFd); xdmcpFd = -1; return; } WellKnownSocketsMax = xdmcpFd; FD_SET (xdmcpFd, &WellKnownSocketsMask); chooserFd = t_open ("/dev/tcp", O_RDWR, NULL); Debug ("Created chooser fd %d\n", chooserFd); if (chooserFd == -1) { LogError ("chooser stream creation failed\n"); t_error("t_open chooser"); return; } if (chooserFd > WellKnownSocketsMax) WellKnownSocketsMax = chooserFd; FD_SET (chooserFd, &WellKnownSocketsMask); }
static int InitGreet(struct display *d) { int pid; WDMDebug("Greet display=%s\n", d->name); pipe(pipe_filedes); pid = fork(); if (pid == -1) { /* error */ WDMError("Greet cannot fork\n"); exit(RESERVER_DISPLAY); } if (pid == 0) { /* child */ char **env = NULL; char *argv[20]; int argc = 1; /* argc = 0 is for command itself */ close(pipe_filedes[0]); fcntl(pipe_filedes[1], F_SETFD, 0); /* Reset close-on-exec (just in case) */ env = (char **)systemEnv(d, (char *)NULL, FAKEHOME); if (*wdmLocale) env = WDMSetEnv(env, "LANG", wdmLocale); if (*wdmCursorTheme) env = WDMSetEnv(env, "XCURSOR_THEME", wdmCursorTheme); if ((argv[0] = strrchr(wdmLogin, '/')) == NULL) argv[0] = wdmLogin; else argv[0]++; argv[argc++] = wstrconcat("-d", d->name); if (*wdmWm) argv[argc++] = wstrconcat("-w", wdmWm); if (*wdmLogo) argv[argc++] = wstrconcat("-l", wdmLogo); if (*wdmHelpFile) argv[argc++] = wstrconcat("-h", wdmHelpFile); if (*wdmDefaultUser) argv[argc++] = "-u"; if (*wdmBg) argv[argc++] = wstrconcat("-b", wdmBg); if (*wdmLoginConfig) argv[argc++] = wstrconcat("-c", wdmLoginConfig); if (wdmAnimations) argv[argc++] = "-a"; if (wdmXineramaHead) { argv[argc] = wmalloc(25); /* much more than length of 64bit integer converted to string, but it still a hack */ sprintf(argv[argc++], "-x%i", wdmXineramaHead); } argv[argc] = wmalloc(25); sprintf(argv[argc++], "-f%i", pipe_filedes[1]); argv[argc++] = NULL; execve(wdmLogin, argv, env); WDMError("Greet cannot exec %s\n", wdmLogin); exit(RESERVER_DISPLAY); } close(pipe_filedes[1]); RegisterCloseOnFork(pipe_filedes[0]); return pid; }