2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-2000 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.
28 * $Id: amservice.c 11167 2008-05-06 11:53:54Z martineau $
30 * Take the REQ packet in stdin and output the REP packet in stdout
37 #include "amfeatures.h"
41 static struct option long_options[] = {
42 {"version" , 0, NULL, 1},
46 static int copy_stream = 0;
47 static time_t conf_ctimeout;
48 static am_feature_t *our_features = NULL;
49 static char *our_feature_string = NULL;
50 static int remote_errors = 0;
51 static event_handle_t *event_in;
52 static security_stream_t *fd;
57 void client_protocol(char *hostname, char *auth, char *service,
59 void client_first_stream(security_handle_t *sech, int port_num);
60 int main(int argc, char **argv);
61 static void read_in(void *cookie);
63 static void read_server(void *cookie, void *buf, ssize_t size);
68 error(_("Usage: amservice [--version] [-o configoption]* [-f input_file [-s]] host auth service"));
77 config_overrides_t *cfg_ovr;
86 int got_input_file = 0;
89 * Configure program for internationalization:
90 * 1) Only set the message locale for now.
91 * 2) Set textdomain for all amanda related programs to "amanda"
92 * We don't want to be forced to support dozens of message catalogs.
94 setlocale(LC_MESSAGES, "C");
100 set_pname("amservice");
101 /* drop root privileges */
102 if (!set_root_privs(0)) {
103 error(_("amservice must be run setuid root"));
106 /* Don't die when child closes pipe */
107 signal(SIGPIPE, SIG_IGN);
109 dbopen(DBG_SUBDIR_SERVER);
111 add_amanda_log_handler(amanda_log_stderr);
113 our_features = am_init_feature_set();
114 our_feature_string = am_feature_to_string(our_features);
116 /* process arguments */
118 cfg_ovr = new_config_overrides(argc/2);
120 while((opt = getopt_long(argc, argv, "o:f:s", long_options, NULL)) != EOF) {
122 case 1: printf("amservice-%s\n", VERSION);
125 case 'o': add_config_override_opt(cfg_ovr, optarg);
127 case 'f': got_input_file = 1;
128 if (*optarg == '/') {
129 input_file = fopen(optarg, "r");
131 char *name = vstralloc(get_original_cwd(), "/",
133 input_file = fopen(name, "r");
137 g_critical("Cannot open output file '%s': %s",
138 optarg, strerror(errno));
140 case 's': use_connect = 1;
145 if (use_connect && !got_input_file) {
146 g_critical("The -s option require -f");
149 argc -= optind, argv += optind;
150 if(argc < 3) usage();
152 /* set a default config */
153 set_config_overrides(cfg_ovr);
154 config_init(CONFIG_INIT_CLIENT, NULL);
155 dbrename(get_config_name(), DBG_SUBDIR_SERVER);
157 if (config_errors(NULL) >= CFGERR_WARNINGS) {
158 config_print_errors();
159 if (config_errors(NULL) >= CFGERR_ERRORS) {
160 g_critical(_("errors processing config file"));
164 conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
170 /* start client side checks */
172 copy_stream = use_connect && got_input_file;
173 client_protocol(hostname, auth, service, input_file);
175 amfree(our_feature_string);
176 am_release_feature_set(our_features);
180 return(remote_errors != 0);
183 /* --------------------------------------------------- */
185 static void handle_result(void *, pkt_t *, security_handle_t *);
186 void start_host(char *hostname, char *auth, char *req);
194 const security_driver_t *secdrv;
195 secdrv = security_getdriver(auth);
196 if (secdrv == NULL) {
197 fprintf(stderr, _("Could not find security driver \"%s\".\n"), auth);
199 protocol_sendreq(hostname, secdrv, generic_client_get_security_conf,
200 req, conf_ctimeout, handle_result, NULL);
214 req = g_strdup_printf("SERVICE %s\nOPTIONS features=%s\n",
215 service, our_feature_string);
217 while(fgets(req1, 1024, input_file) != NULL) {
218 vstrextend(&req, req1, NULL);
222 start_host(hostname, auth, req);
228 amfree(our_feature_string);
235 void *datap G_GNUC_UNUSED,
237 security_handle_t *sech)
247 _("Request failed: %s\n"), security_geterror(sech));
256 skip_quoted_line(s, ch);
262 g_debug("REP: %s\n", line);
264 fprintf(stdout, "%s\n", line);
266 if (strncmp(line, "CONNECT ", 8) == 0) {
267 char *port = strchr(line, ' ');
269 port = strchr(port+1, ' ');
271 port_num = atoi(port+1);
274 } else if (strncmp(line, "ERROR ", 6) == 0) {
276 fprintf(stdout, "%s\n", line);
286 client_first_stream(sech, port_num);
288 fprintf(stdout, "\n");
295 security_handle_t *sech,
300 g_critical("The service did not ask to open stream, do not use '-s' with that service");
303 fd = security_stream_client(sech, port_num);
305 g_critical("Could not connect to stream: %s\n", security_stream_geterror(fd));
307 if (security_stream_auth(fd) < 0) {
308 g_critical("could not authenticate stream: %s\n", security_stream_geterror(fd));
311 printf("Connected\n");
312 /* read from stdin */
313 event_in = event_register((event_id_t)0, EV_READFD, read_in, NULL);
315 /* read from connected stream */
316 security_stream_read(fd, read_server, NULL);
322 void *cookie G_GNUC_UNUSED)
327 nread = read(0, buf, 1024);
329 event_release(event_in);
330 security_stream_close(fd);
335 security_stream_write(fd, buf, nread);
340 void * cookie G_GNUC_UNUSED,
346 case 0: security_stream_close(fd);
347 event_release(event_in);
350 full_write(1, buf, size);
352 g_debug("failed to write to stdout: %s", strerror(errno));