src/video/x11/SDL_x11messagebox.c
changeset 6726 f2898757eaae
parent 6725 a7a99a9d419a
child 6758 2a218048b45f
     1.1 --- a/src/video/x11/SDL_x11messagebox.c	Fri Dec 07 20:28:52 2012 -0800
     1.2 +++ b/src/video/x11/SDL_x11messagebox.c	Sat Dec 08 15:33:14 2012 -0500
     1.3 @@ -26,9 +26,20 @@
     1.4  #include "SDL.h"
     1.5  #include "SDL_x11video.h"
     1.6  #include "SDL_x11dyn.h"
     1.7 +#include "SDL_assert.h"
     1.8  
     1.9  #include <locale.h>
    1.10  
    1.11 +
    1.12 +#define SDL_FORK_MESSAGEBOX 1
    1.13 +
    1.14 +#if SDL_FORK_MESSAGEBOX
    1.15 +#include <sys/types.h>
    1.16 +#include <sys/wait.h>
    1.17 +#include <unistd.h>
    1.18 +#include <errno.h>
    1.19 +#endif
    1.20 +
    1.21  #define MAX_BUTTONS             8       /* Maximum number of buttons supported */
    1.22  #define MAX_TEXT_LINES          32      /* Maximum number of text lines supported */
    1.23  #define MIN_BUTTON_WIDTH        64      /* Minimum button width */
    1.24 @@ -625,9 +636,8 @@
    1.25      return 0;
    1.26  }
    1.27  
    1.28 -/* Display an x11 message box. */
    1.29 -int
    1.30 -X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    1.31 +static int
    1.32 +X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    1.33  {
    1.34      int ret;
    1.35      SDL_MessageBoxDataX11 data;
    1.36 @@ -676,6 +686,61 @@
    1.37      return ret;
    1.38  }
    1.39  
    1.40 +/* Display an x11 message box. */
    1.41 +int
    1.42 +X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    1.43 +{
    1.44 +#if SDL_FORK_MESSAGEBOX
    1.45 +    /* Use a child process to protect against setlocale(). Annoying. */
    1.46 +    pid_t pid;
    1.47 +    int fds[2];
    1.48 +    int status = 0;
    1.49 +
    1.50 +    if (pipe(fds) == -1) {
    1.51 +        return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
    1.52 +    }
    1.53 +
    1.54 +    pid = fork();
    1.55 +    if (pid == -1) {  /* failed */
    1.56 +        close(fds[0]);
    1.57 +        close(fds[1]);
    1.58 +        return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
    1.59 +    } else if (pid == 0) {  /* we're the child */
    1.60 +        int exitcode = 0;
    1.61 +        close(fds[0]);
    1.62 +        status = X11_ShowMessageBoxImpl(messageboxdata, buttonid);
    1.63 +        if (write(fds[1], &status, sizeof (int)) != sizeof (int))
    1.64 +            exitcode = 1;
    1.65 +        else if (write(fds[1], buttonid, sizeof (int)) != sizeof (int))
    1.66 +            exitcode = 1;
    1.67 +        close(fds[1]);
    1.68 +        _exit(exitcode);  /* don't run atexit() stuff, static destructors, etc. */
    1.69 +    } else {  /* we're the parent */
    1.70 +        pid_t rc;
    1.71 +        close(fds[1]);
    1.72 +        do {
    1.73 +            rc = waitpid(pid, &status, 0);
    1.74 +        } while ((rc == -1) && (errno == EINTR));
    1.75 +
    1.76 +        SDL_assert(rc == pid);  /* not sure what to do if this fails. */
    1.77 +
    1.78 +        if ((rc == -1) || (!WIFEXITED(status)) || (WEXITSTATUS(status) != 0)) {
    1.79 +            SDL_SetError("msgbox child process failed");
    1.80 +            return -1;
    1.81 +        }
    1.82 +
    1.83 +        if (read(fds[0], &status, sizeof (int)) != sizeof (int))
    1.84 +            status = -1;
    1.85 +        else if (read(fds[0], buttonid, sizeof (int)) != sizeof (int))
    1.86 +            status = -1;
    1.87 +        close(fds[0]);
    1.88 +
    1.89 +        return status;
    1.90 +    }
    1.91 +#else
    1.92 +    return X11_ShowMessageBoxImpl(messageboxdata, buttonid);
    1.93 +#endif
    1.94 +}
    1.95  #endif /* SDL_VIDEO_DRIVER_X11 */
    1.96  
    1.97  /* vi: set ts=4 sw=4 expandtab: */