All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 463ee6b1 authored by Timothy Stack's avatar Timothy Stack

Mote and robot related stuff.  The main thing is the addition of relay
capabilities to capture and related things.

	* GNUmakefile.in: Add the capture and tip subdirectories to the
	client and client-install targets.

	* configure, configure.in, config.h.in: Detect srandomdev() for
	capture and add "mote/newmote" script.

	* capture/GNUmakefile.in, capture/capture.c: Add "relay"
	capabilities to capture.

	* capture/capquery.c: Query the capserver for the relay receiver's
	port number.

	* capture/capserver.c: Small hack to return the port number
        for a node.

	* db/libdb.pm.in, db/xmlconvert.in: Add virt_tiptunnels table.

	* event/program-agent/program-agent.c: Change log file names to
	something a little more user-friendly.  Add a "MODIFY" event
	handler that lets the user set agent attributes (command, tag,
	timeout) without having to run a program.

	* event/sched/GNUmakefile.in, event/sched/console-agent.cc,
	event/sched/console-agent.h, event/sched/event-sched.c: Add
	console agents that can be used to snapshot a section of the
	capture log file.

	* event/sched/node-agent.cc: Some minor cleanup.

	* event/sched/simulator-agent.cc, event/sched/simulator-agent.h:
	Add the config data to the report mail.  Add a "RESET" event
	handler that runs "loghole clean".  Save the report mail in a file
	so it gets archived with the rest of the logs.

	* lib/libtb/tbdefs.h: Add CONSOLE object type.

	* mote/GNUmakefile.in, mote/newmote: Add newmote script, just a
	quick hack to add motes to the DB.

	* mote/tbuisp.in: Add another backend for loading motes through
	their relay capture server.

	* robots/mtp/mtp_dump.c: Dump the min/max values for x and y,
	handy for figuring out the bounds of the camera.

	* sql/database-fill.sql: Change the RELOAD-MOTE/SHUTDOWN ->
	ALWAYSUP/SHUTDOWN mode transition to ALWAYSUP/ISUP since stated
	doesn't seem to run triggers after a state change by a mode
	transition.

	* tbsetup/tbreport.in: Change the ordering of the eventlist so it
	displays event-sequences appropriately.

	* tbsetup/ns2ir/GNUmakefile.in, tbsetup/ns2ir/console.tcl,
	tbsetup/ns2ir/node.tcl, tbsetup/ns2ir/parse.tcl.in,
	tbsetup/ns2ir/sim.tcl.in: Add a "console" agent that represents
	the serial console for a node.

	* tbsetup/ns2ir/sequence.tcl: Add an "append" method so it is
	easier to build sequences dynamically.

	* tbsetup/ns2ir/topography.tcl: Make checkdest available to
	regular users.

	* tip/GNUmakefile.in, tip/tiptunnel.c: Add support for uploading a
	file to a relay version of capture and exporting the end
	connection as a pty.

	* tmcd/decls.h, tmcd/common/libsetup.pm: Bump version number since
	the dosubnodelist change is not backwards compatible.

	* tmcd/tmcd.c: Make dosubnodelist and dosubconfig callable even
	when a node isn't allocated.  Add dotiptunnels command that
	returns which serial consoles are to be mounted on a node.  Add
	mote version of subconfig that returns information needed to
	startup the relay version of capture.

	* tmcd/common/bootsubnodes: For motes, startup the relay version
	of capture (XXX stargate specific).

	* tmcd/common/libsetup.pm, tmcd/common/libtmcc.pm,
	tmcd/common/config/rc.config, tmcd/common/config/rc.tiptunnels:
	Client side changes for mounting another nodes serial line.

	* tmcd/common/rc.bootsetup: Always boot the subnodes, even when
	free.  This is used for motes since their capture needs to be up
	for reloading at the time.

	* tmcd/linux/ixpboot: Shuffle some code around so the script
	doesn't fail if the ixp isn't allocated.

	* utils/loghole.in: Add "digest.out" and "report.mail" as global
	logs to be saved in archives and display the "report.mail" file
	when showing a loghole archive.

	* xmlrpc/emulabserver.py.in: Scrub more of the return values to
	get rid of "None"s.
parent d75ced68
......@@ -114,6 +114,8 @@ ifeq ($(EVENTSYS),1)
@$(MAKE) -C event client
endif
@$(MAKE) -C os client
@$(MAKE) -C capture client
@$(MAKE) -C tip client
@$(MAKE) -C sensors client
@$(MAKE) -C tmcd client
......@@ -122,6 +124,8 @@ ifeq ($(EVENTSYS),1)
@$(MAKE) -C event client-install
endif
@$(MAKE) -C os client-install
@$(MAKE) -C capture client-install
@$(MAKE) -C tip client-install
@$(MAKE) -C sensors client-install
@$(MAKE) -C tmcd client-install
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -9,11 +9,14 @@ TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ..
SUBDIR = capture
SYSTEM := $(shell uname -s)
include $(OBJDIR)/Makeconf
all: boss-all tipserv-all
boss-all: capserver
tipserv-all: capture capture-tty
tipserv-all: capture capture-tty capquery
client: capture capquery
include $(TESTBED_SRCDIR)/GNUmakerules
......@@ -25,25 +28,44 @@ DESTDIR=
# Define LOG_DROPS to record warnings in syslog whenever chars were dropped
# due to the output device/pty being full.
#
CFLAGS= -g -O2 -DLOG_DROPS -I${OBJDIR} -DLOG_TESTBED=$(LOG_TESTBED)
CFLAGS += -g -O2 -DLOG_DROPS -I${OBJDIR} -DLOG_TESTBED=$(LOG_TESTBED)
ifeq ($(SYSTEM),Linux)
ifeq ($(host_cpu),arm)
LDFLAGS += -static
else
CFLAGS += -I/usr/kerberos/include
LDFLAGS += -L/usr/kerberos/lib -lkrb5 -lk5crypto -lcom_err
endif
else
LDFLAGS += -static
endif
capture: capture.c capdecls.h
cc -static $(CFLAGS) -DUSESOCKETS -DWITHSSL -DPREFIX=\"$(TBROOT)\" -o capture $< -lssl -lcrypto
$(CC) $(CFLAGS) -DUSESOCKETS -DWITHSSL -DPREFIX=\"$(TBROOT)\" -o capture $< -lssl -lcrypto $(LDFLAGS)
capquery: capquery.c capdecls.h
$(CC) $(CFLAGS) -DPREFIX=\"$(TBROOT)\" -o $@ $<
capture-nossl: capture.c capdecls.h
cc $(CFLAGS) -DUSESOCKETS -DPREFIX=\"$(TBROOT)\" -o capture-nossl $<
$(CC) $(CFLAGS) -DUSESOCKETS -DPREFIX=\"$(TBROOT)\" -o capture-nossl $<
capture-tty: capture.c capdecls.h
cc $(CFLAGS) -o capture-tty $<
$(CC) $(CFLAGS) -o capture-tty $<
capserver: capserver.c capdecls.h
cc $(CFLAGS) $(DBFLAGS) -o capserver $< \
$(CC) $(CFLAGS) $(DBFLAGS) -o capserver $< \
-L/usr/local/lib/mysql -lmysqlclient
#
# Do not capture install by default.
#
install: all $(INSTALL_SBINDIR)/capserver
$(INSTALL_PROGRAM) capture $(INSTALL_DIR)/opsdir/sbin/capture
client-install: client
$(INSTALL_PROGRAM) capture$(EXE) $(DESTDIR)$(CLIENT_BINDIR)/capture$(EXE)
$(INSTALL_PROGRAM) capquery$(EXE) $(DESTDIR)$(CLIENT_BINDIR)/capquery$(EXE)
real-install: all $(INSTALL_SBINDIR)/capserver $(INSTALL_SBINDIR)/capture
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2005 University of Utah and the Flux Group.
* All rights reserved.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <assert.h>
#include <stdarg.h>
#include <sys/time.h>
#include <grp.h>
#include "capdecls.h"
static int debug = 0;
static char *usagestr =
"usage: capquery [-d] [-s server] [-p #] name\n"
" -d Turn on debugging.\n"
" -s server Specify a name to connect to.\n"
" -p portnum Specify a port number to connect to.\n"
"\n";
void
usage()
{
fprintf(stderr, usagestr);
exit(1);
}
static int
mygethostbyname(struct sockaddr_in *host_addr, char *host, int port)
{
struct hostent *host_ent;
int retval = 0;
assert(host_addr != NULL);
assert(host != NULL);
assert(strlen(host) > 0);
memset(host_addr, 0, sizeof(struct sockaddr_in));
#ifndef linux
host_addr->sin_len = sizeof(struct sockaddr_in);
#endif
host_addr->sin_family = AF_INET;
host_addr->sin_port = htons(port);
if( (host_ent = gethostbyname(host)) != NULL ) {
memcpy((char *)&host_addr->sin_addr.s_addr,
host_ent->h_addr,
host_ent->h_length);
retval = 1;
}
else {
retval = inet_aton(host, &host_addr->sin_addr);
}
return( retval );
}
int
main(int argc, char **argv)
{
int sock, ch, rc, retval = EXIT_FAILURE;
int length, port = SERVERPORT;
char *server = BOSSNODE;
struct sockaddr_in sin;
whoami_t whoami;
while ((ch = getopt(argc, argv, "ds:p:")) != -1)
switch(ch) {
case 's':
server = optarg;
break;
case 'p':
port = atoi(optarg);
break;
case 'd':
debug++;
break;
case 'h':
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
if (strlen(argv[0]) >= sizeof(whoami.name))
fprintf(stderr, "Name too long: %s\n", argv[0]);
if (getuid() != 0)
fprintf(stderr, "Must be run as root\n");
memset(&whoami, 0, sizeof(whoami));
strcpy(whoami.name, argv[0]);
whoami.portnum = -1;
if (!mygethostbyname(&sin, server, port))
fprintf(stderr, "Bad server name: %s\n", server);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("socket");
else if (bindresvport(sock, NULL) < 0)
perror("bindresvport");
else if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
perror("connect");
else if (write(sock, &whoami, sizeof(whoami)) != sizeof(whoami))
perror("write");
else if ((rc = read(sock, &port, sizeof(port))) != sizeof(port))
perror("read");
else {
printf("%d\n", port);
retval = EXIT_SUCCESS;
}
close(sock);
return retval;
}
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* Copyright (c) 2000-2003, 2005 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -137,6 +137,8 @@ main(int argc, char **argv)
unsigned char buf[BUFSIZ], node_id[64];
secretkey_t secretkey;
tipowner_t tipown;
void *reply = &tipown;
size_t reply_size = sizeof(tipown);
if ((clientsock = accept(tcpsock,
(struct sockaddr *)&client,
......@@ -193,9 +195,9 @@ main(int argc, char **argv)
* message in the log file. Local tip will still work but
* remote tip will not.
*/
res = mydb_query("select server,node_id from tiplines "
res = mydb_query("select server,node_id,portnum from tiplines "
"where tipname='%s'",
2, whoami.name);
3, whoami.name);
if (!res) {
syslog(LOG_ERR, "DB Error getting tiplines for %s!",
whoami.name);
......@@ -209,6 +211,8 @@ main(int argc, char **argv)
}
row = mysql_fetch_row(res);
strcpy(node_id, row[1]);
port = -1;
sscanf(row[2], "%d", &port);
mysql_free_result(res);
/*
......@@ -246,10 +250,14 @@ main(int argc, char **argv)
}
mysql_free_result(res);
if (whoami.portnum == -1) {
reply = &port;
reply_size = sizeof(port);
}
/*
* Update the DB.
*/
if (mydb_update("update tiplines set portnum=%d, "
else if (mydb_update("update tiplines set portnum=%d, "
"keylen=%d, keydata='%s' "
"where tipname='%s'",
whoami.portnum,
......@@ -263,13 +271,13 @@ main(int argc, char **argv)
/*
* And now send the reply.
*/
if ((cc = write(clientsock, &tipown, sizeof(tipown))) <= 0) {
if ((cc = write(clientsock, reply, reply_size)) <= 0) {
if (cc < 0)
syslog(LOG_ERR, "Writing reply: %m");
syslog(LOG_ERR, "Connection aborted (write)");
goto done;
}
if (cc != sizeof(tipown)) {
if (cc != reply_size) {
syslog(LOG_ERR, "Wrong byte count (write)!");
goto done;
}
......
This diff is collapsed.
......@@ -30,5 +30,7 @@
#undef EVENTSERVER
#undef BOSSEVENTPORT
#undef HAVE_SRANDOMDEV
#undef HAVE_LINUX_VIDEODEV_H
#undef HAVE_MEZZANINE
......@@ -1222,6 +1222,62 @@ fi
for ac_func in srandomdev
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1229: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1234 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char $ac_func();
int main() {
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
$ac_func();
#endif
; return 0; }
EOF
if { (eval echo configure:1257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
echo "$ac_t""yes" 1>&6
ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
cat >> confdefs.h <<EOF
#define $ac_tr_func 1
EOF
else
echo "$ac_t""no" 1>&6
fi
done
#
......@@ -1854,17 +1910,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1858: checking for $ac_hdr" >&5
echo "configure:1914: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1863 "configure"
#line 1919 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1868: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1924: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -1903,17 +1959,17 @@ for ac_hdr in linux/videodev.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1907: checking for $ac_hdr" >&5
echo "configure:1963: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1912 "configure"
#line 1968 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1917: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -1946,7 +2002,7 @@ done
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1950: checking for $ac_word" >&5
echo "configure:2006: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2025,7 +2081,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:2029: checking for a BSD compatible install" >&5
echo "configure:2085: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2086,7 +2142,7 @@ esac
# Extract the first word of "rsync", so it can be a program name with args.
set dummy rsync; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2090: checking for $ac_word" >&5
echo "configure:2146: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2256,7 +2312,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
dhcpd/dhcpd.conf.template dhcpd/GNUmakefile \
install/GNUmakefile install/ops-install install/boss-install \
install/newnode_sshkeys/GNUmakefile install/smb.conf.head \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower mote/newmote \
robots/GNUmakefile robots/tbsetdest/GNUmakefile \
robots/mtp/GNUmakefile robots/emc/GNUmakefile \
robots/emc/test_emcd.sh robots/emc/loclistener \
......
......@@ -57,6 +57,8 @@ AC_PATH_PROG(JAR,jar)
AC_CHECK_TOOL(SSH,ssh)
AC_CHECK_FUNCS(srandomdev)
AC_SUBST(optional_subdirs)
#
......@@ -751,7 +753,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
dhcpd/dhcpd.conf.template dhcpd/GNUmakefile \
install/GNUmakefile install/ops-install install/boss-install \
install/newnode_sshkeys/GNUmakefile install/smb.conf.head \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower \
mote/GNUmakefile mote/tbuisp mote/tbsgmotepower mote/newmote \
robots/GNUmakefile robots/tbsetdest/GNUmakefile \
robots/mtp/GNUmakefile robots/emc/GNUmakefile \
robots/emc/test_emcd.sh robots/emc/loclistener \
......
......@@ -3144,6 +3144,7 @@ sub TBRobotLabExpt($$)
"event_groups",
"firewalls",
"firewall_rules",
"virt_tiptunnels",
"ipsubnets",
"nsfiles");
......
......@@ -130,7 +130,11 @@ my %virtual_tables =
"firewall_rules" => { rows => undef,
tag => "firewall_rules",
row => "firewall_rule",
attrs => [ "fwname", "ruleno", "rule" ]}
attrs => [ "fwname", "ruleno", "rule" ]},
"virt_tiptunnels" => { rows => undef,
tag => "tiptunnels",
row => "tiptunnel",
attrs => [ "host", "vnode" ]}
);
# XXX
......
......@@ -182,6 +182,8 @@ static void start_program(struct proginfo *pinfo,
unsigned long token,
char *args);
static void set_program(struct proginfo *pinfo, char *args);
/**
* Stop a running program.
*
......@@ -825,12 +827,40 @@ callback(event_handle_t handle, event_notification_t notification, void *data)
else if (strcmp(event, TBDB_EVENTTYPE_KILL) == 0) {
signal_program(pinfo, args);
}
else if (strcmp(event, TBDB_EVENTTYPE_MODIFY) == 0) {
set_program(pinfo, args);
}
else {
error("Invalid event: %s\n", event);
return;
}
}
static char *fileext(char *path)
{
int has_token = 0, lpc, len;
char *retval = NULL;
assert(path != NULL);
len = strlen(path);
for (lpc = len - 1; lpc > 0; lpc--) {
if (path[lpc] == '.') {
if (has_token) {
retval = &path[lpc + 1];
}
else if (sscanf(&path[lpc + 1], "%*d") == 1) {
has_token = 1;
}
else {
retval = &path[lpc + 1];
}
}
}
return retval;
}
static void
start_callback(event_handle_t handle,
event_notification_t notification,
......@@ -880,20 +910,17 @@ start_callback(event_handle_t handle,
char path[1024];
while ((de = readdir(dir)) != NULL) {
unsigned int token = 0;
char ext[16];
char *ext = NULL;
if ((strlen(de->d_name) < sizeof(path)) &&
((sscanf(de->d_name,
"%[^.].%u.%16s",
path, &token, ext) == 3) ||
(sscanf(de->d_name,
"%[^.].%16s",
path, ext) == 2)) &&
"%1024[^.].",
path) == 1) &&
(find_agent(path) != NULL) &&
((strcmp(ext, "out") == 0) ||
(strcmp(ext, "err") == 0) ||
(strcmp(ext, "status") == 0))) {
((ext = fileext(de->d_name)) != NULL) &&
((strncmp(ext, "out", 3) == 0) ||
(strncmp(ext, "err", 3) == 0) ||
(strncmp(ext, "status", 6) == 0))) {
snprintf(path,
sizeof(path),
"%s/%s",
......@@ -940,16 +967,16 @@ open_logfile(struct proginfo *pinfo, const char *type)
* agent name, the event token, and the type (e.g. out, err).
*/
snprintf(buf, sizeof(buf),
"%s/%s.%lu.%s",
LOGDIR, pinfo->name, pinfo->token, type);
"%s/%s.%s.%lu",
LOGDIR, pinfo->name, type, pinfo->token);
if ((retval = open(buf, O_WRONLY|O_CREAT|O_APPEND, 0640)) >= 0) {
/*
* We've successfully created the file, now create the
* symlinks to that refer to the last run and a tagged run.
*/
snprintf(buf, sizeof(buf),
"./%s.%lu.%s",
pinfo->name, pinfo->token, type);
"./%s.%s.%lu",
pinfo->name, type, pinfo->token);
snprintf(buf2, sizeof(buf2),
"%s/%s.%s",
LOGDIR, pinfo->name, type);
......@@ -968,15 +995,10 @@ open_logfile(struct proginfo *pinfo, const char *type)
}
static void
start_program(struct proginfo *pinfo, unsigned long token, char *args)
set_program(struct proginfo *pinfo, char *args)
{
int pid, in_fd, out_fd = -1, err_fd = -1;
if (pinfo->pid != 0) {
warning("start_program: %s is still running: %d\n",
pinfo->name, pinfo->pid);
return;
}
assert(pinfo != NULL);
assert(args != NULL);
/*
* The args string holds the command line to execute. We allow
......@@ -1043,11 +1065,24 @@ start_program(struct proginfo *pinfo, unsigned long token, char *args)
value = NULL;
}
}
}
static void
start_program(struct proginfo *pinfo, unsigned long token, char *args)
{
int pid, in_fd, out_fd = -1, err_fd = -1;
if (pinfo->pid != 0) {
warning("start_program: %s is still running: %d\n",
pinfo->name, pinfo->pid);
return;
}
set_program(pinfo, args);
gettimeofday(&pinfo->started, NULL);
pinfo->token = token;
if ((pinfo->timeout > 0) &&
(pinfo->timeout_handle =
elvin_sync_add_timeout(NULL,
......@@ -1525,13 +1560,16 @@ child_callback(elvin_io_handler_t handler,
}
}
else {
if (status == pi->expected_exit_code)
exit_code = 0;
else
exit_code = status;
}
/* Dump a status file and */
snprintf(path,
sizeof(path),
"%s/%s.%lu.status",
"%s/%s.status.%lu",