11 |
|
|
12 |
static void kill_helper(void) |
static void kill_helper(void) |
13 |
{ |
{ |
14 |
// TODO!!!: is there more elegant way to terminate child on program failure? |
if (G.helper_pid > 0) { |
|
if (G.helper_pid > 0) |
|
15 |
kill(G.helper_pid, SIGTERM); |
kill(G.helper_pid, SIGTERM); |
16 |
|
G.helper_pid = 0; |
17 |
|
} |
18 |
} |
} |
19 |
|
|
20 |
// generic signal handler |
// generic signal handler |
27 |
} |
} |
28 |
|
|
29 |
// SIGCHLD. reap zombies |
// SIGCHLD. reap zombies |
30 |
if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) |
if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) { |
31 |
|
if (WIFSIGNALED(err)) |
32 |
|
bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err)); |
33 |
if (WIFEXITED(err)) { |
if (WIFEXITED(err)) { |
34 |
G.helper_pid = 0; |
G.helper_pid = 0; |
35 |
if (WEXITSTATUS(err)) |
if (WEXITSTATUS(err)) |
36 |
bb_error_msg_and_die("child exited (%d)", WEXITSTATUS(err)); |
bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err)); |
37 |
} |
} |
38 |
|
} |
39 |
#undef err |
#undef err |
40 |
} |
} |
41 |
|
|
42 |
void FAST_FUNC launch_helper(const char **argv) |
void FAST_FUNC launch_helper(const char **argv) |
43 |
{ |
{ |
44 |
// setup vanilla unidirectional pipes interchange |
// setup vanilla unidirectional pipes interchange |
45 |
int idx; |
int i; |
46 |
int pipes[4]; |
int pipes[4]; |
47 |
|
|
48 |
xpipe(pipes); |
xpipe(pipes); |
49 |
xpipe(pipes+2); |
xpipe(pipes + 2); |
50 |
|
|
51 |
|
// NB: handler must be installed before vfork |
52 |
|
bb_signals(0 |
53 |
|
+ (1 << SIGCHLD) |
54 |
|
+ (1 << SIGALRM) |
55 |
|
, signal_handler); |
56 |
|
|
57 |
G.helper_pid = vfork(); |
G.helper_pid = vfork(); |
58 |
if (G.helper_pid < 0) |
if (G.helper_pid < 0) |
59 |
bb_perror_msg_and_die("vfork"); |
bb_perror_msg_and_die("vfork"); |
60 |
idx = (!G.helper_pid) * 2; |
|
61 |
xdup2(pipes[idx], STDIN_FILENO); |
i = (!G.helper_pid) * 2; // for parent:0, for child:2 |
62 |
xdup2(pipes[3-idx], STDOUT_FILENO); |
close(pipes[i + 1]); // 1 or 3 - closing one write end |
63 |
if (ENABLE_FEATURE_CLEAN_UP) |
close(pipes[2 - i]); // 2 or 0 - closing one read end |
64 |
for (int i = 4; --i >= 0; ) |
xmove_fd(pipes[i], STDIN_FILENO); // 0 or 2 - using other read end |
65 |
if (pipes[i] > STDOUT_FILENO) |
xmove_fd(pipes[3 - i], STDOUT_FILENO); // 3 or 1 - other write end |
66 |
close(pipes[i]); |
|
67 |
if (!G.helper_pid) { |
if (!G.helper_pid) { |
68 |
// child: try to execute connection helper |
// child: try to execute connection helper |
69 |
|
// NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec |
70 |
BB_EXECVP(*argv, (char **)argv); |
BB_EXECVP(*argv, (char **)argv); |
71 |
_exit(127); |
_exit(127); |
72 |
} |
} |
73 |
// parent: check whether child is alive |
|
74 |
bb_signals(0 |
// parent |
75 |
+ (1 << SIGCHLD) |
// check whether child is alive |
76 |
+ (1 << SIGALRM) |
//redundant:signal_handler(SIGCHLD); |
|
, signal_handler); |
|
|
signal_handler(SIGCHLD); |
|
77 |
// child seems OK -> parent goes on |
// child seems OK -> parent goes on |
78 |
atexit(kill_helper); |
atexit(kill_helper); |
79 |
} |
} |
87 |
msg = xasprintf(fmt, param); |
msg = xasprintf(fmt, param); |
88 |
printf("%s\r\n", msg); |
printf("%s\r\n", msg); |
89 |
} |
} |
90 |
fflush(stdout); |
fflush_all(); |
91 |
return msg; |
return msg; |
92 |
} |
} |
93 |
|
|
236 |
*/ |
*/ |
237 |
void FAST_FUNC get_cred_or_die(int fd) |
void FAST_FUNC get_cred_or_die(int fd) |
238 |
{ |
{ |
|
// either from TTY |
|
239 |
if (isatty(fd)) { |
if (isatty(fd)) { |
240 |
G.user = xstrdup(bb_askpass(0, "User: ")); |
G.user = xstrdup(bb_ask(fd, /* timeout: */ 0, "User: ")); |
241 |
G.pass = xstrdup(bb_askpass(0, "Password: ")); |
G.pass = xstrdup(bb_ask(fd, /* timeout: */ 0, "Password: ")); |
|
// or from STDIN |
|
242 |
} else { |
} else { |
243 |
FILE *fp = fdopen(fd, "r"); |
G.user = xmalloc_reads(fd, /* pfx: */ NULL, /* maxsize: */ NULL); |
244 |
G.user = xmalloc_fgetline(fp); |
G.pass = xmalloc_reads(fd, /* pfx: */ NULL, /* maxsize: */ NULL); |
|
G.pass = xmalloc_fgetline(fp); |
|
|
fclose(fp); |
|
245 |
} |
} |
246 |
if (!G.user || !*G.user || !G.pass || !*G.pass) |
if (!G.user || !*G.user || !G.pass) |
247 |
bb_error_msg_and_die("no username or password"); |
bb_error_msg_and_die("no username or password"); |
248 |
} |
} |