2
* Copyright (c) 2008 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
17
* 3. Neither the name of the Institute nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
21
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
#ifndef HAVE_SYS_TYPES_H
37
#include <sys/types.h>
39
#ifdef HAVE_SYS_WAIT_H
56
enum { CMD_EXPECT = 0, CMD_SEND, CMD_PASSWORD } type;
66
static struct command *commands, **next = &commands;
68
static sig_atomic_t alarmset = 0;
70
static int timeout = 10;
73
static int version_flag;
77
static char line[256] = { 0 };
80
caught_signal(int signo)
89
#if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) /* XXX */
90
if(openpty(&master, &slave, line, 0, 0) == 0)
92
#endif /* HAVE_OPENPTY .... */
93
/* more cases, like open /dev/ptmx, etc */
103
iscmd(const char *buf, const char *s)
105
size_t len = strlen(s);
106
if (strncmp(buf, s, len) != 0)
108
return estrdup(buf + len);
112
parse_configuration(const char *fn)
117
unsigned int lineno = 0;
120
cmd = fopen(fn, "r");
122
err(1, "open: %s", fn);
124
while (fgets(s, sizeof(s), cmd) != NULL) {
126
s[strcspn(s, "#\n")] = '\0';
129
c = calloc(1, sizeof(*c));
137
if ((str = iscmd(s, "expect ")) != NULL) {
138
c->type = CMD_EXPECT;
140
} else if ((str = iscmd(s, "send ")) != NULL) {
143
} else if ((str = iscmd(s, "password ")) != NULL) {
144
c->type = CMD_PASSWORD;
147
errx(1, "Invalid command on line %d: %s", lineno, s);
159
eval_parent(pid_t pid)
166
for (c = commands; c != NULL; c = c->next) {
170
printf("[expecting %s]", c->str);
173
while((sret = read(master, &in, sizeof(in))) > 0) {
176
if (c->str[len] != in) {
181
if (c->str[len] == '\0')
185
if (alarmset == SIGALRM)
186
errx(1, "timeout waiting for %s (line %u)",
189
errx(1, "got a signal %d waiting for %s (line %u)",
190
alarmset, c->str, c->lineno);
192
errx(1, "end command while waiting for %s (line %u)",
198
const char *msg = (c->type == CMD_PASSWORD) ? "****" : c->str;
201
printf("[send %s]", msg);
203
len = strlen(c->str);
206
if (c->str[i] == '\\' && i < len - 1) {
210
case 'n': ctrl = '\n'; break;
211
case 'r': ctrl = '\r'; break;
212
case 't': ctrl = '\t'; break;
214
errx(1, "unknown control char %c (line %u)",
215
c->str[i], c->lineno);
217
if (net_write(master, &ctrl, 1) != 1)
218
errx(1, "command refused input (line %u)", c->lineno);
220
if (net_write(master, &c->str[i], 1) != 1)
221
errx(1, "command refused input (line %u)", c->lineno);
231
while(read(master, &in, sizeof(in)) > 0)
235
printf("[end of program]\n");
238
* Fetch status from child
243
ret = waitpid(pid, &status, 0);
246
if (WIFEXITED(status) && WEXITSTATUS(status))
247
return WEXITSTATUS(status);
248
else if (WIFSIGNALED(status)) {
249
printf("killed by signal: %d\n", WTERMSIG(status));
260
static struct getargs args[] = {
261
{ "timeout", 't', arg_integer, &timeout, "timout", "seconds" },
262
{ "verbose", 'v', arg_counter, &verbose, "verbose debugging" },
263
{ "version", 0, arg_flag, &version_flag, "print version" },
264
{ "help", 0, arg_flag, &help_flag, NULL }
270
arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "infile command..");
275
main(int argc, char **argv)
280
setprogname(argv[0]);
282
if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
289
fprintf (stderr, "%s from %s-%s\n", getprogname(), PACKAGE, VERSION);
299
parse_configuration(argv[0]);
309
err(1, "Failed to fork");
315
dup2(slave, STDIN_FILENO);
316
dup2(slave, STDOUT_FILENO);
317
dup2(slave, STDERR_FILENO);
318
closefrom(STDERR_FILENO + 1);
320
execvp(argv[0], argv); /* add NULL to end of array ? */
321
err(1, "Failed to exec: %s", argv[0]);
327
sa.sa_handler = caught_signal;
329
sigemptyset (&sa.sa_mask);
331
sigaction(SIGALRM, &sa, NULL);
334
return eval_parent(pid);