44#define MAX_BINDINGS 256
46#define MAX_REDIRECTS 32
92 const char *directory;
95static void parse_arglist(
struct spawn *
sp,
va_list va);
96static void parse_argvec(
struct spawn *
sp,
const char **
va);
108static void clear(
struct buffer *
b)
111 b->str[
b->len] =
'\0';
114static void init(
struct buffer *
b)
121static char *
release(
struct buffer *
b)
132static void finish(
struct buffer *
b)
139static void ensure(
struct buffer *
b,
size_t n)
141 if (
b->size <=
b->len + n + 1) {
147static void append(
struct buffer *
b,
const char *str)
154 b->str[
b->len] =
'\0';
157static void append_char(
struct buffer *
b,
char c)
162 b->str[
b->len] =
'\0';
165static void escape_arg(
struct buffer *result,
const char *
arg)
175 append_char(result,
'\"');
177 for (
j = 0;
arg[
j];
j++) {
183 append_char(&buf,
'\\');
186 for (k = 0; k < buf.len; k++)
196 append_char(result, c);
205 append_char(result,
'\"');
211static char *
check_program(
const char *
pgm,
const char *dir,
const char *ext)
251 for (i = 0;
path[i]; i++) {
252 const char *dir =
path[i];
275 struct buffer result;
284 append(&result,
" /c \"");
290 append_char(&result,
' ');
301 struct buffer result;
306 for (i = 0;
envp[i]; i++) {
307 const char *env =
envp[i];
310 append_char(&result,
'\0');
354 G_debug(3,
"win_spawn: args = %s", args);
387 for (i = 0; i < 3; i++)
401 return pi.dwProcessId;
404static void do_redirects(
struct redirect *redirects,
int num_redirects,
409 for (i = 0; i < 3; i++)
412 for (i = 0; i < num_redirects; i++) {
413 struct redirect *
r = &redirects[i];
415 if (
r->dst_fd < 0 ||
r->dst_fd > 2) {
416 if (
r->file ||
r->src_fd >= 0)
417 G_warning(
_(
"G_spawn: unable to redirect descriptor %d"),
423 r->src_fd =
open(
r->file,
r->mode, 0666);
426 G_warning(
_(
"G_spawn: unable to open file %s"),
r->file);
434 else if (
r->src_fd >= 0) {
447static void add_binding(
const char **env,
int *
pnum,
const struct binding *
b)
454 snprintf(str, bufsize,
"%s=%s",
b->var,
b->val);
456 for (i = 0; i < n; i++)
466static const char **do_bindings(
const struct binding *bindings,
478 for (i = 0; i < n; i++)
481 for (i = 0; i < num_bindings; i++)
489static int do_spawn(
struct spawn *
sp,
const char *command)
495 do_redirects(
sp->redirects,
sp->num_redirects,
handles);
496 env = do_bindings(
sp->bindings,
sp->num_bindings);
501 if (!
sp->background && status < 0)
502 G_warning(
_(
"G_spawn: unable to execute command"));
509static int undo_signals(
const struct signal *signals,
int num_signals,
515 for (i = num_signals - 1; i >= 0; i--) {
516 const struct signal *s = &signals[i];
518 if (s->which != which)
528 G_warning(
_(
"G_spawn: unable to restore signal %d"), s->signum);
535 G_warning(
_(
"G_spawn: unable to restore signal %d"), s->signum);
545static int do_signals(
struct signal *signals,
int num_signals,
int which)
555 for (i = 0; i < num_signals; i++) {
556 struct signal *s = &signals[i];
558 if (s->which != which)
565 G_warning(
_(
"G_spawn: unable to reset signal %d"), s->signum);
574 G_warning(
_(
"G_spawn: unable to ignore signal %d"), s->signum);
584 G_warning(
_(
"G_spawn: unable to block signal %d"), s->signum);
592 G_warning(
_(
"G_spawn: unable to unblock signal %d"), s->signum);
604static void do_redirects(
struct redirect *redirects,
int num_redirects)
608 for (i = 0; i < num_redirects; i++) {
609 struct redirect *
r = &redirects[i];
612 r->src_fd =
open(
r->file,
r->mode, 0666);
615 G_warning(
_(
"G_spawn: unable to open file %s"),
r->file);
619 if (
dup2(
r->src_fd,
r->dst_fd) < 0) {
620 G_warning(
_(
"G_spawn: unable to duplicate descriptor %d to %d"),
621 r->src_fd,
r->dst_fd);
627 else if (
r->src_fd >= 0) {
628 if (
dup2(
r->src_fd,
r->dst_fd) < 0) {
629 G_warning(
_(
"G_spawn: unable to duplicate descriptor %d to %d"),
630 r->src_fd,
r->dst_fd);
639static void do_bindings(
const struct binding *bindings,
int num_bindings)
643 for (i = 0; i < num_bindings; i++) {
644 const struct binding *
b = &bindings[i];
648 snprintf(str, bufsize,
"%s=%s",
b->var,
b->val);
653static int do_spawn(
struct spawn *
sp,
const char *command)
658 if (!do_signals(
sp->signals,
sp->num_signals,
SST_PRE))
664 undo_signals(
sp->signals,
sp->num_signals,
SST_PRE);
670 if (!undo_signals(
sp->signals,
sp->num_signals,
SST_PRE))
677 if (
chdir(
sp->directory) < 0) {
678 G_warning(
_(
"Unable to change directory to %s"),
sp->directory);
682 do_redirects(
sp->redirects,
sp->num_redirects);
683 do_bindings(
sp->bindings,
sp->num_bindings);
686 G_warning(
_(
"Unable to execute command '%s': %s"), command,
715 undo_signals(
sp->signals,
sp->num_signals,
SST_PRE);
722static void begin_spawn(
struct spawn *
sp)
725 sp->num_redirects = 0;
727 sp->num_bindings = 0;
732#define NEXT_ARG(var, type) ((type) * (var)++)
733#define NEXT_ARG_INT(var) (int)((intptr_t)*(var)++)
735static void parse_argvec(
struct spawn *
sp,
const char **
va)
739 const char *
var, *val;
748 sp->redirects[
sp->num_redirects].src_fd = -1;
750 sp->redirects[
sp->num_redirects].file =
NEXT_ARG(
va,
const char *);
758 sp->redirects[
sp->num_redirects].file =
NULL;
764 sp->redirects[
sp->num_redirects].src_fd = -1;
765 sp->redirects[
sp->num_redirects].file =
NULL;
773 sp->signals[
sp->num_signals].valid = 0;
780 sp->args[
sp->num_args++] = val ? val :
"";
798 sp->args[
sp->num_args++] =
arg;
802static void parse_arglist(
struct spawn *
sp,
va_list va)
806 const char *
var, *val;
813 sp->redirects[
sp->num_redirects].dst_fd =
va_arg(
va,
int);
815 sp->redirects[
sp->num_redirects].src_fd = -1;
816 sp->redirects[
sp->num_redirects].mode =
va_arg(
va,
int);
817 sp->redirects[
sp->num_redirects].file =
va_arg(
va,
const char *);
822 sp->redirects[
sp->num_redirects].dst_fd =
va_arg(
va,
int);
823 sp->redirects[
sp->num_redirects].src_fd =
va_arg(
va,
int);
825 sp->redirects[
sp->num_redirects].file =
NULL;
829 sp->redirects[
sp->num_redirects].dst_fd =
va_arg(
va,
int);
831 sp->redirects[
sp->num_redirects].src_fd = -1;
832 sp->redirects[
sp->num_redirects].file =
NULL;
840 sp->signals[
sp->num_signals].valid = 0;
847 sp->args[
sp->num_args++] = val ? val :
"";
850 sp->bindings[
sp->num_bindings].var =
va_arg(
va,
const char *);
851 sp->bindings[
sp->num_bindings].val =
va_arg(
va,
const char *);
865 sp->args[
sp->num_args++] =
arg;
885 parse_argvec(&
sp, args);
887 return do_spawn(&
sp, command);
907 parse_arglist(&
sp,
va);
910 return do_spawn(&
sp, command);
932 args[num_args++] =
arg;
void G_free(void *)
Free allocated memory.
void G_warning(const char *,...) __attribute__((format(printf
char ** G_tokenize(const char *, const char *)
Tokenize string.
void G_free_tokens(char **)
Free memory allocated to tokens.
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
char * G_store(const char *)
Copy string to allocated memory.
int G_debug(int, const char *,...) __attribute__((format(printf
Header file for msvc/fcntl.c.
float var(IClass_statistics *statistics, int band1, int band2)
Helper function for computing variance.
#define NEXT_ARG(var, type)
int G_vspawn_ex(const char *command, const char **args)
Spawn new process based on command.
int G_spawn(const char *command,...)
Spawn new process based on command.
int G_spawn_ex(const char *command,...)
Spawn new process based on command.
#define NEXT_ARG_INT(var)
#define SF_CLOSE_DESCRIPTOR
#define SF_REDIRECT_DESCRIPTOR