File: xio-exec.c

package info (click to toggle)
socat 1.4.2.0-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,144 kB
  • ctags: 3,624
  • sloc: ansic: 18,730; sh: 3,319; makefile: 153
file content (122 lines) | stat: -rw-r--r-- 3,117 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* $Id: xio-exec.c,v 1.14 2005/03/13 12:21:12 gerhard Exp $ */
/* Copyright Gerhard Rieger 2001-2005 */
/* Published under the GNU General Public License V.2, see file COPYING */

/* this file contains the source for opening addresses of exec type */

#include "xiosysincludes.h"
#include "xioopen.h"

#include "xio-progcall.h"
#include "xio-exec.h"

#if WITH_EXEC

static int xioopen_exec(char *arg,
		int xioflags,	/* XIO_RDONLY etc. */
		xiofile_t *fd,
		unsigned groups,
		int dummy1, int dummy2, void *dummyp1
		);

const struct addrdesc addr_exec = { "exec",   3, xioopen_exec, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 0, 0, NULL HELP(":<command-line>") };

const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };

static int xioopen_exec(char *arg,
		int xioflags,	/* XIO_RDONLY, XIO_MAYCHILD etc. */
		xiofile_t *fd,
		unsigned groups,
		int dummy1, int dummy2, void *dummyp1
		) {
   char *comma;
   int status;
   struct opt *opts = NULL;
   bool dash = false;

   if (comma = strchr(arg, ',')) {
      *comma++ = '\0';
   }

   if (parseopts(comma, groups, &opts) < 0)
      return STAT_NORETRY;

   retropt_bool(opts, OPT_DASH, &dash);

   status = _xioopen_foxec(comma, xioflags, &fd->stream, groups, &opts);
   if (status < 0)  return status;
   if (status == 0) {	/* child */
      char *a1;
      char **argv = NULL;
      int argc, i;
      char *path = NULL;
      char *tmp;
      int numleft;
      int result;

      /*! Close(something) */
      /* parse command line */
      a1 = arg;
      Debug1("child: args = \"%s\"", a1);
      argv = Malloc(8*sizeof(char *));
      if (argv == NULL)  return STAT_RETRYLATER;
      i = 0;
      while (a1[i] && a1[i] != ' ') {
	 ++i;
      }
      if (a1[i]) {
	 a1[i] = '\0';
	 ++i;
      }
      argv[0] = strrchr(a1, '/');
      if (argv[0] == NULL)  argv[0] = a1;  else  ++argv[0];
      for (argc=1; a1[i]; ++argc) {
	 /*Debug3("child: argc = %d, a1 = %s", argc, i, a1);*/
	 if ((argc & 0x07) == 0) {
	    argv = Realloc(argv, (argc+8)*sizeof(char *));
	    if (argv == NULL)  return STAT_RETRYLATER;
	 }
	 argv[argc] = a1+i;
	 while (a1[i] && a1[i] != ' ') {
	    /*fprintf(stderr, "i = %d\n", i);*/
	    ++i;
	 }
	 if (a1[i]) {
	    a1[i] = '\0';
	    ++i;
	 }
      }
      argv[argc] = NULL;

      if ((tmp = Malloc(strlen(argv[0])+2)) == NULL) {
	 return STAT_RETRYLATER;
      }
      if (dash) {
	 tmp[0] = '-';
	 strcpy(tmp+1, argv[0]);
      } else {
	 strcpy(tmp, argv[0]);
      }
      argv[0] = tmp;

      if (setopt_path(opts, &path) < 0) {
	 /* this could be dangerous, so let us abort this child... */
	 Exit(1);
      }

      if ((numleft = leftopts(opts)) > 0) {
	 Error1("%d option(s) could not be used", numleft);
	 showleft(opts);
	 return STAT_NORETRY;
      }

      Notice1("execvp'ing \"%s\"", a1);
      result = Execvp(a1, argv);
      Error2("execvp(\"%s\", ...): %s", argv[0], strerror(errno));
      Exit(1);	/* this child process */
   }

   /* parent */
   return 0;
}
#endif /* WITH_EXEC */