Imported Upstream version 2.6.1
[debian/amanda] / server-src / amservice.c
diff --git a/server-src/amservice.c b/server-src/amservice.c
new file mode 100644 (file)
index 0000000..22c98c7
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Amanda, The Advanced Maryland Automatic Network Disk Archiver
+ * Copyright (c) 1991-2000 University of Maryland at College Park
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: the Amanda Development Team.  Its members are listed in a
+ * file named AUTHORS, in the root directory of this distribution.
+ */
+/*
+ * $Id: amservice.c 11167 2008-05-06 11:53:54Z martineau $
+ *
+ * Take the REQ packet in stdin and output the REP packet in stdout
+ */
+#include "amanda.h"
+#include "util.h"
+#include "conffile.h"
+#include "packet.h"
+#include "protocol.h"
+#include "version.h"
+#include "server_util.h"
+#include "amfeatures.h"
+
+static time_t conf_ctimeout;
+static am_feature_t *our_features = NULL;
+static char *our_feature_string = NULL;
+static int remote_errors = 0;
+
+/* local functions */
+
+void usage(void);
+void client_protocol(char *hostname, char *auth, char *service, FILE *input_file);
+int main(int argc, char **argv);
+
+void
+usage(void)
+{
+    error(_("Usage: amservice%s [-o configoption]* [-f input_file] host auth service"),
+         versionsuffix());
+    /*NOTREACHED*/
+}
+
+int
+main(
+    int                argc,
+    char **    argv)
+{
+    config_overwrites_t *cfg_ovr;
+    char *hostname;
+    char *auth;
+    char *service;
+    int opt;
+    extern int optind;
+    extern char *optarg;
+    FILE *input_file;
+
+    /*
+     * Configure program for internationalization:
+     *   1) Only set the message locale for now.
+     *   2) Set textdomain for all amanda related programs to "amanda"
+     *      We don't want to be forced to support dozens of message catalogs.
+     */  
+    setlocale(LC_MESSAGES, "C");
+    textdomain("amanda"); 
+
+    safe_fd(-1, 0);
+    safe_cd();
+
+    set_pname("amservice");
+    /* drop root privileges */
+    if (!set_root_privs(0)) {
+       error(_("amservice must be run setuid root"));
+    }
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    dbopen(DBG_SUBDIR_SERVER);
+
+    erroutput_type = ERR_INTERACTIVE;
+
+    our_features = am_init_feature_set();
+    our_feature_string = am_feature_to_string(our_features);
+
+    /* process arguments */
+
+    cfg_ovr = new_config_overwrites(argc/2);
+    input_file = stdin;
+    while((opt = getopt(argc, argv, "o:f:")) != EOF) {
+       switch(opt) {
+       case 'o':       add_config_overwrite_opt(cfg_ovr, optarg);
+                       break;
+       case 'f':       if (*optarg == '/') {
+                           input_file = fopen(optarg, "r");
+                       } else {
+                           char *name = vstralloc(get_original_cwd(), "/",
+                                                  optarg, NULL);
+                           input_file = fopen(name, "r");
+                           amfree(name);
+                       }
+                       if (!input_file)
+                           g_critical("Cannot open output file '%s': %s",
+                               optarg, strerror(errno));
+                       break;
+       }
+    }
+
+    argc -= optind, argv += optind;
+    if(argc < 3) usage();
+
+    /* set a default config */
+    config_init(CONFIG_INIT_CLIENT, NULL);
+    apply_config_overwrites(cfg_ovr);
+    dbrename(get_config_name(), DBG_SUBDIR_SERVER);
+
+    if (config_errors(NULL) >= CFGERR_WARNINGS) {
+       config_print_errors();
+       if (config_errors(NULL) >= CFGERR_ERRORS) {
+           g_critical(_("errors processing config file"));
+       }
+    }
+
+    conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
+
+    hostname = argv[0];
+    auth = argv[1];
+    service = argv[2];
+
+    /* start client side checks */
+
+    client_protocol(hostname, auth, service, input_file);
+
+    amfree(our_feature_string);
+    am_release_feature_set(our_features);
+    our_features = NULL;
+
+    dbclose();
+    return(remote_errors != 0);
+}
+
+/* --------------------------------------------------- */
+
+static void handle_result(void *, pkt_t *, security_handle_t *);
+void start_host(char *hostname, char *auth, char *req);
+
+void
+start_host(
+    char *hostname,
+    char *auth,
+    char *req)
+{
+    const security_driver_t *secdrv;
+    secdrv = security_getdriver(auth);
+    if (secdrv == NULL) {
+       fprintf(stderr, _("Could not find security driver \"%s\".\n"), auth);
+    } else {
+       protocol_sendreq(hostname, secdrv, amhost_get_security_conf, 
+                        req, conf_ctimeout, handle_result, NULL);
+    }
+
+}
+
+void
+client_protocol(
+    char *hostname,
+    char *auth,
+    char *service,
+    FILE *input_file)
+{
+    char *req, *req1;
+
+    req = g_strdup_printf("SERVICE %s\nOPTIONS features=%s\n",
+                         service, our_feature_string);
+    req1 = malloc(1024);
+    while(fgets(req1, 1024, input_file) != NULL) {
+       vstrextend(&req, req1, NULL);
+    }
+    protocol_init();
+
+    start_host(hostname, auth, req);
+
+    protocol_run();
+
+    fflush(stdout);
+
+    amfree(our_feature_string);
+
+    return;
+}
+
+static void
+handle_result(
+    G_GNUC_UNUSED void *datap,
+    pkt_t *            pkt,
+    security_handle_t *        sech)
+{
+    char *line;
+    char *s;
+    int ch;
+
+    if (pkt == NULL) {
+       g_fprintf(stdout,
+                 _("Request failed: %s\n"), security_geterror(sech));
+       remote_errors++;
+       return;
+    }
+
+    s = pkt->body;
+    ch = *s++;
+    while(ch) {
+       line = s - 1;
+       skip_quoted_line(s, ch);
+       if (s[-2] == '\n') {
+           s[-2] = '\0';
+       }
+
+       fprintf(stdout, "%s\n", line);
+    }
+    fprintf(stdout, "\n");
+}