2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
4 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
29 * $Id: amandad.c,v 1.18 2006/08/21 20:17:09 martinea Exp $
31 * handle client-host side of Amanda network communications, including
32 * security checks, execution of the proper service, and acking the
40 #include "amfeatures.h"
48 #define REP_TIMEOUT (6*60*60) /* secs for service to reply */
49 #define ACK_TIMEOUT 10 /* XXX should be configurable */
50 #define STDERR_PIPE (DATA_FD_COUNT + 1)
52 #define amandad_debug(i, ...) do { \
53 if ((i) <= debug_amandad) { \
54 dbprintf(__VA_ARGS__); \
59 * These are the actions for entering the state machine
61 typedef enum { A_START, A_RECVPKT, A_RECVREP, A_PENDING, A_FINISH, A_CONTINUE,
62 A_SENDNAK, A_TIMEOUT } action_t;
65 * This is a state in the state machine. It is a function pointer to
66 * the function that actually implements the state.
68 struct active_service;
69 typedef action_t (*state_t)(struct active_service *, action_t, pkt_t *);
71 /* string that we scan for in sendbackup's MESG stream */
72 static const char info_end_str[] = "sendbackup: info end\n";
73 #define INFO_END_LEN (sizeof(info_end_str)-1)
76 * Here are the services that we allow.
77 * Must be in the same order as services[].
89 static struct services {
94 { "noop", 1, SERVICE_NOOP },
95 { "sendsize", 1, SERVICE_SENDSIZE },
96 { "sendbackup", 1, SERVICE_SENDBACKUP },
97 { "selfcheck", 1, SERVICE_SELFCHECK },
98 { "amindexd", 0, SERVICE_AMINDEXD },
99 { "amidxtaped", 0, SERVICE_AMIDXTAPED },
100 { "amdumpd", 0, SERVICE_AMDUMPD }
102 #define NSERVICES (int)(sizeof(services) / sizeof(services[0]))
105 * This structure describes an active running service.
107 * An active service is something running that we have received
108 * a request for. This structure holds info on that service, including
109 * file descriptors for data, etc, as well as the security handle
110 * for communications with the amanda server.
112 struct active_service {
113 service_t service; /* service name */
114 char *cmd; /* name of command we ran */
115 char *arguments; /* arguments we sent it */
116 security_handle_t *security_handle; /* remote server */
117 state_t state; /* how far this has progressed */
118 pid_t pid; /* pid of subprocess */
119 int send_partial_reply; /* send PREP packet */
120 int reqfd; /* pipe to write requests */
121 int repfd; /* pipe to read replies */
122 int errfd; /* pipe to read stderr */
123 event_handle_t *ev_repfd; /* read event handle for repfd */
124 event_handle_t *ev_reptimeout; /* timeout for rep data */
125 event_handle_t *ev_errfd; /* read event handle for errfd */
126 pkt_t rep_pkt; /* rep packet we're sending out */
127 char *errbuf; /* buffer to read the err into */
128 char *repbuf; /* buffer to read the rep into */
129 size_t bufsize; /* length of repbuf */
130 size_t repbufsize; /* length of repbuf */
131 int repretry; /* times we'll retry sending the rep */
132 int seen_info_end; /* have we seen "sendbackup info end\n"? */
133 char info_end_buf[INFO_END_LEN]; /* last few bytes read, used for scanning for info end */
136 * General user streams to the process, and their equivalent
139 struct datafd_handle {
140 int fd_read; /* pipe to child process */
141 int fd_write; /* pipe to child process */
142 event_handle_t *ev_read; /* it's read event handle */
143 event_handle_t *ev_write; /* it's write event handle */
144 security_stream_t *netfd; /* stream to amanda server */
145 struct active_service *as; /* pointer back to our enclosure */
146 } data[DATA_FD_COUNT];
147 char databuf[NETWORK_BLOCK_BYTES]; /* buffer to relay netfd data in */
151 * Queue of outstanding requests that we are running.
153 GSList *serviceq = NULL;
155 static event_handle_t *exit_event;
156 static int exit_on_qlength = 1;
157 static char *auth = NULL;
158 static kencrypt_type amandad_kencrypt = KENCRYPT_NONE;
160 int main(int argc, char **argv);
162 static int allocstream(struct active_service *, int);
163 static void exit_check(void *);
164 static void protocol_accept(security_handle_t *, pkt_t *);
165 static void state_machine(struct active_service *, action_t, pkt_t *);
167 static action_t s_sendack(struct active_service *, action_t, pkt_t *);
168 static action_t s_repwait(struct active_service *, action_t, pkt_t *);
169 static action_t s_processrep(struct active_service *, action_t, pkt_t *);
170 static action_t s_sendrep(struct active_service *, action_t, pkt_t *);
171 static action_t s_ackwait(struct active_service *, action_t, pkt_t *);
173 static void repfd_recv(void *);
174 static void process_errfd(void *cookie);
175 static void errfd_recv(void *);
176 static void timeout_repfd(void *);
177 static void protocol_recv(void *, pkt_t *, security_status_t);
178 static void process_readnetfd(void *);
179 static void process_writenetfd(void *, void *, ssize_t);
180 static struct active_service *service_new(security_handle_t *,
181 const char *, service_t, const char *);
182 static void service_delete(struct active_service *);
183 static int writebuf(struct active_service *, const void *, size_t);
184 static ssize_t do_sendpkt(security_handle_t *handle, pkt_t *pkt);
185 static char *amandad_get_security_conf (char *, void *);
187 static const char *state2str(state_t);
188 static const char *action2str(action_t);
198 const security_driver_t *secdrv;
200 char *pgm = "amandad"; /* in case argv[0] is not set */
201 #if defined(USE_REUSEADDR)
207 * Configure program for internationalization:
208 * 1) Only set the message locale for now.
209 * 2) Set textdomain for all amanda related programs to "amanda"
210 * We don't want to be forced to support dozens of message catalogs.
212 setlocale(LC_MESSAGES, "C");
213 textdomain("amanda");
219 * Nexenta needs the SUN_PERSONALITY env variable to be unset, otherwise
220 * the Sun version of tar in /usr/sun/sbin/tar is called instead.
222 * On other operating systems this will have no effect.
226 unsetenv("SUN_PERSONALITY");
230 * When called via inetd, it is not uncommon to forget to put the
231 * argv[0] value on the config line. On some systems (e.g. Solaris)
232 * this causes argv and/or argv[0] to be NULL, so we have to be
233 * careful getting our name.
235 if ((argv == NULL) || (argv[0] == NULL)) {
236 pgm = "amandad"; /* in case argv[0] is not set */
238 pgm = basename(argv[0]); /* Strip of leading path get debug name */
241 dbopen(DBG_SUBDIR_AMANDAD);
244 error(_("argv == NULL\n"));
248 if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
249 printf("amandad-%s\n", VERSION);
253 /* Don't die when child closes pipe */
254 signal(SIGPIPE, SIG_IGN);
256 /* Parse the configuration; we'll handle errors later */
257 config_init(CONFIG_INIT_CLIENT, NULL);
259 if (geteuid() == 0) {
260 check_running_as(RUNNING_AS_ROOT);
261 initgroups(CLIENT_LOGIN, get_client_gid());
262 setgid(get_client_gid());
263 setegid(get_client_gid());
264 seteuid(get_client_uid());
266 check_running_as(RUNNING_AS_CLIENT_LOGIN);
269 add_amanda_log_handler(amanda_log_stderr);
270 add_amanda_log_handler(amanda_log_syslog);
273 * ad-hoc argument parsing
275 * We accept -auth=[authentication type]
279 * We also add a list of services that amandad can launch
282 in = 0; out = 1; /* default to stdin/stdout */
284 for (i = 1; i < argc; i++) {
286 * Get a driver for a security type specified after -auth=
288 if (strncmp(argv[i], "-auth=", strlen("-auth=")) == 0) {
289 argv[i] += strlen("-auth=");
290 secdrv = security_getdriver(argv[i]);
292 if (secdrv == NULL) {
293 error(_("no driver for security type '%s'\n"), argv[i]);
296 if (strcmp(auth, "local") == 0 ||
297 strcmp(auth, "rsh") == 0 ||
298 strcmp(auth, "ssh") == 0) {
300 for (i=0; i < NSERVICES; i++) {
301 services[i].active = 1;
308 * If -no-exit is specified, always run even after requests have
311 else if (strcmp(argv[i], "-no-exit") == 0) {
317 * Allow us to directly bind to a udp port for debugging.
318 * This may only apply to some security types.
320 else if (strncmp(argv[i], "-udp=", strlen("-udp=")) == 0) {
322 struct sockaddr_in6 sin;
324 struct sockaddr_in sin;
327 argv[i] += strlen("-udp=");
329 in = out = socket(AF_INET6, SOCK_DGRAM, 0);
331 in = out = socket(AF_INET, SOCK_DGRAM, 0);
334 error(_("can't create dgram socket: %s\n"), strerror(errno));
338 r = setsockopt(in, SOL_SOCKET, SO_REUSEADDR,
339 (void *)&on, (socklen_t_equiv)sizeof(on));
341 dbprintf(_("amandad: setsockopt(SO_REUSEADDR) failed: %s\n"),
347 sin.sin6_family = (sa_family_t)AF_INET6;
348 sin.sin6_addr = in6addr_any;
349 sin.sin6_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
351 sin.sin_family = (sa_family_t)AF_INET;
352 sin.sin_addr.s_addr = INADDR_ANY;
353 sin.sin_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
355 if (bind(in, (struct sockaddr *)&sin, (socklen_t_equiv)sizeof(sin)) < 0) {
356 error(_("can't bind to port %d: %s\n"), atoi(argv[i]),
362 * Ditto for tcp ports.
364 else if (strncmp(argv[i], "-tcp=", strlen("-tcp=")) == 0) {
366 struct sockaddr_in6 sin;
368 struct sockaddr_in sin;
373 argv[i] += strlen("-tcp=");
375 sock = socket(AF_INET6, SOCK_STREAM, 0);
377 sock = socket(AF_INET, SOCK_STREAM, 0);
380 error(_("can't create tcp socket: %s\n"), strerror(errno));
384 r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
385 (void *)&on, (socklen_t_equiv)sizeof(on));
387 dbprintf(_("amandad: setsockopt(SO_REUSEADDR) failed: %s\n"),
392 sin.sin6_family = (sa_family_t)AF_INET6;
393 sin.sin6_addr = in6addr_any;
394 sin.sin6_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
396 sin.sin_family = (sa_family_t)AF_INET;
397 sin.sin_addr.s_addr = INADDR_ANY;
398 sin.sin_port = (in_port_t)htons((in_port_t)atoi(argv[i]));
400 if (bind(sock, (struct sockaddr *)&sin, (socklen_t_equiv)sizeof(sin)) < 0) {
401 error(_("can't bind to port %d: %s\n"), atoi(argv[i]),
406 n = (socklen_t_equiv)sizeof(sin);
407 in = out = accept(sock, (struct sockaddr *)&sin, &n);
410 * It must be a service name
413 /* clear all services */
415 for (j = 0; j < (int)NSERVICES; j++)
416 services[j].active = 0;
420 if(strcmp(argv[i],"amdump") == 0) {
421 services[0].active = 1;
422 services[1].active = 1;
423 services[2].active = 1;
424 services[3].active = 1;
427 for (j = 0; j < (int)NSERVICES; j++)
428 if (strcmp(services[j].name, argv[i]) == 0)
430 if (j == (int)NSERVICES) {
431 dbprintf(_("%s: invalid service\n"), argv[i]);
434 services[j].active = 1;
440 * If no security type specified, use BSDTCP
442 if (secdrv == NULL) {
443 secdrv = security_getdriver("BSDTCP");
445 if (secdrv == NULL) {
446 error(_("no driver for default security type 'BSDTCP'\n"));
451 if(strcasecmp(auth, "rsh") == 0 ||
452 strcasecmp(auth, "ssh") == 0 ||
453 strcasecmp(auth, "local") == 0 ||
454 strcasecmp(auth, "bsdtcp") == 0) {
458 #ifndef SINGLE_USERID
459 if (geteuid() == 0) {
460 if (strcasecmp(auth, "krb5") != 0) {
462 /* lookup our local user name */
463 if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
464 error(_("getpwnam(%s) failed."), CLIENT_LOGIN);
467 if (pwd->pw_uid != 0) {
468 error(_("'amandad' must be run as user '%s' when using '%s' authentication"),
473 if (strcasecmp(auth, "krb5") == 0) {
474 error(_("'amandad' must be run as user 'root' when using 'krb5' authentication"));
483 dbprintf(_("version %s\n"), VERSION);
484 for (i = 0; version_info[i] != NULL; i++) {
485 dbprintf(" %s", version_info[i]);
488 if (! (argc >= 1 && argv != NULL && argv[0] != NULL)) {
489 dbprintf(_("WARNING: argv[0] not defined: check inetd.conf\n"));
492 /* krb5 require the euid to be 0 */
493 if (strcasecmp(auth, "krb5") == 0) {
498 * Schedule to call protocol_accept() when new security handles
499 * are created on stdin.
501 security_accept(secdrv, amandad_get_security_conf, in, out, protocol_accept, NULL);
504 * Schedule an event that will try to exit every 30 seconds if there
505 * are no requests outstanding.
507 exit_event = event_register((event_id_t)30, EV_TIME, exit_check, &no_exit);
510 * Call event_loop() with an arg of 0, telling it to block until all
511 * events are completed.
522 * This runs periodically and checks to see if we have any active services
523 * still running. If we don't, then we quit.
531 assert(cookie != NULL);
532 no_exit = *(int *)cookie;
535 * If things are still running, then don't exit.
537 if (g_slist_length(serviceq) > 0)
541 * If the caller asked us to never exit, then we're done
546 g_debug("timeout exit");
552 * Handles new incoming protocol handles. This is a callback for
553 * security_accept(), which gets called when new handles are detected.
557 security_handle_t * handle,
562 struct active_service *as;
563 char *pktbody, *tok, *service, *arguments;
564 char *service_path = NULL;
565 GSList *errlist = NULL;
572 * If handle is NULL, then the connection is closed.
574 if (handle == NULL) {
575 if (exit_on_qlength && exit_event) {
576 /* remove the timeout, we will exit once the service terminate */
577 event_release(exit_event);
584 * If we have errors (not warnings) from the config file, let the remote system
585 * know immediately. Unfortunately, we only get one ERROR line, so if there
586 * are multiple errors, we just show the first.
588 if (config_errors(&errlist) >= CFGERR_ERRORS) {
589 GSList *iter = errlist;
591 gboolean multiple_errors = FALSE;
594 errmsg = (char *)iter->data;
596 multiple_errors = TRUE;
598 errmsg = "(no error message)";
601 pkt_init(&pkt_out, P_NAK, "ERROR %s%s", errmsg,
602 multiple_errors? _(" (additional errors not displayed)"):"");
603 do_sendpkt(handle, &pkt_out);
604 amfree(pkt_out.body);
605 security_close(handle);
609 peer_name = security_get_authenticated_peer_name(handle);
610 g_debug("authenticated peer name is '%s'", peer_name);
614 * If pkt is NULL, then there was a problem with the new connection.
617 dbprintf(_("accept error: %s\n"), security_geterror(handle));
618 pkt_init(&pkt_out, P_NAK, "ERROR %s\n", security_geterror(handle));
619 do_sendpkt(handle, &pkt_out);
620 amfree(pkt_out.body);
621 security_close(handle);
625 dbprintf(_("accept recv %s pkt:\n<<<<<\n%s>>>>>\n"),
626 pkt_type2str(pkt->type), pkt->body);
629 * If this is not a REQ packet, just forget about it.
631 if (pkt->type != P_REQ) {
632 dbprintf(_("received unexpected %s packet:\n<<<<<\n%s>>>>>\n\n"),
633 pkt_type2str(pkt->type), pkt->body);
634 security_close(handle);
638 pktbody = service = arguments = NULL;
642 * Parse out the service and arguments
645 pktbody = stralloc(pkt->body);
647 tok = strtok(pktbody, " ");
650 if (strcmp(tok, "SERVICE") != 0)
653 tok = strtok(NULL, " \n");
656 service = stralloc(tok);
658 /* we call everything else 'arguments' */
659 tok = strtok(NULL, "");
662 arguments = stralloc(tok);
664 /* see if it's one we allow */
665 for (i = 0; i < (int)NSERVICES; i++)
666 if (services[i].active == 1 && strcmp(services[i].name, service) == 0)
668 if (i == (int)NSERVICES) {
669 dbprintf(_("%s: invalid service\n"), service);
670 pkt_init(&pkt_out, P_NAK, _("ERROR %s: invalid service, add '%s' as argument to amandad\n"), service, service);
674 service_path = vstralloc(amlibexecdir, "/", service, NULL);
675 if (access(service_path, X_OK) < 0) {
676 dbprintf(_("can't execute %s: %s\n"), service_path, strerror(errno));
677 pkt_init(&pkt_out, P_NAK,
678 _("ERROR execute access to \"%s\" denied\n"),
683 /* see if its already running */
684 for (iter = serviceq; iter != NULL; iter = g_slist_next(iter)) {
685 as = (struct active_service *)iter->data;
686 if (strcmp(as->cmd, service_path) == 0 &&
687 strcmp(as->arguments, arguments) == 0) {
688 dbprintf(_("%s %s: already running, acking req\n"),
690 pkt_init_empty(&pkt_out, P_ACK);
691 goto send_pkt_out_no_delete;
696 * create a new service instance, and send the arguments down
699 dbprintf(_("creating new service: %s\n%s\n"), service, arguments);
700 as = service_new(handle, service_path, services[i].service, arguments);
701 if (writebuf(as, arguments, strlen(arguments)) < 0) {
702 const char *errmsg = strerror(errno);
703 dbprintf(_("error sending arguments to %s: %s\n"), service, errmsg);
704 pkt_init(&pkt_out, P_NAK, _("ERROR error writing arguments to %s: %s\n"),
712 amfree(service_path);
716 * Move to the sendack state, and start up the state
719 as->state = s_sendack;
720 state_machine(as, A_START, NULL);
724 pkt_init(&pkt_out, P_NAK, _("ERROR invalid REQ\n"));
725 dbprintf(_("received invalid %s packet:\n<<<<<\n%s>>>>>\n\n"),
726 pkt_type2str(pkt->type), pkt->body);
731 send_pkt_out_no_delete:
733 amfree(service_path);
736 do_sendpkt(handle, &pkt_out);
737 security_close(handle);
738 amfree(pkt_out.body);
742 * Handles incoming protocol packets. Routes responses to the proper
747 struct active_service * as,
755 amandad_debug(1, _("state_machine: %p entering\n"), as);
757 curstate = as->state;
758 amandad_debug(1, _("state_machine: %p curstate=%s action=%s\n"), as,
759 state2str(curstate), action2str(action));
760 retaction = (*curstate)(as, action, pkt);
761 amandad_debug(1, _("state_machine: %p curstate=%s returned %s (nextstate=%s)\n"),
762 as, state2str(curstate), action2str(retaction),
763 state2str(as->state));
767 * State has queued up and is now blocking on input.
770 amandad_debug(1, _("state_machine: %p leaving (A_PENDING)\n"), as);
774 * service has switched states. Loop.
780 * state has determined that the packet it received was bogus.
781 * Send a nak, and return.
784 dbprintf(_("received unexpected %s packet\n"),
785 pkt_type2str(pkt->type));
786 dbprintf(_("<<<<<\n%s----\n\n"), pkt->body);
787 pkt_init(&nak, P_NAK, _("ERROR unexpected packet type %s\n"),
788 pkt_type2str(pkt->type));
789 do_sendpkt(as->security_handle, &nak);
791 security_recvpkt(as->security_handle, protocol_recv, as, -1);
792 amandad_debug(1, _("state_machine: %p leaving (A_SENDNAK)\n"), as);
796 * Service is done. Remove it and finish.
799 amandad_debug(1, _("state_machine: %p leaving (A_FINISH)\n"), as);
812 * This state just sends an ack. After that, we move to the repwait
813 * state to wait for REP data to arrive from the subprocess.
817 struct active_service * as,
823 (void)action; /* Quiet unused parameter warning */
824 (void)pkt; /* Quiet unused parameter warning */
826 pkt_init_empty(&ack, P_ACK);
827 if (do_sendpkt(as->security_handle, &ack) < 0) {
828 dbprintf(_("error sending ACK: %s\n"),
829 security_geterror(as->security_handle));
836 * move to the repwait state
837 * Setup a listener for data on the reply fd, but also
838 * listen for packets over the wire, as the server may
839 * poll us if we take a long time.
840 * Setup a timeout that will fire if it takes too long to
843 as->state = s_repwait;
844 as->ev_repfd = event_register((event_id_t)as->repfd, EV_READFD, repfd_recv, as);
845 as->ev_reptimeout = event_register(REP_TIMEOUT, EV_TIME,
848 as->ev_errfd = event_register((event_id_t)as->errfd, EV_READFD, errfd_recv, as);
849 security_recvpkt(as->security_handle, protocol_recv, as, -1);
854 * This is the repwait state. We have responded to the initial REQ with
855 * an ACK, and we are now waiting for the process we spawned to pass us
856 * data to send in a REP.
860 struct active_service * as,
873 * We normally shouldn't receive any packets while waiting
874 * for our REP data, but in some cases we do.
876 if (action == A_RECVPKT) {
879 * Another req for something that's running. Just send an ACK
880 * and go back and wait for more data.
882 if (pkt->type == P_REQ) {
883 dbprintf(_("received dup P_REQ packet, ACKing it\n"));
884 amfree(as->rep_pkt.body);
885 pkt_init_empty(&as->rep_pkt, P_ACK);
886 do_sendpkt(as->security_handle, &as->rep_pkt);
887 security_recvpkt(as->security_handle, protocol_recv, as, -1);
890 /* something unexpected. Nak it */
894 if (action == A_TIMEOUT) {
895 amfree(as->rep_pkt.body);
896 pkt_init(&as->rep_pkt, P_NAK, _("ERROR timeout on reply pipe\n"));
897 dbprintf(_("%s timed out waiting for REP data\n"), as->cmd);
898 do_sendpkt(as->security_handle, &as->rep_pkt);
902 assert(action == A_RECVREP);
903 if(as->bufsize == 0) {
904 as->bufsize = NETWORK_BLOCK_BYTES;
905 as->repbuf = alloc(as->bufsize);
909 n = read(as->repfd, as->repbuf + as->repbufsize,
910 as->bufsize - as->repbufsize - 1);
911 } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
913 const char *errstr = strerror(errno);
914 dbprintf(_("read error on reply pipe: %s\n"), errstr);
915 amfree(as->rep_pkt.body);
916 pkt_init(&as->rep_pkt, P_NAK, _("ERROR read error on reply pipe: %s\n"),
918 do_sendpkt(as->security_handle, &as->rep_pkt);
922 /* If end of service, wait for process status */
924 pid = waitpid(as->pid, &retstat, WNOHANG);
925 if (as->service == SERVICE_NOOP ||
926 as->service == SERVICE_SENDSIZE ||
927 as->service == SERVICE_SELFCHECK) {
929 while (t<5 && pid == 0) {
932 pid = waitpid(as->pid, &retstat, WNOHANG);
939 pid = waitpid(as->pid, &retstat, WNOHANG);
943 if (! WIFEXITED(retstat)) {
945 code = WTERMSIG(retstat);
946 } else if (WEXITSTATUS(retstat) != 0) {
948 code = WEXITSTATUS(retstat);
951 dbprintf(_("service %s failed: pid %u exited with %s %d\n"),
952 (as->cmd)?as->cmd:_("??UNKONWN??"),
956 _("ERROR service %s failed: pid %u exited with %s %d\n"),
957 (as->cmd)?as->cmd:_("??UNKONWN??"), (unsigned)as->pid,
959 if (as->repbufsize + strlen(msg) >= (as->bufsize - 1)) {
961 repbuf_temp = alloc(as->bufsize);
962 memcpy(repbuf_temp, as->repbuf, as->repbufsize + 1);
964 as->repbuf = repbuf_temp;
966 strcpy(as->repbuf + as->repbufsize, msg);
967 as->repbufsize += strlen(msg);
974 * If we got some data, go back and wait for more, or EOF. Nul terminate
977 as->repbuf[n + as->repbufsize] = '\0';
980 if(as->repbufsize >= (as->bufsize - 1)) {
982 repbuf_temp = alloc(as->bufsize);
983 memcpy(repbuf_temp, as->repbuf, as->repbufsize + 1);
985 as->repbuf = repbuf_temp;
987 else if(as->send_partial_reply) {
988 amfree(as->rep_pkt.body);
989 pkt_init(&as->rep_pkt, P_PREP, "%s", as->repbuf);
990 do_sendpkt(as->security_handle, &as->rep_pkt);
991 amfree(as->rep_pkt.body);
992 pkt_init_empty(&as->rep_pkt, P_REP);
999 * If we got 0, then we hit EOF. Process the data and release
1004 assert(as->ev_repfd != NULL);
1005 event_release(as->ev_repfd);
1006 as->ev_repfd = NULL;
1008 assert(as->ev_reptimeout != NULL);
1009 event_release(as->ev_reptimeout);
1010 as->ev_reptimeout = NULL;
1012 as->state = s_processrep;
1014 return (A_CONTINUE);
1018 * After we have read in all of the rep data, we process it and send
1019 * it out as a REP packet.
1023 struct active_service * as,
1029 (void)action; /* Quiet unused parameter warning */
1030 (void)pkt; /* Quiet unused parameter warning */
1033 * Copy the rep lines into the outgoing packet.
1035 * If this line is a CONNECT, translate it
1036 * Format is "CONNECT <tag> <handle> <tag> <handle> etc...
1039 * CONNECT DATA 4 MESG 5 INDEX 6
1041 * The tags are arbitrary. The handles are in the DATA_FD pool.
1042 * We need to map these to security streams and pass them back
1043 * to the amanda server. If the handle is -1, then we don't map.
1045 if (strncmp_const(as->repbuf,"KENCRYPT\n") == 0) {
1046 amandad_kencrypt = KENCRYPT_WILL_DO;
1047 repbuf = stralloc(as->repbuf + 9);
1049 repbuf = stralloc(as->repbuf);
1051 amfree(as->rep_pkt.body);
1052 pkt_init_empty(&as->rep_pkt, P_REP);
1053 tok = strtok(repbuf, " ");
1056 if (strcmp(tok, "CONNECT") == 0) {
1057 char *line, *nextbuf;
1059 /* Save the entire line */
1060 line = strtok(NULL, "\n");
1061 /* Save the buf following the line */
1062 nextbuf = strtok(NULL, "");
1064 if (line == NULL || nextbuf == NULL)
1067 pkt_cat(&as->rep_pkt, "CONNECT");
1069 /* loop over the id/handle pairs */
1072 tok = strtok(line, " ");
1073 line = NULL; /* keep working from line */
1076 pkt_cat(&as->rep_pkt, " %s", tok);
1079 tok = strtok(NULL, " \n");
1082 /* convert the handle into something the server can process */
1083 pkt_cat(&as->rep_pkt, " %d", allocstream(as, atoi(tok)));
1085 pkt_cat(&as->rep_pkt, "\n%s", nextbuf);
1088 pkt_cat(&as->rep_pkt, "%s", as->repbuf);
1092 * We've setup our REP packet in as->rep_pkt. Now move to the transmission
1095 as->state = s_sendrep;
1096 as->repretry = getconf_int(CNF_REP_TRIES);
1098 return (A_CONTINUE);
1102 * This is the state where we send the REP we just collected from our child.
1106 struct active_service * as,
1110 (void)action; /* Quiet unused parameter warning */
1111 (void)pkt; /* Quiet unused parameter warning */
1114 * Transmit it and move to the ack state.
1116 do_sendpkt(as->security_handle, &as->rep_pkt);
1117 security_recvpkt(as->security_handle, protocol_recv, as, ACK_TIMEOUT);
1118 as->state = s_ackwait;
1123 * This is the state in which we wait for the server to ACK the REP
1128 struct active_service * as,
1132 struct datafd_handle *dh;
1136 * If we got a timeout, try again, but eventually give up.
1138 if (action == A_TIMEOUT) {
1139 if (--as->repretry > 0) {
1140 as->state = s_sendrep;
1141 return (A_CONTINUE);
1143 dbprintf(_("timeout waiting for ACK for our REP\n"));
1146 amandad_debug(1, _("received ACK, now opening streams\n"));
1148 assert(action == A_RECVPKT);
1150 if (pkt->type == P_REQ) {
1151 dbprintf(_("received dup P_REQ packet, resending REP\n"));
1152 as->state = s_sendrep;
1153 return (A_CONTINUE);
1156 if (pkt->type != P_ACK)
1159 if (amandad_kencrypt == KENCRYPT_WILL_DO) {
1160 amandad_kencrypt = KENCRYPT_YES;
1164 * Got the ack, now open the pipes
1166 for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1167 if (dh->netfd == NULL)
1169 dbprintf("opening security stream for fd %d\n", (int)(dh - as->data) + DATA_FD_OFFSET);
1170 if (security_stream_accept(dh->netfd) < 0) {
1171 dbprintf(_("stream %td accept failed: %s\n"),
1172 dh - &as->data[0], security_geterror(as->security_handle));
1173 security_stream_close(dh->netfd);
1178 /* setup an event for reads from it. As a special case, don't start
1179 * listening on as->data[0] until we read some data on another fd, if
1180 * the service is sendbackup. This ensures that we send a MESG or
1181 * INDEX token before any DATA tokens, as dumper assumes. This is a
1182 * hack, if that wasn't already obvious! */
1183 if (dh != &as->data[0] || as->service != SERVICE_SENDBACKUP) {
1184 dh->ev_read = event_register((event_id_t)dh->fd_read, EV_READFD,
1185 process_readnetfd, dh);
1187 amandad_debug(1, "Skipping registration of sendbackup's data FD\n");
1190 security_stream_read(dh->netfd, process_writenetfd, dh);
1195 * Pipes are open, so auth them. Count them at the same time.
1197 for (npipes = 0, dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1198 if (dh->netfd == NULL)
1200 if (security_stream_auth(dh->netfd) < 0) {
1201 security_stream_close(dh->netfd);
1203 event_release(dh->ev_read);
1204 event_release(dh->ev_write);
1206 dh->ev_write = NULL;
1213 * If no pipes are open, then we're done. Otherwise, just start running.
1214 * The event handlers on all of the pipes will take it from here.
1216 amandad_debug(1, _("at end of s_ackwait, npipes is %d\n"), npipes);
1220 security_close(as->security_handle);
1221 as->security_handle = NULL;
1227 * Called when a repfd has received data
1233 struct active_service *as = cookie;
1236 assert(as->ev_repfd != NULL);
1238 state_machine(as, A_RECVREP, NULL);
1245 struct active_service *as = cookie;
1247 /* Process errfd before sending the REP packet */
1249 SELECT_ARG_TYPE readset;
1253 memset(&tv, 0, SIZEOF(tv));
1255 FD_SET(as->errfd, &readset);
1256 nfound = select(as->errfd+1, &readset, NULL, NULL, &tv);
1257 if (nfound && FD_ISSET(as->errfd, &readset)) {
1264 * Called when a errfd has received data
1270 struct active_service *as = cookie;
1276 assert(as->ev_errfd != NULL);
1278 n = read(as->errfd, &buf, 32768);
1281 /* Terminate it with '\0' */
1285 as->errbuf = vstrextend(&as->errbuf, buf, NULL);
1287 as->errbuf = stralloc(buf);
1289 } else if (n == 0) {
1290 event_release(as->ev_errfd);
1291 as->ev_errfd = NULL;
1292 } else { /* n < 0 */
1293 event_release(as->ev_errfd);
1294 as->ev_errfd = NULL;
1295 g_snprintf(buf, 32768,
1296 "error reading stderr or service: %s\n", strerror(errno));
1299 /* for each line terminate by '\n' */
1300 while (as->errbuf != NULL && (r = strchr(as->errbuf, '\n')) != NULL) {
1304 s = vstrallocf("ERROR service %s: %s\n",
1305 services[as->service].name, as->errbuf);
1307 /* Add to repbuf, error message will be in the REP packet if it
1308 * is not already sent
1311 if (as->bufsize == 0) {
1312 as->bufsize = NETWORK_BLOCK_BYTES;
1313 as->repbuf = alloc(as->bufsize);
1315 while (as->bufsize < as->repbufsize + n) {
1318 repbuf_temp = alloc(as->bufsize);
1319 memcpy(repbuf_temp, as->repbuf, as->repbufsize + 1);
1321 as->repbuf = repbuf_temp;
1323 memcpy(as->repbuf + as->repbufsize, s, n);
1324 as->repbufsize += n;
1328 /* remove first line from buffer */
1337 * Called when a repfd has timed out
1343 struct active_service *as = cookie;
1346 assert(as->ev_reptimeout != NULL);
1348 state_machine(as, A_TIMEOUT, NULL);
1352 * Called when a handle has received data
1358 security_status_t status)
1360 struct active_service *as = cookie;
1366 dbprintf(_("received %s pkt:\n<<<<<\n%s>>>>>\n"),
1367 pkt_type2str(pkt->type), pkt->body);
1368 state_machine(as, A_RECVPKT, pkt);
1371 dbprintf(_("timeout\n"));
1372 state_machine(as, A_TIMEOUT, NULL);
1375 dbprintf(_("receive error: %s\n"),
1376 security_geterror(as->security_handle));
1382 * This is a generic relay function that just reads data from one of
1383 * the process's pipes and passes it up the equivalent security_stream_t
1390 struct datafd_handle *dh = cookie;
1391 struct active_service *as = dh->as;
1397 n = read(dh->fd_read, as->databuf, SIZEOF(as->databuf));
1398 } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
1404 pkt_init(&nak, P_NAK, _("A ERROR data descriptor %d broken: %s\n"),
1405 dh->fd_read, strerror(errno));
1409 * Process has closed the pipe. Just remove this event handler.
1410 * If all pipes are closed, shut down this service.
1413 event_release(dh->ev_read);
1415 if(dh->ev_write == NULL) {
1416 security_stream_close(dh->netfd);
1419 for (dh = &as->data[0]; dh < &as->data[DATA_FD_COUNT]; dh++) {
1420 if (dh->netfd != NULL)
1427 /* Handle the special case of recognizing "sendbackup info end"
1428 * from sendbackup's MESG fd */
1429 if (as->service == SERVICE_SENDBACKUP && !as->seen_info_end && dh == &as->data[1]) {
1430 /* make a buffer containing the combined data from info_end_buf
1431 * and what we've read this time, and search it for info_end_strj
1432 * This includes a NULL byte for strstr's sanity. */
1433 char *combined_buf = malloc(INFO_END_LEN + n + 1);
1434 memcpy(combined_buf, as->info_end_buf, INFO_END_LEN);
1435 memcpy(combined_buf+INFO_END_LEN, as->databuf, n);
1436 combined_buf[INFO_END_LEN+n] = '\0';
1438 as->seen_info_end = (strstr(combined_buf, info_end_str) != NULL);
1440 /* fill info_end_buf from the tail end of combined_buf */
1441 memcpy(as->info_end_buf, combined_buf + n, INFO_END_LEN);
1442 amfree(combined_buf);
1444 /* if we did see info_end_str, start reading the data fd (fd 0) */
1445 if (as->seen_info_end) {
1446 struct datafd_handle *dh = &as->data[0];
1447 amandad_debug(1, "Opening datafd to sendbackup (delayed until sendbackup sent header info)\n");
1448 dh->ev_read = event_register((event_id_t)dh->fd_read, EV_READFD,
1449 process_readnetfd, dh);
1451 amandad_debug(1, "sendbackup header info still not complete\n");
1455 if (security_stream_write(dh->netfd, as->databuf, (size_t)n) < 0) {
1456 /* stream has croaked */
1457 pkt_init(&nak, P_NAK, _("ERROR write error on stream %d: %s\n"),
1458 security_stream_id(dh->netfd),
1459 security_stream_geterror(dh->netfd));
1465 do_sendpkt(as->security_handle, &nak);
1471 * This is a generic relay function that just read data from one of
1472 * the security_stream_t and passes it up the equivalent process's pipes
1480 struct datafd_handle *dh;
1482 assert(cookie != NULL);
1485 if (dh->fd_write <= 0) {
1486 dbprintf(_("process_writenetfd: dh->fd_write <= 0\n"));
1487 } else if (size > 0) {
1488 full_write(dh->fd_write, buf, (size_t)size);
1490 aclose(dh->fd_write);
1496 * Convert a local stream handle (DATA_FD...) into something that
1497 * can be sent to the amanda server.
1499 * Returns a number that should be sent to the server in the REP packet.
1503 struct active_service * as,
1506 struct datafd_handle *dh;
1508 /* note that handle is in the range DATA_FD_OFFSET to DATA_FD_COUNT, but
1509 * it is NOT a file descriptor! */
1511 /* if the handle is -1, then we don't bother */
1515 /* make sure the handle's kosher */
1516 if (handle < DATA_FD_OFFSET || handle >= DATA_FD_OFFSET + DATA_FD_COUNT)
1519 /* get a pointer into our handle array */
1520 dh = &as->data[handle - DATA_FD_OFFSET];
1522 /* make sure we're not already using the net handle */
1523 if (dh->netfd != NULL)
1526 /* allocate a stream from the security layer and return */
1527 dh->netfd = security_stream_server(as->security_handle);
1528 if (dh->netfd == NULL) {
1529 dbprintf(_("couldn't open stream to server: %s\n"),
1530 security_geterror(as->security_handle));
1535 * convert the stream into a numeric id that can be sent to the
1538 return (security_stream_id(dh->netfd));
1542 * Create a new service instance
1544 static struct active_service *
1546 security_handle_t * security_handle,
1549 const char * arguments)
1552 int data_read[DATA_FD_COUNT + 2][2];
1553 int data_write[DATA_FD_COUNT + 2][2];
1554 struct active_service *as;
1558 char *amanda_remote_host_env[2];
1560 assert(security_handle != NULL);
1561 assert(cmd != NULL);
1562 assert(arguments != NULL);
1564 /* a plethora of pipes */
1565 /* data_read[0] : stdin
1566 * data_write[0] : stdout
1567 * data_read[1], data_write[1] : first stream
1568 * data_read[2], data_write[2] : second stream
1569 * data_read[3], data_write[3] : third stream
1570 * data_write[4] : stderr
1572 for (i = 0; i < DATA_FD_COUNT + 1; i++) {
1573 if (pipe(data_read[i]) < 0) {
1574 error(_("pipe: %s\n"), strerror(errno));
1577 if (pipe(data_write[i]) < 0) {
1578 error(_("pipe: %s\n"), strerror(errno));
1582 if (pipe(data_write[STDERR_PIPE]) < 0) {
1583 error(_("pipe: %s\n"), strerror(errno));
1587 switch(pid = fork()) {
1589 error(_("could not fork service %s: %s\n"), cmd, strerror(errno));
1593 * The parent. Close the far ends of our pipes and return.
1595 as = g_new0(struct active_service, 1);
1596 as->cmd = stralloc(cmd);
1597 as->arguments = stralloc(arguments);
1598 as->security_handle = security_handle;
1600 as->service = service;
1602 as->send_partial_reply = 0;
1603 as->seen_info_end = FALSE;
1604 /* fill in info_end_buf with non-null characters */
1605 memset(as->info_end_buf, '-', sizeof(as->info_end_buf));
1606 if(service == SERVICE_SENDSIZE) {
1607 g_option_t *g_options;
1608 char *option_str, *p;
1610 option_str = stralloc(as->arguments+8);
1611 p = strchr(option_str,'\n');
1614 g_options = parse_g_options(option_str, 1);
1615 if(am_has_feature(g_options->features, fe_partial_estimate)) {
1616 as->send_partial_reply = 1;
1618 free_g_options(g_options);
1622 /* write to the request pipe */
1623 aclose(data_read[0][0]);
1624 as->reqfd = data_read[0][1];
1627 * read from the reply pipe
1629 as->repfd = data_write[0][0];
1630 aclose(data_write[0][1]);
1631 as->ev_repfd = NULL;
1636 as->rep_pkt.body = NULL;
1639 * read from the stderr pipe
1641 as->errfd = data_write[STDERR_PIPE][0];
1642 aclose(data_write[STDERR_PIPE][1]);
1643 as->ev_errfd = NULL;
1647 * read from the rest of the general-use pipes
1648 * (netfds are opened as the client requests them)
1650 for (i = 0; i < DATA_FD_COUNT; i++) {
1651 aclose(data_read[i + 1][1]);
1652 aclose(data_write[i + 1][0]);
1653 as->data[i].fd_read = data_read[i + 1][0];
1654 as->data[i].fd_write = data_write[i + 1][1];
1655 as->data[i].ev_read = NULL;
1656 as->data[i].ev_write = NULL;
1657 as->data[i].netfd = NULL;
1658 as->data[i].as = as;
1661 /* add it to the service queue */
1662 /* increment the active service count */
1663 serviceq = g_slist_append(serviceq, (gpointer)as);
1668 * The child. Put our pipes in their advertised locations
1672 /* set up the AMANDA_AUTHENTICATED_PEER env var so child services
1673 * can use it to authenticate */
1674 peer_name = security_get_authenticated_peer_name(security_handle);
1675 amanda_remote_host_env[0] = NULL;
1676 amanda_remote_host_env[1] = NULL;
1678 amanda_remote_host_env[0] =
1679 g_strdup_printf("AMANDA_AUTHENTICATED_PEER=%s", peer_name);
1683 * The data stream is stdin in the new process
1685 if (dup2(data_read[0][0], 0) < 0) {
1686 error(_("dup %d to %d failed: %s\n"), data_read[0][0], 0,
1690 aclose(data_read[0][0]);
1691 aclose(data_read[0][1]);
1694 * The reply stream is stdout
1696 if (dup2(data_write[0][1], 1) < 0) {
1697 error(_("dup %d to %d failed: %s\n"), data_write[0][1], 1,
1700 aclose(data_write[0][0]);
1701 aclose(data_write[0][1]);
1703 for (i = 0; i < DATA_FD_COUNT; i++) {
1704 aclose(data_read[i + 1][0]);
1705 aclose(data_write[i + 1][1]);
1709 * Make sure they are not open in the range DATA_FD_OFFSET to
1710 * DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1
1712 for (i = 0; i < DATA_FD_COUNT; i++) {
1713 while(data_read[i + 1][1] >= DATA_FD_OFFSET &&
1714 data_read[i + 1][1] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1715 newfd = dup(data_read[i + 1][1]);
1717 error(_("Can't dup out off DATA_FD range"));
1718 data_read[i + 1][1] = newfd;
1720 while(data_write[i + 1][0] >= DATA_FD_OFFSET &&
1721 data_write[i + 1][0] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1722 newfd = dup(data_write[i + 1][0]);
1724 error(_("Can't dup out off DATA_FD range"));
1725 data_write[i + 1][0] = newfd;
1728 while(data_write[4][0] >= DATA_FD_OFFSET &&
1729 data_write[4][0] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1730 newfd = dup(data_write[4][0]);
1732 error(_("Can't dup out off DATA_FD range"));
1733 data_write[4][0] = newfd;
1735 while(data_write[4][1] >= DATA_FD_OFFSET &&
1736 data_write[4][1] <= DATA_FD_OFFSET + DATA_FD_COUNT*2 - 1) {
1737 newfd = dup(data_write[4][1]);
1739 error(_("Can't dup out off DATA_FD range"));
1740 data_write[4][1] = newfd;
1743 for (i = 0; i < DATA_FD_COUNT*2; i++)
1744 close(DATA_FD_OFFSET + i);
1747 * The rest start at the offset defined in amandad.h, and continue
1748 * through the internal defined.
1750 for (i = 0; i < DATA_FD_COUNT; i++) {
1751 if (dup2(data_read[i + 1][1], i*2 + DATA_FD_OFFSET) < 0) {
1752 error(_("dup %d to %d failed: %s\n"), data_read[i + 1][1],
1753 i + DATA_FD_OFFSET, strerror(errno));
1755 aclose(data_read[i + 1][1]);
1757 if (dup2(data_write[i + 1][0], i*2 + 1 + DATA_FD_OFFSET) < 0) {
1758 error(_("dup %d to %d failed: %s\n"), data_write[i + 1][0],
1759 i + DATA_FD_OFFSET, strerror(errno));
1761 aclose(data_write[i + 1][0]);
1764 /* close all unneeded fd */
1765 close(STDERR_FILENO);
1766 dup2(data_write[STDERR_PIPE][1], 2);
1767 aclose(data_write[STDERR_PIPE][0]);
1768 aclose(data_write[STDERR_PIPE][1]);
1769 safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);
1771 execle(cmd, cmd, "amandad", auth, (char *)NULL, safe_env_full(amanda_remote_host_env));
1772 error(_("could not exec service %s: %s\n"), cmd, strerror(errno));
1779 * Unallocate a service instance
1783 struct active_service * as)
1788 struct datafd_handle *dh;
1790 amandad_debug(1, _("closing service: %s\n"),
1791 (as->cmd)?as->cmd:_("??UNKONWN??"));
1795 assert(as->cmd != NULL);
1798 assert(as->arguments != NULL);
1799 amfree(as->arguments);
1801 if (as->reqfd != -1)
1803 if (as->repfd != -1)
1805 if (as->errfd != -1) {
1810 if (as->ev_repfd != NULL)
1811 event_release(as->ev_repfd);
1812 if (as->ev_reptimeout != NULL)
1813 event_release(as->ev_reptimeout);
1814 if (as->ev_errfd != NULL)
1815 event_release(as->ev_errfd);
1817 for (i = 0; i < DATA_FD_COUNT; i++) {
1820 aclose(dh->fd_read);
1821 aclose(dh->fd_write);
1823 if (dh->netfd != NULL)
1824 security_stream_close(dh->netfd);
1826 if (dh->ev_read != NULL)
1827 event_release(dh->ev_read);
1828 if (dh->ev_write != NULL)
1829 event_release(dh->ev_write);
1832 if (as->security_handle != NULL)
1833 security_close(as->security_handle);
1835 /* try to kill the process; if this fails, then it's already dead and
1836 * likely some of the other zombie cleanup ate its brains, so we don't
1837 * bother to waitpid for it */
1838 assert(as->pid > 0);
1839 pid = waitpid(as->pid, NULL, WNOHANG);
1840 if (pid != as->pid && kill(as->pid, SIGTERM) == 0) {
1841 pid = waitpid(as->pid, NULL, WNOHANG);
1843 while (pid != as->pid && count > 0) {
1846 pid = waitpid(as->pid, NULL, WNOHANG);
1848 if (pid != as->pid) {
1849 g_debug("Process %d failed to exit", (int)as->pid);
1853 serviceq = g_slist_remove(serviceq, (gpointer)as);
1856 amfree(as->arguments);
1858 amfree(as->rep_pkt.body);
1861 if(exit_on_qlength == 0 && g_slist_length(serviceq) == 0) {
1868 * Like 'fullwrite', but does the work in a child process so pipelines
1873 struct active_service * as,
1880 switch (pid=fork()) {
1885 waitpid(pid, NULL, WNOHANG);
1886 return 0; /* this is the parent */
1888 case 0: /* this is the child */
1890 writesize = full_write(as->reqfd, bufp, size);
1891 exit(writesize != size);
1899 security_handle_t * handle,
1902 dbprintf(_("sending %s pkt:\n<<<<<\n%s>>>>>\n"),
1903 pkt_type2str(pkt->type), pkt->body);
1905 return security_sendpkt(handle, pkt);
1911 * Convert a state into a string
1917 static const struct {
1921 #define X(state) { state, stringize(state) }
1931 for (i = 0; i < (int)(sizeof(states) / sizeof(states[0])); i++)
1932 if (state == states[i].state)
1933 return (states[i].str);
1934 return (_("INVALID STATE"));
1938 * Convert an action into a string
1944 static const struct {
1948 #define X(action) { action, stringize(action) }
1961 for (i = 0; i < (int)(sizeof(actions) / sizeof(actions[0])); i++)
1962 if (action == actions[i].action)
1963 return (actions[i].str);
1964 return (_("UNKNOWN ACTION"));
1968 amandad_get_security_conf(
1972 (void)arg; /* Quiet unused parameter warning */
1974 if (!string || !*string)
1977 if (strcmp(string, "kencrypt")==0) {
1978 if (amandad_kencrypt == KENCRYPT_YES)