diff options
Diffstat (limited to 'hw/xwin/winprefs.c')
-rw-r--r-- | hw/xwin/winprefs.c | 224 |
1 files changed, 187 insertions, 37 deletions
diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c index 0ac5b4fea..1afba3165 100644 --- a/hw/xwin/winprefs.c +++ b/hw/xwin/winprefs.c @@ -37,6 +37,9 @@ #include <stdlib.h> #ifdef __CYGWIN__ #include <sys/resource.h> +#include <sys/wait.h> +#include <pthread.h> +#include <sys/cygwin.h> #endif #include "win.h" @@ -59,9 +62,6 @@ extern int parse_file(FILE * fp); /* Currently in use command ID, incremented each new menu item created */ static int g_cmdid = STARTMENUID; -/* Local function to handle comma-ified icon names */ -static HICON LoadImageComma(char *fname, int sx, int sy, int flags); - /* * Creates or appends a menu from a MENUPARSED structure */ @@ -295,6 +295,110 @@ HandleCustomWM_INITMENU(HWND hwnd, HMENU hmenu) } +#ifdef __CYGWIN__ +static void +LogLineFromFd(int fd, const char *fdname, int pid) +{ +#define BUFSIZE 512 /* must be less than internal buffer size used in LogVWrite */ + char buf[BUFSIZE]; + char *bufptr = buf; + + /* read from fd until eof, newline or our buffer is full */ + while ((read(fd, bufptr, 1) > 0) && (bufptr < &(buf[BUFSIZE - 1]))) { + if (*bufptr == '\n') + break; + bufptr++; + } + + /* null terminate and log */ + *bufptr = 0; + if (strlen(buf)) + ErrorF("(pid %d %s) %s\n", pid, fdname, buf); +} + +static void * +ExecAndLogThread(void *cmd) +{ + int pid; + int stdout_filedes[2]; + int stderr_filedes[2]; + int status; + + /* Create a pair of pipes */ + pipe(stdout_filedes); + pipe(stderr_filedes); + + switch (pid = fork()) { + case 0: /* child */ + { + struct rlimit rl; + unsigned int fd; + + /* dup write end of pipes onto stderr and stdout */ + close(STDOUT_FILENO); + close(STDERR_FILENO); + + dup2(stdout_filedes[1], STDOUT_FILENO); + dup2(stderr_filedes[1], STDERR_FILENO); + + /* Close any open descriptors except for STD* */ + getrlimit(RLIMIT_NOFILE, &rl); + for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++) + close(fd); + + /* Disassociate any TTYs */ + setsid(); + + execl("/bin/sh", "/bin/sh", "-c", cmd, NULL); + perror("execl failed"); + exit(127); + } + break; + + default: /* parent */ + { + close(stdout_filedes[1]); + close(stderr_filedes[1]); + + ErrorF("executing '%s', pid %d\n", (char *) cmd, pid); + + /* read from pipes, write to log, until both are closed */ + while (TRUE) { + fd_set readfds, errorfds; + int nfds = max(stdout_filedes[0], stderr_filedes[0]) + 1; + + FD_ZERO(&readfds); + FD_SET(stdout_filedes[0], &readfds); + FD_SET(stderr_filedes[0], &readfds); + errorfds = readfds; + + if (select(nfds, &readfds, NULL, &errorfds, NULL) > 0) { + if (FD_ISSET(stdout_filedes[0], &readfds)) + LogLineFromFd(stdout_filedes[0], "stdout", pid); + if (FD_ISSET(stderr_filedes[0], &readfds)) + LogLineFromFd(stderr_filedes[0], "stderr", pid); + + if (FD_ISSET(stdout_filedes[0], &errorfds) && + FD_ISSET(stderr_filedes[0], &errorfds)) + break; + } + else { + break; + } + } + + waitpid(pid, &status, 0); + } + break; + + case -1: /* error */ + ErrorF("fork() to run command failed\n"); + } + + return (void *) (intptr_t) status; +} +#endif + /* * Searches for the custom WM_COMMAND command ID and performs action. * Return TRUE if command is proccessed, FALSE otherwise. @@ -317,24 +421,17 @@ HandleCustomWM_COMMAND(HWND hwnd, WORD command, winPrivScreenPtr pScreenPriv) switch (m->menuItem[j].cmd) { #ifdef __CYGWIN__ case CMD_EXEC: - if (fork() == 0) { - struct rlimit rl; - int fd; - - /* Close any open descriptors except for STD* */ - getrlimit(RLIMIT_NOFILE, &rl); - for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++) - close(fd); - - /* Disassociate any TTYs */ - setsid(); + { + pthread_t t; - execl("/bin/sh", - "/bin/sh", "-c", m->menuItem[j].param, NULL); - exit(0); - } + if (!pthread_create + (&t, NULL, ExecAndLogThread, m->menuItem[j].param)) + pthread_detach(t); else - return TRUE; + ErrorF + ("Creating command output logging thread failed\n"); + } + return TRUE; break; #else case CMD_EXEC: @@ -418,8 +515,10 @@ SetupSysMenu(HWND hwnd) pWin = GetProp(hwnd, WIN_WINDOW_PROP); sys = GetSystemMenu(hwnd, FALSE); - if (!sys) + if (!sys) { + ErrorF("SetupSysMenu: GetSystemMenu() failed for HWND %p\n", hwnd); return; + } if (pWin) { /* First see if there's a class match... */ @@ -474,7 +573,7 @@ winOverrideDefaultIcon(int size) HICON hicon; if (pref.defaultIconName[0]) { - hicon = LoadImageComma(pref.defaultIconName, size, size, 0); + hicon = LoadImageComma(pref.defaultIconName, pref.iconDirectory, size, size, 0); if (hicon == NULL) ErrorF("winOverrideDefaultIcon: LoadImageComma(%s) failed\n", pref.defaultIconName); @@ -496,9 +595,12 @@ winTaskbarIcon(void) hicon = 0; /* First try and load an overridden, if success then return it */ if (pref.trayIconName[0]) { - hicon = LoadImageComma(pref.trayIconName, + hicon = LoadImageComma(pref.trayIconName, pref.iconDirectory, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); + if (hicon == NULL) + ErrorF("winTaskbarIcon: LoadImageComma(%s) failed\n", + pref.trayIconName); } /* Otherwise return the default */ @@ -513,17 +615,18 @@ winTaskbarIcon(void) } /* + * Handle comma-ified icon names + * * Parse a filename to extract an icon: * If fname is exactly ",nnn" then extract icon from our resource * else if it is "file,nnn" then extract icon nnn from that file * else try to load it as an .ico file and if that fails return NULL */ -static HICON -LoadImageComma(char *fname, int sx, int sy, int flags) +HICON +LoadImageComma(char *fname, char *iconDirectory, int sx, int sy, int flags) { HICON hicon; int i; - char file[PATH_MAX + NAME_MAX + 2]; /* Some input error checking */ if (!fname || !fname[0]) @@ -539,31 +642,67 @@ LoadImageComma(char *fname, int sx, int sy, int flags) MAKEINTRESOURCE(i), IMAGE_ICON, sx, sy, flags); } else { + char *file = malloc(PATH_MAX + NAME_MAX + 2); + Bool convert = FALSE; + + if (!file) + return NULL; + file[0] = 0; - /* Prepend path if not given a "X:\" filename */ + + /* If fname starts 'X:\', it's an absolute Windows path, do nothing */ if (!(fname[0] && fname[1] == ':' && fname[2] == '\\')) { - strcpy(file, pref.iconDirectory); - if (pref.iconDirectory[0]) - if (fname[strlen(fname) - 1] != '\\') - strcat(file, "\\"); +#ifdef __CYGWIN__ + /* If fname starts with '/', it's an absolute cygwin path, we'll + need to convert it */ + if (fname[0] == '/') { + convert = TRUE; + } + else +#endif + if (iconDirectory) { + /* Otherwise, prepend the default icon directory, which + currently must be in absolute Windows path form */ + strcpy(file, iconDirectory); + if (iconDirectory[0]) + if (iconDirectory[strlen(iconDirectory) - 1] != '\\') + strcat(file, "\\"); + } } strcat(file, fname); + /* Trim off any ',index' */ if (strrchr(file, ',')) { - /* Specified as <fname>,<index> */ - *(strrchr(file, ',')) = 0; /* End string at comma */ i = atoi(strrchr(fname, ',') + 1); - hicon = ExtractIcon(g_hInstance, file, i); } else { - /* Just an .ico file... */ + i = -1; + } + +#ifdef __CYGWIN__ + /* Convert from Cygwin path to Windows path */ + if (convert) { + char *converted_file = cygwin_create_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, file); + if (converted_file) { + free(file); + file = converted_file; + } + } +#endif + if (i >= 0) { + /* Specified as <fname>,<index> */ + hicon = ExtractIcon(g_hInstance, file, i); + } + else { + /* Specified as just an .ico file */ hicon = (HICON) LoadImage(NULL, file, IMAGE_ICON, sx, sy, LR_LOADFROMFILE | flags); } + free(file); } return hicon; } @@ -585,7 +724,7 @@ winOverrideIcon(char *res_name, char *res_class, char *wmName) if (pref.icon[i].hicon) return pref.icon[i].hicon; - hicon = LoadImageComma(pref.icon[i].iconFile, 0, 0, LR_DEFAULTSIZE); + hicon = LoadImageComma(pref.icon[i].iconFile, pref.iconDirectory, 0, 0, LR_DEFAULTSIZE); if (hicon == NULL) ErrorF("winOverrideIcon: LoadImageComma(%s) failed\n", pref.icon[i].iconFile); @@ -635,11 +774,17 @@ winPrefsLoadPreferences(const char *path) "MENU rmenu {\n" " \"How to customize this menu\" EXEC \"xterm +tb -e man XWinrc\"\n" " \"Launch xterm\" EXEC xterm\n" - " \"Load .XWinrc\" RELOAD\n" + " SEPARATOR\n" + " FAQ EXEC \"cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html\"\n" + " \"User's Guide\" EXEC \"cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html\"\n" + " SEPARATOR\n" + " \"Reload .XWinrc\" RELOAD\n" " SEPARATOR\n" "}\n" "\n" "ROOTMENU rmenu\n"; path = "built-in default"; prefFile = fmemopen(defaultPrefs, strlen(defaultPrefs), "r"); + + } #endif @@ -670,7 +815,7 @@ LoadPreferences(void) char *home; char fname[PATH_MAX + NAME_MAX + 2]; char szDisplay[512]; - char *szEnvDisplay; + char *szEnvDisplay, *szEnvLogFile; int i, j; char param[PARAM_MAX + 1]; char *srcParam, *dstParam; @@ -718,6 +863,11 @@ LoadPreferences(void) putenv(szEnvDisplay); } + /* Setup XWINLOGFILE environment variable */ + szEnvLogFile = (char *) (malloc(strlen(g_pszLogFile) + strlen("XWINLOGFILE=") + 1)); + snprintf(szEnvLogFile, 512, "XWINLOGFILE=%s", g_pszLogFile); + putenv(szEnvLogFile); + /* Replace any "%display%" in menu commands with display string */ for (i = 0; i < pref.menuItems; i++) { for (j = 0; j < pref.menu[i].menuItems; j++) { |