2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-2000 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: amservice.c 11167 2008-05-06 11:53:54Z martineau $
29 * Take the REQ packet in stdin and output the REP packet in stdout
36 #include "amfeatures.h"
40 static struct option long_options[] = {
41 {"version" , 0, NULL, 1},
45 static int copy_stream = 0;
46 static time_t conf_ctimeout;
47 static am_feature_t *our_features = NULL;
48 static char *our_feature_string = NULL;
49 static int remote_errors = 0;
50 static event_handle_t *event_in;
51 static security_stream_t *fd;
56 void client_protocol(char *hostname, char *auth, char *service,
58 void client_first_stream(security_handle_t *sech, int port_num);
59 int main(int argc, char **argv);
60 static void read_in(void *cookie);
62 static void read_server(void *cookie, void *buf, ssize_t size);
67 error(_("Usage: amservice [--version] [-o configoption]* [-f input_file [-s]] host auth service"));
76 config_overrides_t *cfg_ovr;
85 int got_input_file = 0;
88 * Configure program for internationalization:
89 * 1) Only set the message locale for now.
90 * 2) Set textdomain for all amanda related programs to "amanda"
91 * We don't want to be forced to support dozens of message catalogs.
93 setlocale(LC_MESSAGES, "C");
99 set_pname("amservice");
100 /* drop root privileges */
101 if (!set_root_privs(0)) {
102 error(_("amservice must be run setuid root"));
105 /* Don't die when child closes pipe */
106 signal(SIGPIPE, SIG_IGN);
108 dbopen(DBG_SUBDIR_SERVER);
110 add_amanda_log_handler(amanda_log_stderr);
112 our_features = am_init_feature_set();
113 our_feature_string = am_feature_to_string(our_features);
115 /* process arguments */
117 cfg_ovr = new_config_overrides(argc/2);
119 while((opt = getopt_long(argc, argv, "o:f:s", long_options, NULL)) != EOF) {
121 case 1: printf("amservice-%s\n", VERSION);
124 case 'o': add_config_override_opt(cfg_ovr, optarg);
126 case 'f': got_input_file = 1;
127 if (*optarg == '/') {
128 input_file = fopen(optarg, "r");
130 char *name = vstralloc(get_original_cwd(), "/",
132 input_file = fopen(name, "r");
136 g_critical("Cannot open output file '%s': %s",
137 optarg, strerror(errno));
139 case 's': use_connect = 1;
144 if (use_connect && !got_input_file) {
145 g_critical("The -s option require -f");
148 argc -= optind, argv += optind;
149 if(argc < 3) usage();
151 /* set a default config */
152 set_config_overrides(cfg_ovr);
153 config_init(CONFIG_INIT_CLIENT, NULL);
154 dbrename(get_config_name(), DBG_SUBDIR_SERVER);
156 if (config_errors(NULL) >= CFGERR_WARNINGS) {
157 config_print_errors();
158 if (config_errors(NULL) >= CFGERR_ERRORS) {
159 g_critical(_("errors processing config file"));
163 conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
169 /* start client side checks */
171 copy_stream = use_connect && got_input_file;
172 client_protocol(hostname, auth, service, input_file);
174 amfree(our_feature_string);
175 am_release_feature_set(our_features);
179 return(remote_errors != 0);
182 /* --------------------------------------------------- */
184 static void handle_result(void *, pkt_t *, security_handle_t *);
185 void start_host(char *hostname, char *auth, char *req);
193 const security_driver_t *secdrv;
194 secdrv = security_getdriver(auth);
195 if (secdrv == NULL) {
196 fprintf(stderr, _("Could not find security driver \"%s\".\n"), auth);
198 protocol_sendreq(hostname, secdrv, generic_client_get_security_conf,
199 req, conf_ctimeout, handle_result, NULL);
213 req = g_strdup_printf("SERVICE %s\nOPTIONS features=%s\n",
214 service, our_feature_string);
216 while(fgets(req1, 1024, input_file) != NULL) {
217 vstrextend(&req, req1, NULL);
221 start_host(hostname, auth, req);
227 amfree(our_feature_string);
234 void *datap G_GNUC_UNUSED,
236 security_handle_t *sech)
246 _("Request failed: %s\n"), security_geterror(sech));
255 skip_quoted_line(s, ch);
261 g_debug("REP: %s\n", line);
263 fprintf(stdout, "%s\n", line);
265 if (strncmp(line, "CONNECT ", 8) == 0) {
266 char *port = strchr(line, ' ');
268 port = strchr(port+1, ' ');
270 port_num = atoi(port+1);
273 } else if (strncmp(line, "ERROR ", 6) == 0) {
275 fprintf(stdout, "%s\n", line);
285 client_first_stream(sech, port_num);
287 fprintf(stdout, "\n");
294 security_handle_t *sech,
299 g_critical("The service did not ask to open stream, do not use '-s' with that service");
302 fd = security_stream_client(sech, port_num);
304 g_critical("Could not connect to stream: %s\n", security_stream_geterror(fd));
306 if (security_stream_auth(fd) < 0) {
307 g_critical("could not authenticate stream: %s\n", security_stream_geterror(fd));
310 printf("Connected\n");
311 /* read from stdin */
312 event_in = event_register((event_id_t)0, EV_READFD, read_in, NULL);
314 /* read from connected stream */
315 security_stream_read(fd, read_server, NULL);
321 void *cookie G_GNUC_UNUSED)
326 event_release(event_in);
327 nread = read(0, buf, 1024);
329 security_stream_close(fd);
334 security_stream_write(fd, buf, nread);
335 event_in = event_register((event_id_t)0, EV_READFD, read_in, NULL);
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));
354 security_stream_read(fd, read_server, NULL);