Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_spawn.c
Go to the documentation of this file.
1
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <time.h>
23#include <unistd.h>
24
25#include "nilorea/n_common.h"
26#include "nilorea/n_log.h"
27
28int main(void) {
29 char dir[256];
30 char target[512];
31 int failures = 0;
32 int i = 0;
33
35#if defined(__windows__)
36 n_log(LOG_NOTICE, "ex_spawn: the detached start is checked on POSIX; nothing to do here");
37 return 0;
38#else
39 snprintf(dir, sizeof(dir), "%s/ex_spawn_%d", getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp",
40 (int)getpid());
41 snprintf(target, sizeof(target), "%s/a file; with \"quotes\" and $HOME", dir);
42 {
43 /* The script writes "ok" into the file named by its first argument. */
44 const char* args[] = {"-c", "echo ok > \"$1\"", "ex_spawn", target, NULL};
45 char mk[300];
46
47 snprintf(mk, sizeof(mk), "mkdir -p '%s'", dir);
48 if (system(mk) != 0) {
49 n_log(LOG_ERR, "ex_spawn: cannot make %s", dir);
50 return 1;
51 }
52 if (n_spawn_detached("sh", args) != TRUE) {
53 n_log(LOG_ERR, "ex_spawn: sh could not be started");
54 failures++;
55 }
56 }
57 /* Detached: nothing to wait on, so the file is looked for. */
58 for (i = 0; i < 100 && !file_exist(target); i++)
59 usleep(20000);
60 if (file_exist(target)) {
61 n_log(LOG_NOTICE, "ex_spawn: the argument arrived whole");
62 } else {
63 n_log(LOG_ERR, "ex_spawn: no file named %s appeared", target);
64 failures++;
65 }
66 unlink(target);
67 rmdir(dir);
68
69 {
70 const char* none[] = {NULL};
71
72 /* Not found: the child reports it and exits 127; the call itself
73 * started it, so it is not an error here, and nothing is left. */
74 n_spawn_detached("ex-spawn-no-such-program", none);
75 }
76 if (n_spawn_detached(NULL, NULL) != FALSE) {
77 n_log(LOG_ERR, "ex_spawn: a NULL program was accepted");
78 failures++;
79 }
80
81 /* The waiting form: the exit code comes back, and the file the program
82 * wrote is there the moment the call returns, with no polling. */
83 {
84 const char* write_it[] = {"-c", "echo ok > \"$1\"; exit 3", "ex_spawn", target, NULL};
85 const char* none[] = {NULL};
86 char mk[300];
87 int code = 0;
88
89 snprintf(mk, sizeof(mk), "mkdir -p '%s'", dir);
90 if (system(mk) != 0) {
91 n_log(LOG_ERR, "ex_spawn: cannot make %s", dir);
92 return 1;
93 }
94 if (n_spawn_wait("sh", write_it, &code) != FALSE || code != 3) {
95 n_log(LOG_ERR, "ex_spawn: an exit code of 3 came back as %d", code);
96 failures++;
97 }
98 if (!file_exist(target)) {
99 n_log(LOG_ERR, "ex_spawn: the waited for program's file is not there on return");
100 failures++;
101 }
102 unlink(target);
103 rmdir(dir);
104 if (n_spawn_wait("true", none, &code) != TRUE || code != 0) {
105 n_log(LOG_ERR, "ex_spawn: true did not succeed (%d)", code);
106 failures++;
107 }
108 if (n_spawn_wait("ex-spawn-no-such-program", none, &code) != FALSE || code != 127) {
109 n_log(LOG_ERR, "ex_spawn: a missing program came back as %d, not 127", code);
110 failures++;
111 }
112 if (n_spawn_wait(NULL, NULL, &code) != FALSE) {
113 n_log(LOG_ERR, "ex_spawn: a NULL program was accepted by n_spawn_wait");
114 failures++;
115 }
116 }
117
118 /* The stoppable form. A flag left down waits as n_spawn_wait() does; a
119 * flag raised ends a program that would otherwise run for half a
120 * minute, and the call returns within the two seconds of grace. */
121 {
122 const char* none[] = {NULL};
123 const char* long_one[] = {"30", NULL};
124 volatile int stop = 0;
125 int code = 0;
126 time_t started = 0;
127
128 if (n_spawn_wait_cancel("true", none, &code, &stop) != TRUE || code != 0) {
129 n_log(LOG_ERR, "ex_spawn: true with a lowered flag did not succeed (%d)", code);
130 failures++;
131 }
132 stop = 1;
133 started = time(NULL);
134 if (n_spawn_wait_cancel("sleep", long_one, &code, &stop) != FALSE) {
135 n_log(LOG_ERR, "ex_spawn: a stopped program reported success");
136 failures++;
137 }
138 if (time(NULL) - started > 5) {
139 n_log(LOG_ERR, "ex_spawn: the stop took %ld seconds", (long)(time(NULL) - started));
140 failures++;
141 }
142 }
143 n_log(LOG_NOTICE, "ex_spawn: %s", failures ? "FAILED" : "ok");
144 return failures ? 1 : 0;
145#endif
146}
static int failures
Definition ex_atlas.c:51
int main(void)
Definition ex_atlas.c:117
static void stop(int sig)
Definition ex_kafka.c:75
int n_spawn_wait(const char *program, const char *const *args, int *exit_code)
Run a program with arguments and wait for it to finish.
Definition n_common.c:369
int n_spawn_detached(const char *program, const char *const *args)
Start a program and do not wait for it.
Definition n_common.c:292
int n_spawn_wait_cancel(const char *program, const char *const *args, int *exit_code, const volatile int *cancel)
Run a program and wait for it, ending it early when asked.
Definition n_common.c:373
int file_exist(const char *filename)
test if file exist and if it's readable
Definition n_common.c:104
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:104
Common headers and low-level functions & define.
Generic log system.