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"
39 static int copy_stream = 0;
40 static time_t conf_ctimeout;
41 static am_feature_t *our_features = NULL;
42 static char *our_feature_string = NULL;
43 static int remote_errors = 0;
44 static event_handle_t *event_in;
45 static security_stream_t *fd;
50 void client_protocol(char *hostname, char *auth, char *service,
52 void client_first_stream(security_handle_t *sech, int port_num);
53 int main(int argc, char **argv);
54 static void read_in(void *cookie);
56 static void read_server(void *cookie, void *buf, ssize_t size);
61 error(_("Usage: amservice [-o configoption]* [-f input_file [-s]] host auth service"));
70 config_overrides_t *cfg_ovr;
79 int got_input_file = 0;
82 * Configure program for internationalization:
83 * 1) Only set the message locale for now.
84 * 2) Set textdomain for all amanda related programs to "amanda"
85 * We don't want to be forced to support dozens of message catalogs.
87 setlocale(LC_MESSAGES, "C");
93 set_pname("amservice");
94 /* drop root privileges */
95 if (!set_root_privs(0)) {
96 error(_("amservice must be run setuid root"));
99 /* Don't die when child closes pipe */
100 signal(SIGPIPE, SIG_IGN);
102 dbopen(DBG_SUBDIR_SERVER);
104 add_amanda_log_handler(amanda_log_stderr);
106 our_features = am_init_feature_set();
107 our_feature_string = am_feature_to_string(our_features);
109 /* process arguments */
111 cfg_ovr = new_config_overrides(argc/2);
113 while((opt = getopt(argc, argv, "o:f:s")) != EOF) {
115 case 'o': add_config_override_opt(cfg_ovr, optarg);
117 case 'f': got_input_file = 1;
118 if (*optarg == '/') {
119 input_file = fopen(optarg, "r");
121 char *name = vstralloc(get_original_cwd(), "/",
123 input_file = fopen(name, "r");
127 g_critical("Cannot open output file '%s': %s",
128 optarg, strerror(errno));
130 case 's': use_connect = 1;
135 if (use_connect && !got_input_file) {
136 g_critical("The -s option require -f");
139 argc -= optind, argv += optind;
140 if(argc < 3) usage();
142 /* set a default config */
143 set_config_overrides(cfg_ovr);
144 config_init(CONFIG_INIT_CLIENT, NULL);
145 dbrename(get_config_name(), DBG_SUBDIR_SERVER);
147 if (config_errors(NULL) >= CFGERR_WARNINGS) {
148 config_print_errors();
149 if (config_errors(NULL) >= CFGERR_ERRORS) {
150 g_critical(_("errors processing config file"));
154 conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
160 /* start client side checks */
162 copy_stream = use_connect && got_input_file;
163 client_protocol(hostname, auth, service, input_file);
165 amfree(our_feature_string);
166 am_release_feature_set(our_features);
170 return(remote_errors != 0);
173 /* --------------------------------------------------- */
175 static void handle_result(void *, pkt_t *, security_handle_t *);
176 void start_host(char *hostname, char *auth, char *req);
184 const security_driver_t *secdrv;
185 secdrv = security_getdriver(auth);
186 if (secdrv == NULL) {
187 fprintf(stderr, _("Could not find security driver \"%s\".\n"), auth);
189 protocol_sendreq(hostname, secdrv, generic_client_get_security_conf,
190 req, conf_ctimeout, handle_result, NULL);
204 req = g_strdup_printf("SERVICE %s\nOPTIONS features=%s\n",
205 service, our_feature_string);
207 while(fgets(req1, 1024, input_file) != NULL) {
208 vstrextend(&req, req1, NULL);
212 start_host(hostname, auth, req);
218 amfree(our_feature_string);
225 void *datap G_GNUC_UNUSED,
227 security_handle_t *sech)
237 _("Request failed: %s\n"), security_geterror(sech));
246 skip_quoted_line(s, ch);
252 g_debug("REP: %s\n", line);
254 fprintf(stdout, "%s\n", line);
256 if (strncmp(line, "CONNECT ", 8) == 0) {
257 char *port = strchr(line, ' ');
259 port = strchr(port+1, ' ');
261 port_num = atoi(port+1);
264 } else if (strncmp(line, "ERROR ", 6) == 0) {
266 fprintf(stdout, "%s\n", line);
276 client_first_stream(sech, port_num);
278 fprintf(stdout, "\n");
285 security_handle_t *sech,
290 g_critical("The service did not ask to open stream, do not use '-s' with that service");
293 fd = security_stream_client(sech, port_num);
295 g_critical("Could not connect to stream: %s\n", security_stream_geterror(fd));
297 if (security_stream_auth(fd) < 0) {
298 g_critical("could not authenticate stream: %s\n", security_stream_geterror(fd));
301 printf("Connected\n");
302 /* read from stdin */
303 event_in = event_register((event_id_t)0, EV_READFD, read_in, NULL);
305 /* read from connected stream */
306 security_stream_read(fd, read_server, NULL);
312 void *cookie G_GNUC_UNUSED)
317 event_release(event_in);
318 nread = read(0, buf, 1024);
320 security_stream_close(fd);
325 security_stream_write(fd, buf, nread);
326 event_in = event_register((event_id_t)0, EV_READFD, read_in, NULL);
331 void * cookie G_GNUC_UNUSED,
337 case 0: security_stream_close(fd);
338 event_release(event_in);
341 full_write(1, buf, size);
343 g_debug("failed to write to stdout: %s", strerror(errno));
345 security_stream_read(fd, read_server, NULL);