xinit.c revision 29004570
1a73027baSmrg/* 2a73027baSmrg 3a73027baSmrgCopyright 1986, 1998 The Open Group 4a73027baSmrg 5a73027baSmrgPermission to use, copy, modify, distribute, and sell this software and its 6a73027baSmrgdocumentation for any purpose is hereby granted without fee, provided that 7a73027baSmrgthe above copyright notice appear in all copies and that both that 8a73027baSmrgcopyright notice and this permission notice appear in supporting 9a73027baSmrgdocumentation. 10a73027baSmrg 11a73027baSmrgThe above copyright notice and this permission notice shall be included in 12a73027baSmrgall copies or substantial portions of the Software. 13a73027baSmrg 14a73027baSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15a73027baSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16a73027baSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17a73027baSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18a73027baSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19a73027baSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20a73027baSmrg 21a73027baSmrgExcept as contained in this notice, the name of The Open Group shall not be 22a73027baSmrgused in advertising or otherwise to promote the sale, use or other dealings 23a73027baSmrgin this Software without prior written authorization from The Open Group. 24a73027baSmrg 25a73027baSmrg*/ 26a73027baSmrg 27a73027baSmrg#ifdef HAVE_CONFIG_H 28a73027baSmrg# include "config.h" 29a73027baSmrg#endif 30a73027baSmrg 31a73027baSmrg#include <X11/Xlib.h> 32a73027baSmrg#include <X11/Xos.h> 33a73027baSmrg#include <X11/Xatom.h> 34a73027baSmrg#include <stdio.h> 35a73027baSmrg#include <ctype.h> 36a73027baSmrg#include <stdint.h> 37a73027baSmrg 38a73027baSmrg#include <signal.h> 39a73027baSmrg#include <sys/wait.h> 40a73027baSmrg#include <errno.h> 41a73027baSmrg#include <setjmp.h> 42a73027baSmrg#include <stdarg.h> 43a73027baSmrg 4472e81212Smrg#ifdef __APPLE__ 4572e81212Smrg#include <AvailabilityMacros.h> 46bf4a254eSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 4772e81212Smrg#include <vproc.h> 4872e81212Smrg#endif 4972e81212Smrg#endif 5072e81212Smrg 5129004570Smrg/* For PRIO_PROCESS and setpriority() */ 5229004570Smrg#ifdef __DragonFly__ 5329004570Smrg#include <sys/time.h> 5429004570Smrg#include <sys/resource.h> 5529004570Smrg#endif /* __DragonFly__ */ 56a73027baSmrg 57a73027baSmrg#include <stdlib.h> 58a73027baSmrg 59a73027baSmrg#ifndef SHELL 60a73027baSmrg#define SHELL "sh" 61a73027baSmrg#endif 62a73027baSmrg 63a73027baSmrgconst char *bindir = BINDIR; 64a73027baSmrgconst char * const server_names[] = { 65a73027baSmrg#ifdef __APPLE__ 66a73027baSmrg "Xquartz Mac OSX Quartz displays.", 67bf4a254eSmrg#else 68bf4a254eSmrg# ifdef __CYGWIN__ 69bf4a254eSmrg "XWin X Server for the Cygwin environment on Microsoft Windows", 70bf4a254eSmrg# else 71bf4a254eSmrg "Xorg Common X server for most displays", 72bf4a254eSmrg# endif 73a73027baSmrg#endif 74a73027baSmrg "Xvfb Virtual frame buffer", 75a73027baSmrg "Xfake kdrive-based virtual frame buffer", 76a73027baSmrg "Xnest X server nested in a window on another X server", 77a73027baSmrg "Xephyr kdrive-based nested X server", 78bf4a254eSmrg "Xvnc X server accessed over VNC's RFB protocol", 79bf4a254eSmrg "Xdmx Distributed Multi-head X server", 80a73027baSmrg NULL}; 81a73027baSmrg 82a73027baSmrg#ifndef XINITRC 83a73027baSmrg#define XINITRC ".xinitrc" 84a73027baSmrg#endif 85a73027baSmrgchar xinitrcbuf[256]; 86a73027baSmrg 87a73027baSmrg#ifndef XSERVERRC 88a73027baSmrg#define XSERVERRC ".xserverrc" 89a73027baSmrg#endif 90a73027baSmrgchar xserverrcbuf[256]; 91a73027baSmrg 9229004570Smrg#define TRUE 1 9329004570Smrg#define FALSE 0 94a73027baSmrg 95a73027baSmrgstatic char *default_server = "X"; 9629004570Smrgstatic char *default_display = ":0"; /* choose most efficient */ 97a73027baSmrgstatic char *default_client[] = {"xterm", "-geometry", "+1+1", "-n", "login", NULL}; 98a73027baSmrgstatic char *serverargv[100]; 99a73027baSmrgstatic char *clientargv[100]; 10029004570Smrgstatic char **server = serverargv + 2; /* make sure room for sh .xserverrc args */ 10129004570Smrgstatic char **client = clientargv + 2; /* make sure room for sh .xinitrc args */ 102a73027baSmrgstatic char *displayNum = NULL; 103a73027baSmrgstatic char *program = NULL; 10429004570Smrgstatic Display *xd = NULL; /* server connection */ 105a73027baSmrgint status; 106a73027baSmrgint serverpid = -1; 107a73027baSmrgint clientpid = -1; 108a73027baSmrgvolatile int gotSignal = 0; 109a73027baSmrg 11029004570Smrgstatic void Execute(char **vec); 11129004570Smrgstatic Bool waitforserver(void); 11229004570Smrgstatic Bool processTimeout(int timeout, char *string); 11329004570Smrgstatic int startServer(char *server[]); 11429004570Smrgstatic int startClient(char *client[]); 11529004570Smrgstatic int ignorexio(Display *dpy); 11629004570Smrgstatic void shutdown(void); 11729004570Smrgstatic void set_environment(void); 11829004570Smrg 11929004570Smrgstatic void Fatal(const char *fmt, ...); 12029004570Smrgstatic void Error(const char *fmt, ...); 12129004570Smrgstatic void Fatalx(const char *fmt, ...); 12229004570Smrgstatic void Errorx(const char *fmt, ...); 123a73027baSmrg 12429004570Smrgstatic void 12529004570SmrgsigCatch(int sig) 126a73027baSmrg{ 12729004570Smrg /* On system with POSIX signals, just interrupt the system call */ 12829004570Smrg gotSignal = sig; 129a73027baSmrg} 130a73027baSmrg 13129004570Smrgstatic void 13229004570SmrgsigIgnore(int sig) 133a73027baSmrg{ 134a73027baSmrg} 135a73027baSmrg 13629004570Smrgstatic void 13729004570SmrgExecute(char **vec) /* has room from up above */ 138a73027baSmrg{ 13929004570Smrg execvp(vec[0], vec); 14029004570Smrg if (access(vec[0], R_OK) == 0) { 141a73027baSmrg vec--; /* back it up to stuff shell in */ 142a73027baSmrg vec[0] = SHELL; 14329004570Smrg execvp(vec[0], vec); 144a73027baSmrg } 145a73027baSmrg return; 146a73027baSmrg} 147a73027baSmrg 148a73027baSmrgint 149a73027baSmrgmain(int argc, char *argv[]) 150a73027baSmrg{ 15129004570Smrg register char **sptr = server; 15229004570Smrg register char **cptr = client; 15329004570Smrg register char **ptr; 15429004570Smrg int pid; 15529004570Smrg int client_given = 0, server_given = 0; 15629004570Smrg int client_args_given = 0, server_args_given = 0; 15729004570Smrg int start_of_client_args, start_of_server_args; 15829004570Smrg struct sigaction sa, si; 15972e81212Smrg#ifdef __APPLE__ 160bf4a254eSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 16129004570Smrg vproc_transaction_t vt; 16272e81212Smrg#endif 16372e81212Smrg#endif 164a73027baSmrg 16529004570Smrg program = *argv++; 16629004570Smrg argc--; 16729004570Smrg /* 16829004570Smrg * copy the client args. 16929004570Smrg */ 17029004570Smrg if (argc == 0 || 17129004570Smrg (**argv != '/' && **argv != '.')) { 17229004570Smrg for (ptr = default_client; *ptr; ) 17329004570Smrg *cptr++ = *ptr++; 17429004570Smrg } else { 17529004570Smrg client_given = 1; 17629004570Smrg } 17729004570Smrg start_of_client_args = (cptr - client); 17829004570Smrg while (argc && strcmp(*argv, "--")) { 17929004570Smrg client_args_given++; 18029004570Smrg *cptr++ = *argv++; 18129004570Smrg argc--; 18229004570Smrg } 18329004570Smrg *cptr = NULL; 18429004570Smrg if (argc) { 18529004570Smrg argv++; 18629004570Smrg argc--; 18729004570Smrg } 18829004570Smrg 18929004570Smrg /* 19029004570Smrg * Copy the server args. 19129004570Smrg */ 19229004570Smrg if (argc == 0 || 19329004570Smrg (**argv != '/' && **argv != '.')) { 19429004570Smrg *sptr++ = default_server; 19529004570Smrg } else { 19629004570Smrg server_given = 1; 19729004570Smrg *sptr++ = *argv++; 19829004570Smrg argc--; 19929004570Smrg } 20029004570Smrg if (argc > 0 && (argv[0][0] == ':' && isdigit(argv[0][1]))) 20129004570Smrg displayNum = *argv; 20229004570Smrg else 20329004570Smrg displayNum = *sptr++ = default_display; 20429004570Smrg 20529004570Smrg start_of_server_args = (sptr - server); 20629004570Smrg while (--argc >= 0) { 20729004570Smrg server_args_given++; 20829004570Smrg *sptr++ = *argv++; 20929004570Smrg } 21029004570Smrg *sptr = NULL; 21129004570Smrg 21229004570Smrg /* 21329004570Smrg * if no client arguments given, check for a startup file and copy 21429004570Smrg * that into the argument list 21529004570Smrg */ 21629004570Smrg if (!client_given) { 21729004570Smrg char *cp; 21829004570Smrg Bool required = False; 21929004570Smrg 22029004570Smrg xinitrcbuf[0] = '\0'; 22129004570Smrg if ((cp = getenv("XINITRC")) != NULL) { 22229004570Smrg snprintf(xinitrcbuf, sizeof(xinitrcbuf), "%s", cp); 22329004570Smrg required = True; 22429004570Smrg } else if ((cp = getenv("HOME")) != NULL) { 22529004570Smrg snprintf(xinitrcbuf, sizeof(xinitrcbuf), 22629004570Smrg "%s/%s", cp, XINITRC); 22729004570Smrg } 22829004570Smrg if (xinitrcbuf[0]) { 22929004570Smrg if (access(xinitrcbuf, F_OK) == 0) { 23029004570Smrg client += start_of_client_args - 1; 23129004570Smrg client[0] = xinitrcbuf; 23229004570Smrg } else if (required) { 23329004570Smrg Error("warning, no client init file \"%s\"", xinitrcbuf); 23429004570Smrg } 23529004570Smrg } 23629004570Smrg } 23729004570Smrg 23829004570Smrg /* 23929004570Smrg * if no server arguments given, check for a startup file and copy 24029004570Smrg * that into the argument list 24129004570Smrg */ 24229004570Smrg if (!server_given) { 24329004570Smrg char *cp; 24429004570Smrg Bool required = False; 24529004570Smrg 24629004570Smrg xserverrcbuf[0] = '\0'; 24729004570Smrg if ((cp = getenv("XSERVERRC")) != NULL) { 24829004570Smrg snprintf(xserverrcbuf, sizeof(xserverrcbuf), "%s", cp); 24929004570Smrg required = True; 25029004570Smrg } else if ((cp = getenv("HOME")) != NULL) { 25129004570Smrg snprintf(xserverrcbuf, sizeof(xserverrcbuf), 25229004570Smrg "%s/%s", cp, XSERVERRC); 25329004570Smrg } 25429004570Smrg if (xserverrcbuf[0]) { 25529004570Smrg if (access(xserverrcbuf, F_OK) == 0) { 25629004570Smrg server += start_of_server_args - 1; 25729004570Smrg server[0] = xserverrcbuf; 25829004570Smrg } else if (required) { 25929004570Smrg Error("warning, no server init file \"%s\"", xserverrcbuf); 26029004570Smrg } 26129004570Smrg } 26229004570Smrg } 26329004570Smrg 26429004570Smrg /* 26529004570Smrg * Start the server and client. 26629004570Smrg */ 26729004570Smrg signal(SIGCHLD, SIG_DFL); /* Insurance */ 26829004570Smrg 26929004570Smrg /* Let those signal interrupt the wait() call in the main loop */ 27029004570Smrg memset(&sa, 0, sizeof sa); 27129004570Smrg sa.sa_handler = sigCatch; 27229004570Smrg sigemptyset(&sa.sa_mask); 27329004570Smrg sa.sa_flags = 0; /* do not set SA_RESTART */ 27429004570Smrg 27529004570Smrg sigaction(SIGTERM, &sa, NULL); 27629004570Smrg sigaction(SIGQUIT, &sa, NULL); 27729004570Smrg sigaction(SIGINT, &sa, NULL); 27829004570Smrg sigaction(SIGHUP, &sa, NULL); 27929004570Smrg sigaction(SIGPIPE, &sa, NULL); 280a73027baSmrg 28129004570Smrg memset(&si, 0, sizeof(si)); 28229004570Smrg si.sa_handler = sigIgnore; 28329004570Smrg sigemptyset(&si.sa_mask); 28429004570Smrg si.sa_flags = SA_RESTART; 28529004570Smrg 28629004570Smrg sigaction(SIGALRM, &si, NULL); 28729004570Smrg sigaction(SIGUSR1, &si, NULL); 28872e81212Smrg 28972e81212Smrg#ifdef __APPLE__ 290bf4a254eSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 29129004570Smrg vt = vproc_transaction_begin(NULL); 29272e81212Smrg#endif 29372e81212Smrg#endif 29472e81212Smrg 29529004570Smrg if (startServer(server) > 0 29629004570Smrg && startClient(client) > 0) { 29729004570Smrg pid = -1; 29829004570Smrg while (pid != clientpid && pid != serverpid 29929004570Smrg && gotSignal == 0 30029004570Smrg ) 30129004570Smrg pid = wait(NULL); 30229004570Smrg } 30372e81212Smrg 30472e81212Smrg#ifdef __APPLE__ 305bf4a254eSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 30629004570Smrg vproc_transaction_end(NULL, vt); 30772e81212Smrg#endif 30872e81212Smrg#endif 30972e81212Smrg 31029004570Smrg signal(SIGTERM, SIG_IGN); 31129004570Smrg signal(SIGQUIT, SIG_IGN); 31229004570Smrg signal(SIGINT, SIG_IGN); 31329004570Smrg signal(SIGHUP, SIG_IGN); 31429004570Smrg signal(SIGPIPE, SIG_IGN); 315a73027baSmrg 31629004570Smrg shutdown(); 317a73027baSmrg 31829004570Smrg if (gotSignal != 0) { 31929004570Smrg Errorx("unexpected signal %d", gotSignal); 32029004570Smrg exit(EXIT_FAILURE); 32129004570Smrg } 322a73027baSmrg 32329004570Smrg if (serverpid < 0) 32429004570Smrg Fatalx("server error"); 32529004570Smrg if (clientpid < 0) 32629004570Smrg Fatalx("client error"); 32729004570Smrg exit(EXIT_SUCCESS); 328a73027baSmrg} 329a73027baSmrg 330a73027baSmrg 331a73027baSmrg/* 33229004570Smrg * waitforserver - wait for X server to start up 333a73027baSmrg */ 334a73027baSmrgstatic Bool 335a73027baSmrgwaitforserver(void) 336a73027baSmrg{ 33729004570Smrg int ncycles = 120; /* # of cycles to wait */ 33829004570Smrg int cycles; /* Wait cycle count */ 339a73027baSmrg 34072e81212Smrg#ifdef __APPLE__ 34129004570Smrg /* For Apple, we don't get signaled by the server when it's ready, so we just 34229004570Smrg * want to sleep now since we're going to sleep later anyways and this allows us 34329004570Smrg * to avoid the awkard, "why is there an error message in the log" questions 34429004570Smrg * from users. 34529004570Smrg */ 34629004570Smrg 34729004570Smrg sleep(2); 34829004570Smrg#endif 34929004570Smrg 35029004570Smrg for (cycles = 0; cycles < ncycles; cycles++) { 35129004570Smrg if ((xd = XOpenDisplay(displayNum))) { 35229004570Smrg return(TRUE); 35329004570Smrg } 35429004570Smrg else { 35529004570Smrg if (!processTimeout(1, "X server to begin accepting connections")) 35629004570Smrg break; 35729004570Smrg } 35829004570Smrg } 35972e81212Smrg 36029004570Smrg Errorx("giving up"); 36172e81212Smrg 36229004570Smrg return(FALSE); 363a73027baSmrg} 364a73027baSmrg 365a73027baSmrg/* 366a73027baSmrg * return TRUE if we timeout waiting for pid to exit, FALSE otherwise. 367a73027baSmrg */ 368a73027baSmrgstatic Bool 369a73027baSmrgprocessTimeout(int timeout, char *string) 370a73027baSmrg{ 37129004570Smrg int i = 0, pidfound = -1; 37229004570Smrg static char *laststring; 37329004570Smrg 37429004570Smrg for (;;) { 37529004570Smrg if ((pidfound = waitpid(serverpid, &status, WNOHANG)) == serverpid) 37629004570Smrg break; 37729004570Smrg if (timeout) { 37829004570Smrg if (i == 0 && string != laststring) 37929004570Smrg fprintf(stderr, "\r\nwaiting for %s ", string); 38029004570Smrg else 38129004570Smrg fprintf(stderr, "."); 38229004570Smrg fflush(stderr); 38329004570Smrg } 38429004570Smrg if (timeout) 38529004570Smrg sleep(1); 38629004570Smrg if (++i > timeout) 38729004570Smrg break; 38829004570Smrg } 38929004570Smrg if (i > 0) fputc('\n', stderr); /* tidy up after message */ 39029004570Smrg laststring = string; 39129004570Smrg return (serverpid != pidfound); 392a73027baSmrg} 393a73027baSmrg 394a73027baSmrgstatic int 395a73027baSmrgstartServer(char *server[]) 396a73027baSmrg{ 39729004570Smrg sigset_t mask, old; 39829004570Smrg const char * const *cpp; 399a73027baSmrg 40029004570Smrg sigemptyset(&mask); 40129004570Smrg sigaddset(&mask, SIGUSR1); 40229004570Smrg sigprocmask(SIG_BLOCK, &mask, &old); 403a73027baSmrg 40429004570Smrg serverpid = fork(); 405a73027baSmrg 40629004570Smrg switch(serverpid) { 40729004570Smrg case 0: 40829004570Smrg /* Unblock */ 40929004570Smrg sigprocmask(SIG_SETMASK, &old, NULL); 410a73027baSmrg 41129004570Smrg /* 41229004570Smrg * don't hang on read/write to control tty 41329004570Smrg */ 41429004570Smrg signal(SIGTTIN, SIG_IGN); 41529004570Smrg signal(SIGTTOU, SIG_IGN); 41629004570Smrg /* 41729004570Smrg * ignore SIGUSR1 in child. The server 41829004570Smrg * will notice this and send SIGUSR1 back 41929004570Smrg * at xinit when ready to accept connections 42029004570Smrg */ 42129004570Smrg signal(SIGUSR1, SIG_IGN); 42229004570Smrg /* 42329004570Smrg * prevent server from getting sighup from vhangup() 42429004570Smrg * if client is xterm -L 42529004570Smrg */ 42629004570Smrg setpgid(0,getpid()); 42729004570Smrg Execute(server); 42829004570Smrg 42929004570Smrg Error("unable to run server \"%s\"", server[0]); 43029004570Smrg 43129004570Smrg fprintf(stderr, "Use the -- option, or make sure that %s is in your path and\n", bindir); 43229004570Smrg fprintf(stderr, "that \"%s\" is a program or a link to the right type of server\n", server[0]); 43329004570Smrg fprintf(stderr, "for your display. Possible server names include:\n\n"); 43429004570Smrg for (cpp = server_names; *cpp; cpp++) 43529004570Smrg fprintf(stderr, " %s\n", *cpp); 43629004570Smrg fprintf(stderr, "\n"); 43729004570Smrg 43829004570Smrg exit(EXIT_FAILURE); 43929004570Smrg 44029004570Smrg break; 44129004570Smrg case -1: 44229004570Smrg break; 44329004570Smrg default: 44429004570Smrg /* 44529004570Smrg * don't nice server 44629004570Smrg */ 44729004570Smrg setpriority(PRIO_PROCESS, serverpid, -1); 44829004570Smrg 44929004570Smrg errno = 0; 45029004570Smrg if(! processTimeout(0, "")) { 45129004570Smrg serverpid = -1; 45229004570Smrg break; 45329004570Smrg } 45429004570Smrg /* 45529004570Smrg * kludge to avoid race with TCP, giving server time to 45629004570Smrg * set his socket options before we try to open it, 45729004570Smrg * either use the 15 second timeout, or await SIGUSR1. 45829004570Smrg * 45929004570Smrg * If your machine is substantially slower than 15 seconds, 46029004570Smrg * you can easily adjust this value. 46129004570Smrg */ 46229004570Smrg alarm(15); 46329004570Smrg 46429004570Smrg sigsuspend(&old); 46529004570Smrg alarm(0); 46629004570Smrg sigprocmask(SIG_SETMASK, &old, NULL); 46729004570Smrg 46829004570Smrg if (waitforserver() == 0) { 46929004570Smrg Error("unable to connect to X server"); 47029004570Smrg shutdown(); 47129004570Smrg serverpid = -1; 47229004570Smrg } 47329004570Smrg break; 47429004570Smrg } 475a73027baSmrg 47629004570Smrg return(serverpid); 477a73027baSmrg} 478a73027baSmrg 479a73027baSmrgstatic void 480a73027baSmrgsetWindowPath(void) 481a73027baSmrg{ 48229004570Smrg /* setting WINDOWPATH for clients */ 48329004570Smrg Atom prop; 48429004570Smrg Atom actualtype; 48529004570Smrg int actualformat; 48629004570Smrg unsigned long nitems; 48729004570Smrg unsigned long bytes_after; 48829004570Smrg unsigned char *buf; 48929004570Smrg const char *windowpath; 49029004570Smrg char *newwindowpath; 49129004570Smrg unsigned long num; 49229004570Smrg char nums[10]; 49329004570Smrg int numn; 49429004570Smrg size_t len; 49529004570Smrg prop = XInternAtom(xd, "XFree86_VT", False); 49629004570Smrg if (prop == None) { 49729004570Smrg Errorx("Unable to intern XFree86_VT atom"); 49829004570Smrg return; 49929004570Smrg } 50029004570Smrg if (XGetWindowProperty(xd, DefaultRootWindow(xd), prop, 0, 1, 50129004570Smrg False, AnyPropertyType, &actualtype, &actualformat, 50229004570Smrg &nitems, &bytes_after, &buf)) { 50329004570Smrg Errorx("No XFree86_VT property detected on X server, WINDOWPATH won't be set"); 50429004570Smrg return; 50529004570Smrg } 50629004570Smrg if (nitems != 1) { 50729004570Smrg Errorx("XFree86_VT property unexpectedly has %lu items instead of 1", nitems); 50829004570Smrg XFree(buf); 50929004570Smrg return; 51029004570Smrg } 51129004570Smrg switch (actualtype) { 51229004570Smrg case XA_CARDINAL: 51329004570Smrg case XA_INTEGER: 51429004570Smrg case XA_WINDOW: 51529004570Smrg switch (actualformat) { 51629004570Smrg case 8: 51729004570Smrg num = (*(uint8_t *)(void *)buf); 51829004570Smrg break; 51929004570Smrg case 16: 52029004570Smrg num = (*(uint16_t *)(void *)buf); 52129004570Smrg break; 52229004570Smrg case 32: 52329004570Smrg num = (*(uint32_t *)(void *)buf); 52429004570Smrg break; 52529004570Smrg default: 52629004570Smrg Errorx("XFree86_VT property has unexpected format %d", actualformat); 52729004570Smrg XFree(buf); 52829004570Smrg return; 52929004570Smrg } 53029004570Smrg break; 53129004570Smrg default: 53229004570Smrg Errorx("XFree86_VT property has unexpected type %lx", actualtype); 53329004570Smrg XFree(buf); 53429004570Smrg return; 53529004570Smrg } 53629004570Smrg XFree(buf); 53729004570Smrg windowpath = getenv("WINDOWPATH"); 53829004570Smrg numn = snprintf(nums, sizeof(nums), "%lu", num); 53929004570Smrg if (!windowpath) { 54029004570Smrg len = numn + 1; 54129004570Smrg newwindowpath = malloc(len); 54229004570Smrg if (newwindowpath == NULL) 54329004570Smrg return; 54429004570Smrg snprintf(newwindowpath, len, "%s", nums); 54529004570Smrg } else { 54629004570Smrg len = strlen(windowpath) + 1 + numn + 1; 54729004570Smrg newwindowpath = malloc(len); 54829004570Smrg if (newwindowpath == NULL) 54929004570Smrg return; 55029004570Smrg snprintf(newwindowpath, len, "%s:%s", 55129004570Smrg windowpath, nums); 55229004570Smrg } 55329004570Smrg if (setenv("WINDOWPATH", newwindowpath, TRUE) == -1) 55429004570Smrg Error("unable to set WINDOWPATH"); 55529004570Smrg 55629004570Smrg 55729004570Smrg free(newwindowpath); 558a73027baSmrg} 559a73027baSmrg 560a73027baSmrgstatic int 561a73027baSmrgstartClient(char *client[]) 562a73027baSmrg{ 56329004570Smrg clientpid = fork(); 56429004570Smrg if (clientpid == 0) { 56529004570Smrg set_environment(); 56629004570Smrg setWindowPath(); 56729004570Smrg 56829004570Smrg if (setuid(getuid()) == -1) { 56929004570Smrg Error("cannot change uid"); 57029004570Smrg _exit(EXIT_FAILURE); 57129004570Smrg } 57229004570Smrg setpgid(0, getpid()); 57329004570Smrg Execute(client); 57429004570Smrg Error("Unable to run program \"%s\"", client[0]); 57529004570Smrg 57629004570Smrg fprintf(stderr, "Specify a program on the command line or make sure that %s\n", bindir); 57729004570Smrg fprintf(stderr, "is in your path.\n\n"); 57829004570Smrg 57929004570Smrg _exit(EXIT_FAILURE); 58029004570Smrg } else { 58129004570Smrg return clientpid; 58229004570Smrg } 583a73027baSmrg} 584a73027baSmrg 585a73027baSmrgstatic jmp_buf close_env; 586a73027baSmrg 58729004570Smrgstatic int 588a73027baSmrgignorexio(Display *dpy) 589a73027baSmrg{ 59029004570Smrg Errorx("connection to X server lost"); 59129004570Smrg longjmp(close_env, 1); 592a73027baSmrg /*NOTREACHED*/ 593a73027baSmrg return 0; 594a73027baSmrg} 595a73027baSmrg 59629004570Smrgstatic void 597a73027baSmrgshutdown(void) 598a73027baSmrg{ 59929004570Smrg /* have kept display opened, so close it now */ 60029004570Smrg if (clientpid > 0) { 60129004570Smrg XSetIOErrorHandler(ignorexio); 60229004570Smrg if (! setjmp(close_env)) { 60329004570Smrg XCloseDisplay(xd); 60429004570Smrg } 60529004570Smrg 60629004570Smrg /* HUP all local clients to allow them to clean up */ 60729004570Smrg if (killpg(clientpid, SIGHUP) < 0 && errno != ESRCH) 60829004570Smrg Error("can't send HUP to process group %d", clientpid); 60929004570Smrg } 610a73027baSmrg 61129004570Smrg if (serverpid < 0) 61229004570Smrg return; 613a73027baSmrg 61429004570Smrg if (killpg(serverpid, SIGTERM) < 0) { 61529004570Smrg if (errno == ESRCH) 61629004570Smrg return; 61729004570Smrg Fatal("can't kill X server"); 61829004570Smrg } 61929004570Smrg 62029004570Smrg if (!processTimeout(10, "X server to shut down")) 62129004570Smrg return; 622a73027baSmrg 62329004570Smrg Errorx("X server slow to shut down, senging KILL signal"); 62429004570Smrg 62529004570Smrg if (killpg(serverpid, SIGKILL) < 0) { 62629004570Smrg if (errno == ESRCH) 62729004570Smrg return; 62829004570Smrg Error("can't SIGKILL X server"); 62929004570Smrg } 63029004570Smrg 63129004570Smrg if (processTimeout(3, "server to die")) 63229004570Smrg Fatalx("X server refuses to die"); 63329004570Smrg} 63429004570Smrg 63529004570Smrgstatic void 636a73027baSmrgset_environment(void) 637a73027baSmrg{ 63829004570Smrg if (setenv("DISPLAY", displayNum, TRUE) == -1) 63929004570Smrg Fatal("unable to set DISPLAY"); 64029004570Smrg} 641a73027baSmrg 64229004570Smrgstatic void 64329004570Smrgverror(const char *fmt, va_list ap) 64429004570Smrg{ 64529004570Smrg fprintf(stderr, "%s: ", program); 64629004570Smrg vfprintf(stderr, fmt, ap); 64729004570Smrg fprintf(stderr, ": %s\n", strerror(errno)); 64829004570Smrg} 64929004570Smrg 65029004570Smrgstatic void 65129004570Smrgverrorx(const char *fmt, va_list ap) 65229004570Smrg{ 65329004570Smrg fprintf(stderr, "%s: ", program); 65429004570Smrg vfprintf(stderr, fmt, ap); 65529004570Smrg fprintf(stderr, "\n"); 65629004570Smrg} 65729004570Smrg 65829004570Smrgstatic void 65929004570SmrgFatal(const char *fmt, ...) 66029004570Smrg{ 66129004570Smrg va_list ap; 66229004570Smrg va_start(ap, fmt); 66329004570Smrg verror(fmt, ap); 66429004570Smrg va_end(ap); 66529004570Smrg exit(EXIT_FAILURE); 66629004570Smrg} 66729004570Smrg 66829004570Smrgstatic void 66929004570SmrgFatalx(const char *fmt, ...) 67029004570Smrg{ 67129004570Smrg va_list ap; 67229004570Smrg va_start(ap, fmt); 67329004570Smrg verrorx(fmt, ap); 67429004570Smrg va_end(ap); 67529004570Smrg exit(EXIT_FAILURE); 676a73027baSmrg} 677a73027baSmrg 678a73027baSmrgstatic void 67929004570SmrgError(const char *fmt, ...) 680a73027baSmrg{ 68129004570Smrg va_list ap; 68229004570Smrg va_start(ap, fmt); 68329004570Smrg verror(fmt, ap); 68429004570Smrg va_end(ap); 685a73027baSmrg} 686a73027baSmrg 687a73027baSmrgstatic void 68829004570SmrgErrorx(const char *fmt, ...) 689a73027baSmrg{ 69029004570Smrg va_list ap; 69129004570Smrg va_start(ap, fmt); 69229004570Smrg verrorx(fmt, ap); 69329004570Smrg va_end(ap); 694a73027baSmrg} 695