Imported Upstream version 3.2.1
[debian/amanda] / server-src / amservice.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-2000 University of Maryland at College Park
4  * All Rights Reserved.
5  *
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.
15  *
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.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: amservice.c 11167 2008-05-06 11:53:54Z martineau $
28  *
29  * Take the REQ packet in stdin and output the REP packet in stdout
30  */
31 #include "amanda.h"
32 #include "util.h"
33 #include "conffile.h"
34 #include "packet.h"
35 #include "protocol.h"
36 #include "server_util.h"
37 #include "amfeatures.h"
38
39 static time_t conf_ctimeout;
40 static am_feature_t *our_features = NULL;
41 static char *our_feature_string = NULL;
42 static int remote_errors = 0;
43
44 /* local functions */
45
46 void usage(void);
47 void client_protocol(char *hostname, char *auth, char *service, FILE *input_file);
48 int main(int argc, char **argv);
49
50 void
51 usage(void)
52 {
53     error(_("Usage: amservice [-o configoption]* [-f input_file] host auth service"));
54     /*NOTREACHED*/
55 }
56
57 int
58 main(
59     int         argc,
60     char **     argv)
61 {
62     config_overrides_t *cfg_ovr;
63     char *hostname;
64     char *auth;
65     char *service;
66     int opt;
67     extern int optind;
68     extern char *optarg;
69     FILE *input_file;
70
71     /*
72      * Configure program for internationalization:
73      *   1) Only set the message locale for now.
74      *   2) Set textdomain for all amanda related programs to "amanda"
75      *      We don't want to be forced to support dozens of message catalogs.
76      */  
77     setlocale(LC_MESSAGES, "C");
78     textdomain("amanda"); 
79
80     safe_fd(-1, 0);
81     safe_cd();
82
83     set_pname("amservice");
84     /* drop root privileges */
85     if (!set_root_privs(0)) {
86         error(_("amservice must be run setuid root"));
87     }
88
89     /* Don't die when child closes pipe */
90     signal(SIGPIPE, SIG_IGN);
91
92     dbopen(DBG_SUBDIR_SERVER);
93
94     add_amanda_log_handler(amanda_log_stderr);
95
96     our_features = am_init_feature_set();
97     our_feature_string = am_feature_to_string(our_features);
98
99     /* process arguments */
100
101     cfg_ovr = new_config_overrides(argc/2);
102     input_file = stdin;
103     while((opt = getopt(argc, argv, "o:f:")) != EOF) {
104         switch(opt) {
105         case 'o':       add_config_override_opt(cfg_ovr, optarg);
106                         break;
107         case 'f':       if (*optarg == '/') {
108                             input_file = fopen(optarg, "r");
109                         } else {
110                             char *name = vstralloc(get_original_cwd(), "/",
111                                                    optarg, NULL);
112                             input_file = fopen(name, "r");
113                             amfree(name);
114                         }
115                         if (!input_file)
116                             g_critical("Cannot open output file '%s': %s",
117                                 optarg, strerror(errno));
118                         break;
119         }
120     }
121
122     argc -= optind, argv += optind;
123     if(argc < 3) usage();
124
125     /* set a default config */
126     set_config_overrides(cfg_ovr);
127     config_init(CONFIG_INIT_CLIENT, NULL);
128     dbrename(get_config_name(), DBG_SUBDIR_SERVER);
129
130     if (config_errors(NULL) >= CFGERR_WARNINGS) {
131         config_print_errors();
132         if (config_errors(NULL) >= CFGERR_ERRORS) {
133             g_critical(_("errors processing config file"));
134         }
135     }
136
137     conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
138
139     hostname = argv[0];
140     auth = argv[1];
141     service = argv[2];
142
143     /* start client side checks */
144
145     client_protocol(hostname, auth, service, input_file);
146
147     amfree(our_feature_string);
148     am_release_feature_set(our_features);
149     our_features = NULL;
150
151     dbclose();
152     return(remote_errors != 0);
153 }
154
155 /* --------------------------------------------------- */
156
157 static void handle_result(void *, pkt_t *, security_handle_t *);
158 void start_host(char *hostname, char *auth, char *req);
159
160 void
161 start_host(
162     char *hostname,
163     char *auth,
164     char *req)
165 {
166     const security_driver_t *secdrv;
167     secdrv = security_getdriver(auth);
168     if (secdrv == NULL) {
169         fprintf(stderr, _("Could not find security driver \"%s\".\n"), auth);
170     } else {
171         protocol_sendreq(hostname, secdrv, amhost_get_security_conf, 
172                          req, conf_ctimeout, handle_result, NULL);
173     }
174
175 }
176
177 void
178 client_protocol(
179     char *hostname,
180     char *auth,
181     char *service,
182     FILE *input_file)
183 {
184     char *req, *req1;
185
186     req = g_strdup_printf("SERVICE %s\nOPTIONS features=%s\n",
187                           service, our_feature_string);
188     req1 = malloc(1024);
189     while(fgets(req1, 1024, input_file) != NULL) {
190         vstrextend(&req, req1, NULL);
191     }
192     protocol_init();
193
194     start_host(hostname, auth, req);
195
196     protocol_run();
197
198     fflush(stdout);
199
200     amfree(our_feature_string);
201
202     return;
203 }
204
205 static void
206 handle_result(
207     G_GNUC_UNUSED void *datap,
208     pkt_t *             pkt,
209     security_handle_t * sech)
210 {
211     char *line;
212     char *s;
213     int ch;
214
215     if (pkt == NULL) {
216         g_fprintf(stdout,
217                   _("Request failed: %s\n"), security_geterror(sech));
218         remote_errors++;
219         return;
220     }
221
222     s = pkt->body;
223     ch = *s++;
224     while(ch) {
225         line = s - 1;
226         skip_quoted_line(s, ch);
227         if (s[-2] == '\n') {
228             s[-2] = '\0';
229         }
230
231         fprintf(stdout, "%s\n", line);
232     }
233     fprintf(stdout, "\n");
234 }