File: xio-shell.c

package info (click to toggle)
socat 1.8.1.1-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 5,408 kB
  • sloc: ansic: 35,501; sh: 19,882; makefile: 159
file content (105 lines) | stat: -rw-r--r-- 2,859 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
/* source: xio-shell.c */
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
/* Published under the GNU General Public License V.2, see file COPYING */

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

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

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


#if WITH_SHELL

static int xioopen_shell(int arg, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);

const struct addrdesc xioaddr_shell = { "SHELL", 3, xioopen_shell, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT|GROUP_SHELL, 1, 0, 0 HELP("[:<shell-command>]") };

const struct optdesc opt_shell = { "shell", NULL, OPT_SHELL, GROUP_SHELL, PH_PREEXEC, TYPE_STRING, OFUNC_SPEC, 0, 0 };

static int xioopen_shell(
	int argc,
	const char *argv[],
	struct opt *opts,
	int xioflags,
	xiofile_t *xfd,
	const struct addrdesc *addrdesc)
{
	struct single *sfd = &xfd->stream;
	int status;
	char *path = NULL;
	int duptostderr;
	int result;
	char *shellpath = NULL;
	const char *shellname;
	const char *string = argv[1];

	if (argc < 1 || argc > 2) {
		xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
		return STAT_NORETRY;
	}

	shellpath = getenv("SHELL");
	retropt_string(opts, OPT_SHELL, &shellpath);
	if (shellpath == NULL) {
		Error("SHELL variable undefined");
		errno = EINVAL;
		return -1;
	}
	shellname = strrchr(shellpath, '/');
	if (shellname == NULL) {
		Error1("SHELL \"%s\" variable does not specify a path (has no '/')", shellpath);
		errno = EINVAL;
		return -1;
	}
	++shellname;

	status = _xioopen_foxec(xioflags, sfd, addrdesc->groups, &opts, &duptostderr);
	if (status < 0)  return status;
	if (status == 0) {	/* child */
		int numleft;

		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;
		}

		/* only now redirect stderr */
		if (duptostderr >= 0) {
			diag_dup();
			Dup2(duptostderr, 2);
		}

		Setenv("SHELL", shellpath, 1);

		if (string != NULL) {
			Info1("executing shell command \"%s\"", string);
			Debug3("execl(\"%s\", \"%s\", \"-c\", \"%s\", NULL)",
			       shellpath, shellname, string);
			result = execl(shellpath, shellname, "-c", string, (char *)NULL);
		} else {
			Info("executing interactive shell");
			Debug2("execl(\"%s\", \"%s\", NULL)",
			       shellpath, shellname);
			result = execl(shellpath, shellname, (char *)NULL);
		}
		if (result != 0) {
			Warn2("execl(\"%s\") returned with status %d", string, result);
			Warn1("execl(): %s", strerror(errno));
		}
		Exit(0);	/* this child process */
	}

	/* parent */
	return 0;
}

#endif /* WITH_SHELL */