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