|
2 | 2 | #include "config_ac.h"
|
3 | 3 | #endif
|
4 | 4 |
|
| 5 | +#include "env.h" |
5 | 6 | #include "log.h"
|
6 | 7 | #include "os_calls.h"
|
7 | 8 | #include "string_calls.h"
|
8 | 9 | #include "xwait.h"
|
9 | 10 |
|
10 | 11 | #include <stdio.h>
|
11 | 12 | #include <string.h>
|
12 |
| -#include <sys/wait.h> |
13 | 13 |
|
14 | 14 | /******************************************************************************/
|
15 |
| -enum xwait_status |
16 |
| -wait_for_xserver(int display) |
| 15 | +static void |
| 16 | +log_waitforx_messages(FILE *dp) |
17 | 17 | {
|
18 |
| - FILE *dp = NULL; |
19 |
| - enum xwait_status rv = XW_STATUS_MISC_ERROR; |
20 |
| - int ret; |
21 |
| - |
22 |
| - char buffer[100]; |
23 |
| - const char exe[] = XRDP_LIBEXEC_PATH "/waitforx"; |
24 |
| - char cmd[sizeof(exe) + 64]; |
25 |
| - |
26 |
| - if (!g_file_exist(exe)) |
27 |
| - { |
28 |
| - LOG(LOG_LEVEL_ERROR, "Unable to find %s", exe); |
29 |
| - return rv; |
30 |
| - } |
31 |
| - |
32 |
| - g_snprintf(cmd, sizeof(cmd), "%s -d :%d", exe, display); |
33 |
| - LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display :%d", |
34 |
| - display); |
35 |
| - |
36 |
| - dp = popen(cmd, "r"); |
37 |
| - if (dp == NULL) |
38 |
| - { |
39 |
| - LOG(LOG_LEVEL_ERROR, "Unable to launch waitforx"); |
40 |
| - return rv; |
41 |
| - } |
42 |
| - |
43 |
| - while (fgets(buffer, 100, dp)) |
| 18 | + char buffer[256]; |
| 19 | + while (fgets(buffer, sizeof(buffer), dp)) |
44 | 20 | {
|
45 | 21 | const char *msg = buffer;
|
46 | 22 | enum logLevels level = LOG_LEVEL_ERROR;
|
@@ -73,18 +49,136 @@ wait_for_xserver(int display)
|
73 | 49 | LOG(level, "waitforx: %s", msg);
|
74 | 50 | }
|
75 | 51 | }
|
| 52 | +} |
| 53 | + |
| 54 | +/******************************************************************************/ |
| 55 | +/** |
| 56 | + * Contruct the command to run to check the X server |
| 57 | + */ |
| 58 | +static struct list * |
| 59 | +make_xwait_command(int display) |
| 60 | +{ |
| 61 | + const char exe[] = XRDP_LIBEXEC_PATH "/waitforx"; |
| 62 | + char displaystr[64]; |
| 63 | + |
| 64 | + struct list *cmd = list_create(); |
| 65 | + if (cmd != NULL) |
| 66 | + { |
| 67 | + cmd->auto_free = 1; |
| 68 | + g_snprintf(displaystr, sizeof(displaystr), ":%d", display); |
| 69 | + |
| 70 | + if (!list_add_strdup_multi(cmd, exe, "-d", displaystr, NULL)) |
| 71 | + { |
| 72 | + list_delete(cmd); |
| 73 | + cmd = NULL; |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + return cmd; |
| 78 | +} |
| 79 | + |
| 80 | +/******************************************************************************/ |
| 81 | +enum xwait_status |
| 82 | +wait_for_xserver(uid_t uid, |
| 83 | + struct list *env_names, |
| 84 | + struct list *env_values, |
| 85 | + int display) |
| 86 | +{ |
| 87 | + enum xwait_status rv = XW_STATUS_MISC_ERROR; |
| 88 | + int fd[2] = {-1, -1}; |
| 89 | + struct list *cmd = make_xwait_command(display); |
76 | 90 |
|
77 |
| - ret = pclose(dp); |
78 |
| - if (WIFEXITED(ret)) |
| 91 | + |
| 92 | + // Construct the command to execute to check the display |
| 93 | + if (cmd == NULL) |
79 | 94 | {
|
80 |
| - rv = (enum xwait_status)WEXITSTATUS(ret); |
| 95 | + LOG(LOG_LEVEL_ERROR, "Can't create xwait command list - no mem"); |
81 | 96 | }
|
82 |
| - else if (WIFSIGNALED(ret)) |
| 97 | + else if (g_pipe(fd) != 0) |
83 | 98 | {
|
84 |
| - int sig = WTERMSIG(ret); |
85 |
| - LOG(LOG_LEVEL_ERROR, "waitforx failed with unexpected signal %d", |
86 |
| - sig); |
| 99 | + LOG(LOG_LEVEL_ERROR, "Can't create pipe : %s", g_get_strerror()); |
| 100 | + } |
| 101 | + else |
| 102 | + { |
| 103 | + pid_t pid = g_fork(); |
| 104 | + if (pid < 0) |
| 105 | + { |
| 106 | + LOG(LOG_LEVEL_ERROR, "Can't create pipe : %s", |
| 107 | + g_get_strerror()); |
| 108 | + } |
| 109 | + else if (pid == 0) |
| 110 | + { |
| 111 | + /* Child process */ |
| 112 | + |
| 113 | + /* Send stdout and stderr up the pipe */ |
| 114 | + g_file_close(fd[0]); |
| 115 | + g_file_duplicate_on(fd[1], 1); |
| 116 | + g_file_duplicate_on(fd[1], 2); |
| 117 | + |
| 118 | + /* Move to the user context... */ |
| 119 | + env_set_user(uid, |
| 120 | + 0, |
| 121 | + display, |
| 122 | + env_names, |
| 123 | + env_values); |
| 124 | + |
| 125 | + /* ...and run the program */ |
| 126 | + g_execvp_list((const char *)cmd->items[0], cmd); |
| 127 | + LOG(LOG_LEVEL_ERROR, "Can't run %s - %s", |
| 128 | + (const char *)cmd->items[0], g_get_strerror()); |
| 129 | + g_exit(rv); |
| 130 | + } |
| 131 | + else |
| 132 | + { |
| 133 | + LOG(LOG_LEVEL_DEBUG, |
| 134 | + "Waiting for X server to start on display :%d", |
| 135 | + display); |
| 136 | + |
| 137 | + g_file_close(fd[1]); |
| 138 | + fd[1] = -1; |
| 139 | + FILE *dp = fdopen(fd[0], "r"); |
| 140 | + if (dp == NULL) |
| 141 | + { |
| 142 | + LOG(LOG_LEVEL_ERROR, "Unable to launch waitforx"); |
| 143 | + } |
| 144 | + else |
| 145 | + { |
| 146 | + struct exit_status e; |
| 147 | + |
| 148 | + fd[0] = -1; // File descriptor closed by fclose() |
| 149 | + log_waitforx_messages(dp); |
| 150 | + fclose(dp); |
| 151 | + e = g_waitpid_status(pid); |
| 152 | + switch (e.reason) |
| 153 | + { |
| 154 | + case E_XR_STATUS_CODE: |
| 155 | + rv = (enum xwait_status)e.val; |
| 156 | + break; |
| 157 | + |
| 158 | + case E_XR_SIGNAL: |
| 159 | + LOG(LOG_LEVEL_ERROR, |
| 160 | + "waitforx failed with unexpected signal %d", |
| 161 | + e.val); |
| 162 | + break; |
| 163 | + |
| 164 | + default: |
| 165 | + LOG(LOG_LEVEL_ERROR, |
| 166 | + "waitforx failed with unknown reason"); |
| 167 | + } |
| 168 | + } |
| 169 | + } |
| 170 | + if (fd[0] >= 0) |
| 171 | + { |
| 172 | + g_file_close(fd[0]); |
| 173 | + } |
| 174 | + |
| 175 | + if (fd[1] >= 0) |
| 176 | + { |
| 177 | + g_file_close(fd[1]); |
| 178 | + } |
87 | 179 | }
|
88 | 180 |
|
| 181 | + list_delete(cmd); |
| 182 | + |
89 | 183 | return rv;
|
90 | 184 | }
|
0 commit comments