Skip to content

Commit 1fe5b8f

Browse files
committed
xwait changes (breaks compile)
The wait_for_xserver() call is refactored so that it can be called from root context to wait for an X server run by a specific user.
1 parent 70ebb77 commit 1fe5b8f

File tree

2 files changed

+139
-37
lines changed

2 files changed

+139
-37
lines changed

sesman/xwait.c

+130-36
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,21 @@
22
#include "config_ac.h"
33
#endif
44

5+
#include "env.h"
56
#include "log.h"
67
#include "os_calls.h"
78
#include "string_calls.h"
89
#include "xwait.h"
910

1011
#include <stdio.h>
1112
#include <string.h>
12-
#include <sys/wait.h>
1313

1414
/******************************************************************************/
15-
enum xwait_status
16-
wait_for_xserver(int display)
15+
static void
16+
log_waitforx_messages(FILE *dp)
1717
{
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))
4420
{
4521
const char *msg = buffer;
4622
enum logLevels level = LOG_LEVEL_ERROR;
@@ -73,18 +49,136 @@ wait_for_xserver(int display)
7349
LOG(level, "waitforx: %s", msg);
7450
}
7551
}
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);
7690

77-
ret = pclose(dp);
78-
if (WIFEXITED(ret))
91+
92+
// Construct the command to execute to check the display
93+
if (cmd == NULL)
7994
{
80-
rv = (enum xwait_status)WEXITSTATUS(ret);
95+
LOG(LOG_LEVEL_ERROR, "Can't create xwait command list - no mem");
8196
}
82-
else if (WIFSIGNALED(ret))
97+
else if (g_pipe(fd) != 0)
8398
{
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+
}
87179
}
88180

181+
list_delete(cmd);
182+
89183
return rv;
90184
}

sesman/xwait.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef XWAIT_H
22
#define XWAIT_H
33

4+
#include <sys/types.h>
5+
46
enum xwait_status
57
{
68
XW_STATUS_OK = 0,
@@ -12,10 +14,16 @@ enum xwait_status
1214
/**
1315
*
1416
* @brief waits for X to start
17+
* @param uid User to run program under
18+
* @param env_names Environment to set for user (names)
19+
* @param env_values Environment to set for user (values)
1520
* @param display number
1621
* @return status
1722
*
1823
*/
1924
enum xwait_status
20-
wait_for_xserver(int display);
25+
wait_for_xserver(uid_t uid,
26+
struct list *env_names,
27+
struct list *env_values,
28+
int display);
2129
#endif

0 commit comments

Comments
 (0)