spawn.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /**
  2. * \file spawn.c
  3. *
  4. * \brief GIS Library - Handles process spawning.
  5. *
  6. * (C) 2001-2008 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author Glynn Clements
  12. *
  13. * \date 2004-2006
  14. */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <signal.h>
  19. #include <stdarg.h>
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <errno.h>
  23. #include <sys/types.h>
  24. #ifndef __MINGW32__
  25. #include <sys/wait.h>
  26. #endif
  27. #include <grass/config.h>
  28. #include <grass/gis.h>
  29. #include <grass/glocale.h>
  30. #include <grass/spawn.h>
  31. /** \def MAX_ARGS Maximum number of arguments */
  32. /** \def MAX_BINDINGS Maximum number of bindings */
  33. /** \def MAX_SIGNALS Maximum number of signals */
  34. /** \def MAX_REDIRECTS Maximum number of redirects */
  35. #define MAX_ARGS 256
  36. #define MAX_BINDINGS 256
  37. #define MAX_SIGNALS 32
  38. #define MAX_REDIRECTS 32
  39. /**
  40. * \brief Spawns a new process.
  41. *
  42. * A more useful alternative to G_system(), which takes the
  43. * arguments of <b>command</b> as parameters.
  44. *
  45. * \param[in] command command to execute
  46. * \return -1 on error
  47. * \return process status on success
  48. */
  49. #ifdef __MINGW32__
  50. int G_spawn(const char *command, ...)
  51. {
  52. va_list va;
  53. const char *args[MAX_ARGS];
  54. int num_args = 0;
  55. va_start(va, command);
  56. for (num_args = 0; num_args < MAX_ARGS;) {
  57. const char *arg = va_arg(va, const char *);
  58. args[num_args++] = arg;
  59. if (!arg)
  60. break;
  61. }
  62. va_end(va);
  63. if (num_args >= MAX_ARGS) {
  64. G_warning(_("Too many arguments"));
  65. return -1;
  66. }
  67. G_debug(3, "spawning '%s' ...", command);
  68. return _spawnvp(_P_WAIT, command, args);
  69. }
  70. #else
  71. int G_spawn(const char *command, ...)
  72. {
  73. va_list va;
  74. char *args[MAX_ARGS];
  75. int num_args = 0;
  76. struct sigaction act, intr, quit;
  77. sigset_t block, oldmask;
  78. int status = -1;
  79. pid_t pid;
  80. va_start(va, command);
  81. for (num_args = 0; num_args < MAX_ARGS;) {
  82. char *arg = va_arg(va, char *);
  83. args[num_args++] = arg;
  84. if (!arg)
  85. break;
  86. }
  87. va_end(va);
  88. if (num_args >= MAX_ARGS) {
  89. G_warning(_("Too many arguments"));
  90. return -1;
  91. }
  92. sigemptyset(&act.sa_mask);
  93. act.sa_flags = SA_RESTART;
  94. act.sa_handler = SIG_IGN;
  95. if (sigaction(SIGINT, &act, &intr) < 0)
  96. goto error_1;
  97. if (sigaction(SIGQUIT, &act, &quit) < 0)
  98. goto error_2;
  99. sigemptyset(&block);
  100. sigaddset(&block, SIGCHLD);
  101. if (sigprocmask(SIG_BLOCK, &block, &oldmask) < 0)
  102. goto error_3;
  103. G_debug(3, "forking '%s' ...", command);
  104. pid = fork();
  105. if (pid < 0) {
  106. G_warning(_("Unable to create a new process"));
  107. goto error_4;
  108. }
  109. if (pid == 0) {
  110. sigaction(SIGINT, &intr, NULL);
  111. sigaction(SIGQUIT, &quit, NULL);
  112. execvp(command, args);
  113. G_warning(_("Unable to execute command"));
  114. _exit(127);
  115. }
  116. else {
  117. pid_t n;
  118. do
  119. n = waitpid(pid, &status, 0);
  120. while (n == (pid_t) - 1 && errno == EINTR);
  121. if (n != pid)
  122. status = -1;
  123. }
  124. error_4:
  125. sigprocmask(SIG_SETMASK, &oldmask, NULL);
  126. error_3:
  127. sigaction(SIGQUIT, &quit, NULL);
  128. error_2:
  129. sigaction(SIGINT, &intr, NULL);
  130. error_1:
  131. return status;
  132. }
  133. #endif /*__MINGW32__*/
  134. struct redirect
  135. {
  136. int dst_fd;
  137. int src_fd;
  138. const char *file;
  139. int mode;
  140. };
  141. struct signal
  142. {
  143. int which;
  144. int action;
  145. int signum;
  146. int valid;
  147. #ifndef __MINGW32__
  148. struct sigaction old_act;
  149. sigset_t old_mask;
  150. #endif
  151. };
  152. struct binding
  153. {
  154. const char *var;
  155. const char *val;
  156. };
  157. struct spawn
  158. {
  159. const char *args[MAX_ARGS];
  160. int num_args;
  161. struct redirect redirects[MAX_REDIRECTS];
  162. int num_redirects;
  163. struct signal signals[MAX_SIGNALS];
  164. int num_signals;
  165. struct binding bindings[MAX_BINDINGS];
  166. int num_bindings;
  167. int background;
  168. const char *directory;
  169. };
  170. #ifdef __MINGW32__
  171. static void do_redirects(const struct redirect *redirects, int num_redirects)
  172. {
  173. if (num_redirects > 0)
  174. G_fatal_error
  175. ("G_spawn_ex: redirection not (yet) supported on Windows");
  176. }
  177. static void add_binding(const char **env, int *pnum, const struct binding *b)
  178. {
  179. char *str = G_malloc(strlen(b->var) + strlen(b->val) + 2);
  180. int n = *pnum;
  181. int i;
  182. sprintf(str, "%s=%s", b->var, b->val);
  183. for (i = 0; i < n; i++)
  184. if (G_strcasecmp(env[i], b->var) == 0) {
  185. env[i] = str;
  186. return;
  187. }
  188. env[n++] = str;
  189. *pnum = n;
  190. }
  191. static const char **do_bindings(const struct binding *bindings, int num_bindings)
  192. {
  193. const char **newenv;
  194. int i, n;
  195. for (i = 0; _environ[i]; i++)
  196. ;
  197. n = i;
  198. newenv = G_malloc((num_bindings + n + 1) * sizeof(char *));
  199. for (i = 0; i < n; i++)
  200. newenv[i] = _environ[i];
  201. for (i = 0; i < num_bindings; i++)
  202. add_binding(newenv, &n, &bindings[i]);
  203. return newenv;
  204. }
  205. static int do_spawn(const struct spawn *sp, const char *command)
  206. {
  207. const char **env;
  208. int status;
  209. do_redirects(sp->redirects, sp->num_redirects);
  210. env = do_bindings(sp->bindings, sp->num_bindings);
  211. status =
  212. spawnvpe(sp->background ? _P_NOWAIT : _P_WAIT, command, sp->args, env);
  213. if (!sp->background && status < 0)
  214. G_warning(_("Unable to execute command"));
  215. return status;
  216. }
  217. #else /* __MINGW32__ */
  218. static int undo_signals(const struct signal *signals, int num_signals, int which)
  219. {
  220. int error = 0;
  221. int i;
  222. for (i = num_signals - 1; i >= 0; i--) {
  223. const struct signal *s = &signals[i];
  224. if (s->which != which)
  225. continue;
  226. if (!s->valid)
  227. continue;
  228. switch (s->action) {
  229. case SSA_IGNORE:
  230. case SSA_DEFAULT:
  231. if (sigaction(s->signum, &s->old_act, NULL) < 0) {
  232. G_warning(_("G_spawn: unable to restore signal %d"),
  233. s->signum);
  234. error = 1;
  235. }
  236. break;
  237. case SSA_BLOCK:
  238. case SSA_UNBLOCK:
  239. if (sigprocmask(SIG_UNBLOCK, &s->old_mask, NULL) < 0) {
  240. G_warning(_("G_spawn: unable to restore signal %d"),
  241. s->signum);
  242. error = 1;
  243. }
  244. break;
  245. }
  246. }
  247. return !error;
  248. }
  249. static int do_signals(struct signal *signals, int num_signals, int which)
  250. {
  251. struct sigaction act;
  252. sigset_t mask;
  253. int error = 0;
  254. int i;
  255. sigemptyset(&act.sa_mask);
  256. act.sa_flags = SA_RESTART;
  257. for (i = 0; i < num_signals; i++) {
  258. struct signal *s = &signals[i];
  259. if (s->which != which)
  260. continue;
  261. switch (s->action) {
  262. case SSA_IGNORE:
  263. act.sa_handler = SIG_IGN;
  264. if (sigaction(s->signum, &act, &s->old_act) < 0) {
  265. G_warning(_("G_spawn: unable to reset signal %d"), s->signum);
  266. error = 1;
  267. }
  268. else
  269. s->valid = 1;
  270. break;
  271. case SSA_DEFAULT:
  272. act.sa_handler = SIG_DFL;
  273. if (sigaction(s->signum, &act, &s->old_act) < 0) {
  274. G_warning(_("G_spawn: unable to ignore signal %d"),
  275. s->signum);
  276. error = 1;
  277. }
  278. else
  279. s->valid = 1;
  280. break;
  281. case SSA_BLOCK:
  282. sigemptyset(&mask);
  283. sigaddset(&mask, s->signum);
  284. if (sigprocmask(SIG_BLOCK, &mask, &s->old_mask) < 0) {
  285. G_warning(_("G_spawn: unable to block signal %d"), s->signum);
  286. error = 1;
  287. }
  288. break;
  289. case SSA_UNBLOCK:
  290. sigemptyset(&mask);
  291. sigaddset(&mask, s->signum);
  292. if (sigprocmask(SIG_UNBLOCK, &mask, &s->old_mask) < 0) {
  293. G_warning(_("G_spawn: unable to unblock signal %d"),
  294. s->signum);
  295. error = 1;
  296. }
  297. else
  298. s->valid = 1;
  299. break;
  300. }
  301. }
  302. return !error;
  303. }
  304. static void do_redirects(struct redirect *redirects, int num_redirects)
  305. {
  306. int i;
  307. for (i = 0; i < num_redirects; i++) {
  308. struct redirect *r = &redirects[i];
  309. if (r->file) {
  310. r->src_fd = open(r->file, r->mode, 0666);
  311. if (r->src_fd < 0) {
  312. G_warning(_("G_spawn: unable to open file %s"), r->file);
  313. _exit(127);
  314. }
  315. if (dup2(r->src_fd, r->dst_fd) < 0) {
  316. G_warning(_("G_spawn: unable to duplicate descriptor %d to %d"),
  317. r->src_fd, r->dst_fd);
  318. _exit(127);
  319. }
  320. close(r->src_fd);
  321. }
  322. else if (r->src_fd >= 0) {
  323. if (dup2(r->src_fd, r->dst_fd) < 0) {
  324. G_warning(_("G_spawn: unable to duplicate descriptor %d to %d"),
  325. r->src_fd, r->dst_fd);
  326. _exit(127);
  327. }
  328. }
  329. else
  330. close(r->dst_fd);
  331. }
  332. }
  333. static void do_bindings(const struct binding *bindings, int num_bindings)
  334. {
  335. int i;
  336. for (i = 0; i < num_bindings; i++) {
  337. const struct binding *b = &bindings[i];
  338. char *str = G_malloc(strlen(b->var) + strlen(b->val) + 2);
  339. sprintf(str, "%s=%s", b->var, b->val);
  340. putenv(str);
  341. }
  342. }
  343. static int do_spawn(struct spawn *sp, const char *command)
  344. {
  345. int status = -1;
  346. pid_t pid;
  347. if (!do_signals(sp->signals, sp->num_signals, SST_PRE))
  348. return status;
  349. pid = fork();
  350. if (pid < 0) {
  351. G_warning(_("Unable to create a new process"));
  352. undo_signals(sp->signals, sp->num_signals, SST_PRE);
  353. return status;
  354. }
  355. if (pid == 0) {
  356. if (!undo_signals(sp->signals, sp->num_signals, SST_PRE))
  357. _exit(127);
  358. if (!do_signals(sp->signals, sp->num_signals, SST_CHILD))
  359. _exit(127);
  360. if (sp->directory)
  361. if (chdir(sp->directory) < 0) {
  362. G_warning(_("Unable to change directory to %s"), sp->directory);
  363. _exit(127);
  364. }
  365. do_redirects(sp->redirects, sp->num_redirects);
  366. do_bindings(sp->bindings, sp->num_bindings);
  367. execvp(command, (char **)sp->args);
  368. G_warning(_("Unable to execute command"));
  369. _exit(127);
  370. }
  371. do_signals(sp->signals, sp->num_signals, SST_POST);
  372. if (sp->background)
  373. status = (int)pid;
  374. else {
  375. pid_t n;
  376. do
  377. n = waitpid(pid, &status, 0);
  378. while (n == (pid_t) - 1 && errno == EINTR);
  379. if (n != pid)
  380. status = -1;
  381. }
  382. undo_signals(sp->signals, sp->num_signals, SST_POST);
  383. undo_signals(sp->signals, sp->num_signals, SST_PRE);
  384. return status;
  385. }
  386. #endif /* __MINGW32__ */
  387. static void begin_spawn(struct spawn *sp)
  388. {
  389. sp->num_args = 0;
  390. sp->num_redirects = 0;
  391. sp->num_signals = 0;
  392. sp->num_bindings = 0;
  393. sp->background = 0;
  394. sp->directory = NULL;
  395. }
  396. #define NEXT_ARG(var, type) ((type) *(var)++)
  397. static void parse_argvec(struct spawn *sp, const char **va)
  398. {
  399. for (;;) {
  400. const char *arg = NEXT_ARG(va, const char *);
  401. const char *var, *val;
  402. switch ((int)arg) {
  403. case 0:
  404. sp->args[sp->num_args++] = NULL;
  405. break;
  406. case ((int)SF_REDIRECT_FILE):
  407. sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
  408. sp->redirects[sp->num_redirects].src_fd = -1;
  409. sp->redirects[sp->num_redirects].mode = NEXT_ARG(va, int);
  410. sp->redirects[sp->num_redirects].file = NEXT_ARG(va, const char *);
  411. sp->num_redirects++;
  412. break;
  413. case ((int)SF_REDIRECT_DESCRIPTOR):
  414. sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
  415. sp->redirects[sp->num_redirects].src_fd = NEXT_ARG(va, int);
  416. sp->redirects[sp->num_redirects].file = NULL;
  417. sp->num_redirects++;
  418. break;
  419. case ((int)SF_CLOSE_DESCRIPTOR):
  420. sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
  421. sp->redirects[sp->num_redirects].src_fd = -1;
  422. sp->redirects[sp->num_redirects].file = NULL;
  423. sp->num_redirects++;
  424. break;
  425. case ((int)SF_SIGNAL):
  426. sp->signals[sp->num_signals].which = NEXT_ARG(va, int);
  427. sp->signals[sp->num_signals].action = NEXT_ARG(va, int);
  428. sp->signals[sp->num_signals].signum = NEXT_ARG(va, int);
  429. sp->signals[sp->num_signals].valid = 0;
  430. sp->num_signals++;
  431. break;
  432. case ((int)SF_VARIABLE):
  433. var = NEXT_ARG(va, const char *);
  434. val = getenv(var);
  435. sp->args[sp->num_args++] = val ? val : "";
  436. break;
  437. case ((int)SF_BINDING):
  438. sp->bindings[sp->num_bindings].var = NEXT_ARG(va, const char *);
  439. sp->bindings[sp->num_bindings].val = NEXT_ARG(va, const char *);
  440. sp->num_bindings++;
  441. break;
  442. case ((int)SF_BACKGROUND):
  443. sp->background = 1;
  444. break;
  445. case ((int)SF_DIRECTORY):
  446. sp->directory = NEXT_ARG(va, const char *);
  447. break;
  448. case ((int)SF_ARGVEC):
  449. parse_argvec(sp, NEXT_ARG(va, const char **));
  450. break;
  451. default:
  452. sp->args[sp->num_args++] = arg;
  453. break;
  454. }
  455. if (!arg)
  456. break;
  457. }
  458. }
  459. static void parse_arglist(struct spawn *sp, va_list va)
  460. {
  461. for (;;) {
  462. const char *arg = va_arg(va, const char *);
  463. const char *var, *val;
  464. switch ((int)arg) {
  465. case 0:
  466. sp->args[sp->num_args++] = NULL;
  467. break;
  468. case ((int)SF_REDIRECT_FILE):
  469. sp->redirects[sp->num_redirects].dst_fd = va_arg(va, int);
  470. sp->redirects[sp->num_redirects].src_fd = -1;
  471. sp->redirects[sp->num_redirects].mode = va_arg(va, int);
  472. sp->redirects[sp->num_redirects].file = va_arg(va, const char *);
  473. sp->num_redirects++;
  474. break;
  475. case ((int)SF_REDIRECT_DESCRIPTOR):
  476. sp->redirects[sp->num_redirects].dst_fd = va_arg(va, int);
  477. sp->redirects[sp->num_redirects].src_fd = va_arg(va, int);
  478. sp->redirects[sp->num_redirects].file = NULL;
  479. sp->num_redirects++;
  480. break;
  481. case ((int)SF_CLOSE_DESCRIPTOR):
  482. sp->redirects[sp->num_redirects].dst_fd = va_arg(va, int);
  483. sp->redirects[sp->num_redirects].src_fd = -1;
  484. sp->redirects[sp->num_redirects].file = NULL;
  485. sp->num_redirects++;
  486. break;
  487. case ((int)SF_SIGNAL):
  488. sp->signals[sp->num_signals].which = va_arg(va, int);
  489. sp->signals[sp->num_signals].action = va_arg(va, int);
  490. sp->signals[sp->num_signals].signum = va_arg(va, int);
  491. sp->signals[sp->num_signals].valid = 0;
  492. sp->num_signals++;
  493. break;
  494. case ((int)SF_VARIABLE):
  495. var = va_arg(va, char *);
  496. val = getenv(var);
  497. sp->args[sp->num_args++] = val ? val : "";
  498. break;
  499. case ((int)SF_BINDING):
  500. sp->bindings[sp->num_bindings].var = va_arg(va, const char *);
  501. sp->bindings[sp->num_bindings].val = va_arg(va, const char *);
  502. sp->num_bindings++;
  503. break;
  504. case ((int)SF_BACKGROUND):
  505. sp->background = 1;
  506. break;
  507. case ((int)SF_DIRECTORY):
  508. sp->directory = va_arg(va, const char *);
  509. break;
  510. case ((int)SF_ARGVEC):
  511. parse_argvec(sp, va_arg(va, const char **));
  512. break;
  513. default:
  514. sp->args[sp->num_args++] = arg;
  515. break;
  516. }
  517. if (!arg)
  518. break;
  519. }
  520. }
  521. /**
  522. * \brief Spawn new process based on <b>command</b>.
  523. *
  524. * This is a more advanced version of G_spawn().
  525. *
  526. * \param[in] command
  527. * \param[in] args arguments
  528. * \return -1 on error
  529. * \return process status on success
  530. */
  531. int G_vspawn_ex(const char *command, const char **args)
  532. {
  533. struct spawn sp;
  534. begin_spawn(&sp);
  535. parse_argvec(&sp, args);
  536. return do_spawn(&sp, command);
  537. }
  538. /**
  539. * \brief Spawn new process based on <b>command</b>.
  540. *
  541. * This is a more advanced version of G_spawn().
  542. *
  543. * \param[in] command
  544. * \return -1 on error
  545. * \return process status on success
  546. */
  547. int G_spawn_ex(const char *command, ...)
  548. {
  549. struct spawn sp;
  550. va_list va;
  551. begin_spawn(&sp);
  552. va_start(va, command);
  553. parse_arglist(&sp, va);
  554. va_end(va);
  555. return do_spawn(&sp, command);
  556. }