42#define MAX_BINDINGS 256
44#define MAX_REDIRECTS 32
90 const char *directory;
93static void parse_arglist(
struct spawn *
sp,
va_list va);
94static void parse_argvec(
struct spawn *
sp,
const char **
va);
106static void clear(
struct buffer *
b)
109 b->str[
b->len] =
'\0';
112static void init(
struct buffer *
b)
119static char *
release(
struct buffer *
b)
130static void finish(
struct buffer *
b)
137static void ensure(
struct buffer *
b,
size_t n)
139 if (
b->size <=
b->len + n + 1) {
145static void append(
struct buffer *
b,
const char *str)
152 b->str[
b->len] =
'\0';
155static void append_char(
struct buffer *
b,
char c)
160 b->str[
b->len] =
'\0';
163static void escape_arg(
struct buffer *result,
const char *
arg)
173 append_char(result,
'\"');
175 for (
j = 0;
arg[
j];
j++) {
181 append_char(&buf,
'\\');
184 for (k = 0; k < buf.len; k++)
194 append_char(result, c);
203 append_char(result,
'\"');
209static char *
check_program(
const char *
pgm,
const char *dir,
const char *ext)
249 for (i = 0;
path[i]; i++) {
250 const char *dir =
path[i];
273 struct buffer result;
282 append(&result,
" /c \"");
288 append_char(&result,
' ');
299 struct buffer result;
304 for (i = 0;
envp[i]; i++) {
305 const char *env =
envp[i];
308 append_char(&result,
'\0');
352 G_debug(3,
"win_spawn: args = %s", args);
385 for (i = 0; i < 3; i++)
399 return pi.dwProcessId;
402static void do_redirects(
struct redirect *redirects,
int num_redirects,
407 for (i = 0; i < 3; i++)
410 for (i = 0; i < num_redirects; i++) {
411 struct redirect *
r = &redirects[i];
413 if (
r->dst_fd < 0 ||
r->dst_fd > 2) {
414 if (
r->file ||
r->src_fd >= 0)
415 G_warning(
_(
"G_spawn: unable to redirect descriptor %d"),
421 r->src_fd =
open(
r->file,
r->mode, 0666);
424 G_warning(
_(
"G_spawn: unable to open file %s"),
r->file);
432 else if (
r->src_fd >= 0) {
445static void add_binding(
const char **env,
int *
pnum,
const struct binding *
b)
452 snprintf(str, bufsize,
"%s=%s",
b->var,
b->val);
454 for (i = 0; i < n; i++)
464static const char **do_bindings(
const struct binding *bindings,
476 for (i = 0; i < n; i++)
479 for (i = 0; i < num_bindings; i++)
487static int do_spawn(
struct spawn *
sp,
const char *command)
493 do_redirects(
sp->redirects,
sp->num_redirects,
handles);
494 env = do_bindings(
sp->bindings,
sp->num_bindings);
499 if (!
sp->background && status < 0)
500 G_warning(
_(
"G_spawn: unable to execute command"));
507static int undo_signals(
const struct signal *signals,
int num_signals,
513 for (i = num_signals - 1; i >= 0; i--) {
514 const struct signal *s = &signals[i];
516 if (s->which != which)
526 G_warning(
_(
"G_spawn: unable to restore signal %d"), s->signum);
533 G_warning(
_(
"G_spawn: unable to restore signal %d"), s->signum);
543static int do_signals(
struct signal *signals,
int num_signals,
int which)
553 for (i = 0; i < num_signals; i++) {
554 struct signal *s = &signals[i];
556 if (s->which != which)
563 G_warning(
_(
"G_spawn: unable to reset signal %d"), s->signum);
572 G_warning(
_(
"G_spawn: unable to ignore signal %d"), s->signum);
582 G_warning(
_(
"G_spawn: unable to block signal %d"), s->signum);
590 G_warning(
_(
"G_spawn: unable to unblock signal %d"), s->signum);
602static void do_redirects(
struct redirect *redirects,
int num_redirects)
606 for (i = 0; i < num_redirects; i++) {
607 struct redirect *
r = &redirects[i];
610 r->src_fd =
open(
r->file,
r->mode, 0666);
613 G_warning(
_(
"G_spawn: unable to open file %s"),
r->file);
617 if (
dup2(
r->src_fd,
r->dst_fd) < 0) {
618 G_warning(
_(
"G_spawn: unable to duplicate descriptor %d to %d"),
619 r->src_fd,
r->dst_fd);
625 else if (
r->src_fd >= 0) {
626 if (
dup2(
r->src_fd,
r->dst_fd) < 0) {
627 G_warning(
_(
"G_spawn: unable to duplicate descriptor %d to %d"),
628 r->src_fd,
r->dst_fd);
637static void do_bindings(
const struct binding *bindings,
int num_bindings)
641 for (i = 0; i < num_bindings; i++) {
642 const struct binding *
b = &bindings[i];
646 snprintf(str, bufsize,
"%s=%s",
b->var,
b->val);
651static int do_spawn(
struct spawn *
sp,
const char *command)
656 if (!do_signals(
sp->signals,
sp->num_signals,
SST_PRE))
662 undo_signals(
sp->signals,
sp->num_signals,
SST_PRE);
668 if (!undo_signals(
sp->signals,
sp->num_signals,
SST_PRE))
675 if (
chdir(
sp->directory) < 0) {
676 G_warning(
_(
"Unable to change directory to %s"),
sp->directory);
680 do_redirects(
sp->redirects,
sp->num_redirects);
681 do_bindings(
sp->bindings,
sp->num_bindings);
684 G_warning(
_(
"Unable to execute command '%s': %s"), command,
713 undo_signals(
sp->signals,
sp->num_signals,
SST_PRE);
720static void begin_spawn(
struct spawn *
sp)
723 sp->num_redirects = 0;
725 sp->num_bindings = 0;
730#define NEXT_ARG(var, type) ((type) * (var)++)
731#define NEXT_ARG_INT(var) (int)((intptr_t)*(var)++)
733static void parse_argvec(
struct spawn *
sp,
const char **
va)
737 const char *
var, *val;
746 sp->redirects[
sp->num_redirects].src_fd = -1;
748 sp->redirects[
sp->num_redirects].file =
NEXT_ARG(
va,
const char *);
756 sp->redirects[
sp->num_redirects].file =
NULL;
762 sp->redirects[
sp->num_redirects].src_fd = -1;
763 sp->redirects[
sp->num_redirects].file =
NULL;
771 sp->signals[
sp->num_signals].valid = 0;
778 sp->args[
sp->num_args++] = val ? val :
"";
796 sp->args[
sp->num_args++] =
arg;
800static void parse_arglist(
struct spawn *
sp,
va_list va)
804 const char *
var, *val;
811 sp->redirects[
sp->num_redirects].dst_fd =
va_arg(
va,
int);
813 sp->redirects[
sp->num_redirects].src_fd = -1;
814 sp->redirects[
sp->num_redirects].mode =
va_arg(
va,
int);
815 sp->redirects[
sp->num_redirects].file =
va_arg(
va,
const char *);
820 sp->redirects[
sp->num_redirects].dst_fd =
va_arg(
va,
int);
821 sp->redirects[
sp->num_redirects].src_fd =
va_arg(
va,
int);
823 sp->redirects[
sp->num_redirects].file =
NULL;
827 sp->redirects[
sp->num_redirects].dst_fd =
va_arg(
va,
int);
829 sp->redirects[
sp->num_redirects].src_fd = -1;
830 sp->redirects[
sp->num_redirects].file =
NULL;
838 sp->signals[
sp->num_signals].valid = 0;
845 sp->args[
sp->num_args++] = val ? val :
"";
848 sp->bindings[
sp->num_bindings].var =
va_arg(
va,
const char *);
849 sp->bindings[
sp->num_bindings].val =
va_arg(
va,
const char *);
863 sp->args[
sp->num_args++] =
arg;
883 parse_argvec(&
sp, args);
885 return do_spawn(&
sp, command);
905 parse_arglist(&
sp,
va);
908 return do_spawn(&
sp, command);
930 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