/*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-1999 University of Maryland at College Park
+ * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
SERVICE_SENDBACKUP,
SERVICE_SELFCHECK,
SERVICE_AMINDEXD,
- SERVICE_AMIDXTAPED
+ SERVICE_AMIDXTAPED,
+ SERVICE_AMDUMPD
} service_t;
static struct services {
{ "sendbackup", 1, SERVICE_SENDBACKUP },
{ "selfcheck", 1, SERVICE_SELFCHECK },
{ "amindexd", 0, SERVICE_AMINDEXD },
- { "amidxtaped", 0, SERVICE_AMIDXTAPED }
+ { "amidxtaped", 0, SERVICE_AMIDXTAPED },
+ { "amdumpd", 0, SERVICE_AMDUMPD }
};
#define NSERVICES (int)(sizeof(services) / sizeof(services[0]))
*/
GSList *serviceq = NULL;
-static int wait_30s = 1;
+static event_handle_t *exit_event;
static int exit_on_qlength = 1;
static char *auth = NULL;
static kencrypt_type amandad_kencrypt = KENCRYPT_NONE;
safe_fd(-1, 0);
safe_cd();
+ /*
+ * Nexenta needs the SUN_PERSONALITY env variable to be unset, otherwise
+ * the Sun version of tar in /usr/sun/sbin/tar is called instead.
+ *
+ * On other operating systems this will have no effect.
+ */
+
+#ifdef HAVE_UNSETENV
+ unsetenv("SUN_PERSONALITY");
+#endif
+
/*
* When called via inetd, it is not uncommon to forget to put the
* argv[0] value on the config line. On some systems (e.g. Solaris)
/*NOTREACHED*/
}
+ if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
+ printf("amandad-%s\n", VERSION);
+ return (0);
+ }
+
/* Don't die when child closes pipe */
signal(SIGPIPE, SIG_IGN);
error(_("no driver for security type '%s'\n"), argv[i]);
/*NOTREACHED*/
}
+ if (strcmp(auth, "local") == 0 ||
+ strcmp(auth, "rsh") == 0 ||
+ strcmp(auth, "ssh") == 0) {
+ int i;
+ for (i=0; i < NSERVICES; i++) {
+ services[i].active = 1;
+ }
+ }
continue;
}
}
/*
- * If no security type specified, use BSD
+ * If no security type specified, use BSDTCP
*/
if (secdrv == NULL) {
- secdrv = security_getdriver("BSD");
- auth = "bsd";
+ secdrv = security_getdriver("BSDTCP");
+ auth = "bsdtcp";
if (secdrv == NULL) {
- error(_("no driver for default security type 'BSD'\n"));
+ error(_("no driver for default security type 'BSDTCP'\n"));
/*NOTREACHED*/
}
}
strcasecmp(auth, "ssh") == 0 ||
strcasecmp(auth, "local") == 0 ||
strcasecmp(auth, "bsdtcp") == 0) {
- wait_30s = 0;
exit_on_qlength = 1;
}
* Schedule an event that will try to exit every 30 seconds if there
* are no requests outstanding.
*/
- if(wait_30s)
- (void)event_register((event_id_t)30, EV_TIME, exit_check, &no_exit);
+ exit_event = event_register((event_id_t)30, EV_TIME, exit_check, &no_exit);
/*
* Call event_loop() with an arg of 0, telling it to block until all
if (no_exit)
return;
+ g_debug("timeout exit");
dbclose();
exit(0);
}
char *service_path = NULL;
GSList *errlist = NULL;
int i;
+ char *peer_name;
pkt_out.body = NULL;
/*
* If handle is NULL, then the connection is closed.
*/
- if(handle == NULL) {
+ if (handle == NULL) {
+ if (exit_on_qlength && exit_event) {
+ /* remove the timeout, we will exit once the service terminate */
+ event_release(exit_event);
+ exit_event = NULL;
+ }
return;
}
/*
- * If we have errors (not warnings) from the config file, let the server
+ * If we have errors (not warnings) from the config file, let the remote system
* know immediately. Unfortunately, we only get one ERROR line, so if there
* are multiple errors, we just show the first.
*/
return;
}
+ peer_name = security_get_authenticated_peer_name(handle);
+ g_debug("authenticated peer name is '%s'", peer_name);
+ amfree(peer_name);
+
/*
* If pkt is NULL, then there was a problem with the new connection.
*/
/* fill info_end_buf from the tail end of combined_buf */
memcpy(as->info_end_buf, combined_buf + n, INFO_END_LEN);
+ amfree(combined_buf);
/* if we did see info_end_str, start reading the data fd (fd 0) */
if (as->seen_info_end) {
dbprintf(_("process_writenetfd: dh->fd_write <= 0\n"));
} else if (size > 0) {
full_write(dh->fd_write, buf, (size_t)size);
- security_stream_read(dh->netfd, process_writenetfd, dh);
- }
- else {
+ } else {
aclose(dh->fd_write);
}
}
struct active_service *as;
pid_t pid;
int newfd;
+ char *peer_name;
+ char *amanda_remote_host_env[2];
assert(security_handle != NULL);
assert(cmd != NULL);
* and start up.
*/
+ /* set up the AMANDA_AUTHENTICATED_PEER env var so child services
+ * can use it to authenticate */
+ peer_name = security_get_authenticated_peer_name(security_handle);
+ amanda_remote_host_env[0] = NULL;
+ amanda_remote_host_env[1] = NULL;
+ if (*peer_name) {
+ amanda_remote_host_env[0] =
+ g_strdup_printf("AMANDA_AUTHENTICATED_PEER=%s", peer_name);
+ }
+
/*
* The data stream is stdin in the new process
*/
aclose(data_write[STDERR_PIPE][1]);
safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);
- execle(cmd, cmd, "amandad", auth, (char *)NULL, safe_env());
+ execle(cmd, cmd, "amandad", auth, (char *)NULL, safe_env_full(amanda_remote_host_env));
error(_("could not exec service %s: %s\n"), cmd, strerror(errno));
/*NOTREACHED*/
}
if (as->security_handle != NULL)
security_close(as->security_handle);
+ /* try to kill the process; if this fails, then it's already dead and
+ * likely some of the other zombie cleanup ate its brains, so we don't
+ * bother to waitpid for it */
assert(as->pid > 0);
- kill(as->pid, SIGTERM);
pid = waitpid(as->pid, NULL, WNOHANG);
- count = 5;
- while (pid != as->pid && count > 0) {
- count--;
- sleep(1);
+ if (pid != as->pid && kill(as->pid, SIGTERM) == 0) {
pid = waitpid(as->pid, NULL, WNOHANG);
- }
- if (pid != as->pid) {
- g_debug("Process %d failed to exit", (int)as->pid);
+ count = 5;
+ while (pid != as->pid && count > 0) {
+ count--;
+ sleep(1);
+ pid = waitpid(as->pid, NULL, WNOHANG);
+ }
+ if (pid != as->pid) {
+ g_debug("Process %d failed to exit", (int)as->pid);
+ }
}
serviceq = g_slist_remove(serviceq, (gpointer)as);