Imported Upstream version 3.3.3
[debian/amanda] / server-src / dumper.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1999 University of Maryland at College Park
4  * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
5  * All Rights Reserved.
6  *
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.
16  *
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.
23  *
24  * Authors: the Amanda Development Team.  Its members are listed in a
25  * file named AUTHORS, in the root directory of this distribution.
26  */
27 /* $Id: dumper.c,v 1.190 2006/08/30 19:53:57 martinea Exp $
28  *
29  * requests remote amandad processes to dump filesystems
30  */
31 #include "amanda.h"
32 #include "amindex.h"
33 #include "arglist.h"
34 #include "clock.h"
35 #include "conffile.h"
36 #include "event.h"
37 #include "logfile.h"
38 #include "packet.h"
39 #include "protocol.h"
40 #include "security.h"
41 #include "stream.h"
42 #include "fileheader.h"
43 #include "amfeatures.h"
44 #include "server_util.h"
45 #include "util.h"
46 #include "timestamp.h"
47 #include "amxml.h"
48
49 #define dumper_debug(i,x) do {          \
50         if ((i) <= debug_dumper) {      \
51             dbprintf(x);                \
52         }                               \
53 } while (0)
54
55 #ifndef SEEK_SET
56 #define SEEK_SET 0
57 #endif
58
59 #ifndef SEEK_CUR
60 #define SEEK_CUR 1
61 #endif
62
63 #define CONNECT_TIMEOUT 5*60
64
65 #define STARTUP_TIMEOUT 60
66
67 struct databuf {
68     int fd;                     /* file to flush to */
69     char *buf;
70     char *datain;               /* data buffer markers */
71     char *dataout;
72     char *datalimit;
73     pid_t compresspid;          /* valid if fd is pipe to compress */
74     pid_t encryptpid;           /* valid if fd is pipe to encrypt */
75 };
76
77 struct databuf *g_databuf = NULL;
78
79 typedef struct filter_s {
80     int             fd;
81     char           *name;
82     char           *buffer;
83     gint64          first;           /* first byte used */
84     gint64          size;            /* number of byte use in the buffer */
85     gint64          allocated_size ; /* allocated size of the buffer     */
86     event_handle_t *event;
87 } filter_t;
88
89 static char *handle = NULL;
90
91 static char *errstr = NULL;
92 static off_t dumpbytes;
93 static off_t dumpsize, headersize, origsize;
94
95 static comp_t srvcompress = COMP_NONE;
96 char *srvcompprog = NULL;
97 char *clntcompprog = NULL;
98
99 static encrypt_t srvencrypt = ENCRYPT_NONE;
100 char *srv_encrypt = NULL;
101 char *clnt_encrypt = NULL;
102 char *srv_decrypt_opt = NULL;
103 char *clnt_decrypt_opt = NULL;
104 static kencrypt_type dumper_kencrypt;
105
106 static FILE *errf = NULL;
107 static char *hostname = NULL;
108 am_feature_t *their_features = NULL;
109 static char *diskname = NULL;
110 static char *qdiskname = NULL, *b64disk;
111 static char *device = NULL, *b64device;
112 static char *options = NULL;
113 static char *progname = NULL;
114 static char *amandad_path=NULL;
115 static char *client_username=NULL;
116 static char *client_port=NULL;
117 static char *ssh_keys=NULL;
118 static char *auth=NULL;
119 static data_path_t data_path=DATA_PATH_AMANDA;
120 static char *dataport_list = NULL;
121 static int level;
122 static char *dumpdate = NULL;
123 static char *dumper_timestamp = NULL;
124 static time_t conf_dtimeout;
125 static int indexfderror;
126 static int set_datafd;
127 static char *dle_str = NULL;
128 static char *errfname = NULL;
129 static int   errf_lines = 0;
130 static int   max_warnings = 0;
131
132 static dumpfile_t file;
133
134 static struct {
135     const char *name;
136     security_stream_t *fd;
137 } streams[] = {
138 #define DATAFD  0
139     { "DATA", NULL },
140 #define MESGFD  1
141     { "MESG", NULL },
142 #define INDEXFD 2
143     { "INDEX", NULL },
144 };
145 #define NSTREAMS        (int)(sizeof(streams) / sizeof(streams[0]))
146
147 static am_feature_t *our_features = NULL;
148 static char *our_feature_string = NULL;
149
150 /* buffer to keep partial line from the MESG stream */
151 static struct {
152     char *buf;          /* buffer holding msg data */
153     size_t size;        /* size of alloced buffer */
154 } msg = { NULL, 0 };
155
156
157 /* local functions */
158 int             main(int, char **);
159 static int      do_dump(struct databuf *);
160 static void     check_options(char *);
161 static void     xml_check_options(char *optionstr);
162 static void     finish_tapeheader(dumpfile_t *);
163 static ssize_t  write_tapeheader(int, dumpfile_t *);
164 static void     databuf_init(struct databuf *, int);
165 static int      databuf_write(struct databuf *, const void *, size_t);
166 static int      databuf_flush(struct databuf *);
167 static void     process_dumpeof(void);
168 static void     process_dumpline(const char *);
169 static void     add_msg_data(const char *, size_t);
170 static void     parse_info_line(char *);
171 static int      log_msgout(logtype_t);
172 static char *   dumper_get_security_conf (char *, void *);
173
174 static int      runcompress(int, pid_t *, comp_t, char *);
175 static int      runencrypt(int, pid_t *,  encrypt_t);
176
177 static void     sendbackup_response(void *, pkt_t *, security_handle_t *);
178 static int      startup_dump(const char *, const char *, const char *, int,
179                         const char *, const char *, const char *,
180                         const char *, const char *, const char *,
181                         const char *, const char *);
182 static void     stop_dump(void);
183
184 static void     read_indexfd(void *, void *, ssize_t);
185 static void     read_datafd(void *, void *, ssize_t);
186 static void     read_mesgfd(void *, void *, ssize_t);
187 static void     timeout(time_t);
188 static void     timeout_callback(void *);
189
190 static void
191 check_options(
192     char *options)
193 {
194   char *compmode = NULL;
195   char *compend  = NULL;
196   char *encryptmode = NULL;
197   char *encryptend = NULL;
198   char *decryptmode = NULL;
199   char *decryptend = NULL;
200
201     /* parse the compression option */
202     if (strstr(options, "srvcomp-best;") != NULL) 
203       srvcompress = COMP_BEST;
204     else if (strstr(options, "srvcomp-fast;") != NULL)
205       srvcompress = COMP_FAST;
206     else if ((compmode = strstr(options, "srvcomp-cust=")) != NULL) {
207         compend = strchr(compmode, ';');
208         if (compend ) {
209             srvcompress = COMP_SERVER_CUST;
210             *compend = '\0';
211             srvcompprog = stralloc(compmode + strlen("srvcomp-cust="));
212             *compend = ';';
213         }
214     } else if ((compmode = strstr(options, "comp-cust=")) != NULL) {
215         compend = strchr(compmode, ';');
216         if (compend) {
217             srvcompress = COMP_CUST;
218             *compend = '\0';
219             clntcompprog = stralloc(compmode + strlen("comp-cust="));
220             *compend = ';';
221         }
222     }
223     else {
224       srvcompress = COMP_NONE;
225     }
226     
227
228     /* now parse the encryption option */
229     if ((encryptmode = strstr(options, "encrypt-serv-cust=")) != NULL) {
230       encryptend = strchr(encryptmode, ';');
231       if (encryptend) {
232             srvencrypt = ENCRYPT_SERV_CUST;
233             *encryptend = '\0';
234             srv_encrypt = stralloc(encryptmode + strlen("encrypt-serv-cust="));
235             *encryptend = ';';
236       }
237     } else if ((encryptmode = strstr(options, "encrypt-cust=")) != NULL) {
238       encryptend = strchr(encryptmode, ';');
239       if (encryptend) {
240             srvencrypt = ENCRYPT_CUST;
241             *encryptend = '\0';
242             clnt_encrypt = stralloc(encryptmode + strlen("encrypt-cust="));
243             *encryptend = ';';
244       }
245     } else {
246       srvencrypt = ENCRYPT_NONE;
247     }
248     /* get the decryption option parameter */
249     if ((decryptmode = strstr(options, "server-decrypt-option=")) != NULL) {
250       decryptend = strchr(decryptmode, ';');
251       if (decryptend) {
252         *decryptend = '\0';
253         srv_decrypt_opt = stralloc(decryptmode + strlen("server-decrypt-option="));
254         *decryptend = ';';
255       }
256     } else if ((decryptmode = strstr(options, "client-decrypt-option=")) != NULL) {
257       decryptend = strchr(decryptmode, ';');
258       if (decryptend) {
259         *decryptend = '\0';
260         clnt_decrypt_opt = stralloc(decryptmode + strlen("client-decrypt-option="));
261         *decryptend = ';';
262       }
263     }
264
265     if (strstr(options, "kencrypt;") != NULL) {
266         dumper_kencrypt = KENCRYPT_WILL_DO;
267     } else {
268         dumper_kencrypt = KENCRYPT_NONE;
269     }
270 }
271
272
273 static void
274 xml_check_options(
275     char *optionstr)
276 {
277     char *o, *oo;
278     char *errmsg = NULL;
279     dle_t *dle;
280
281     o = oo = vstralloc("<dle>", strchr(optionstr,'<'), "</dle>", NULL);
282
283     dle = amxml_parse_node_CHAR(o, &errmsg);
284     if (dle == NULL) {
285         error("amxml_parse_node_CHAR failed: %s\n", errmsg);
286     }
287
288     if (dle->compress == COMP_SERVER_FAST) {
289         srvcompress = COMP_FAST;
290     } else if (dle->compress == COMP_SERVER_BEST) {
291         srvcompress = COMP_BEST;
292     } else if (dle->compress == COMP_SERVER_CUST) {
293         srvcompress = COMP_SERVER_CUST;
294         srvcompprog = g_strdup(dle->compprog);
295     } else if (dle->compress == COMP_CUST) {
296         srvcompress = COMP_CUST;
297         clntcompprog = g_strdup(dle->compprog);
298     } else {
299         srvcompress = COMP_NONE;
300     }
301
302     if (dle->encrypt == ENCRYPT_CUST) {
303         srvencrypt = ENCRYPT_CUST;
304         clnt_encrypt = g_strdup(dle->clnt_encrypt);
305         clnt_decrypt_opt = g_strdup(dle->clnt_decrypt_opt);
306     } else if (dle->encrypt == ENCRYPT_SERV_CUST) {
307         srvencrypt = ENCRYPT_SERV_CUST;
308         srv_encrypt = g_strdup(dle->srv_encrypt);
309         srv_decrypt_opt = g_strdup(dle->srv_decrypt_opt);
310     } else {
311         srvencrypt = ENCRYPT_NONE;
312     }
313     free_dle(dle);
314     amfree(o);
315 }
316
317
318 int
319 main(
320     int         argc,
321     char **     argv)
322 {
323     static struct databuf db;
324     struct cmdargs *cmdargs = NULL;
325     int outfd = -1;
326     int rc;
327     in_port_t header_port;
328     char *q = NULL;
329     int a;
330     int res;
331     config_overrides_t *cfg_ovr = NULL;
332     char *cfg_opt = NULL;
333     int dumper_setuid;
334
335     if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
336         printf("dumper-%s\n", VERSION);
337         return (0);
338     }
339
340     /*
341      * Configure program for internationalization:
342      *   1) Only set the message locale for now.
343      *   2) Set textdomain for all amanda related programs to "amanda"
344      *      We don't want to be forced to support dozens of message catalogs.
345      */  
346     setlocale(LC_MESSAGES, "C");
347     textdomain("amanda"); 
348
349     /* drop root privileges */
350     dumper_setuid = set_root_privs(0);
351
352     safe_fd(-1, 0);
353
354     set_pname("dumper");
355
356     dbopen(DBG_SUBDIR_SERVER);
357
358     /* Don't die when child closes pipe */
359     signal(SIGPIPE, SIG_IGN);
360
361     add_amanda_log_handler(amanda_log_stderr);
362     add_amanda_log_handler(amanda_log_trace_log);
363
364     cfg_ovr = extract_commandline_config_overrides(&argc, &argv);
365     if (argc > 1)
366         cfg_opt = argv[1];
367     set_config_overrides(cfg_ovr);
368     config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt);
369
370     if (!dumper_setuid) {
371         error(_("dumper must be run setuid root"));
372     }
373
374     if (config_errors(NULL) >= CFGERR_ERRORS) {
375         g_critical(_("errors processing config file"));
376     }
377
378     safe_cd(); /* do this *after* config_init() */
379
380     check_running_as(RUNNING_AS_ROOT | RUNNING_AS_UID_ONLY);
381
382     dbrename(get_config_name(), DBG_SUBDIR_SERVER);
383
384     our_features = am_init_feature_set();
385     our_feature_string = am_feature_to_string(our_features);
386
387     log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid());
388     g_fprintf(stderr,
389             _("%s: pid %ld executable %s version %s\n"),
390             get_pname(), (long) getpid(),
391             argv[0], VERSION);
392     fflush(stderr);
393
394     /* now, make sure we are a valid user */
395
396     signal(SIGPIPE, SIG_IGN);
397
398     conf_dtimeout = (time_t)getconf_int(CNF_DTIMEOUT);
399
400     protocol_init();
401
402     do {
403         if (cmdargs)
404             free_cmdargs(cmdargs);
405         cmdargs = getcmd();
406
407         amfree(errstr);
408         switch(cmdargs->cmd) {
409         case START:
410             if(cmdargs->argc <  2)
411                 error(_("error [dumper START: not enough args: timestamp]"));
412             dumper_timestamp = newstralloc(dumper_timestamp, cmdargs->argv[1]);
413             break;
414
415         case ABORT:
416             break;
417
418         case QUIT:
419             break;
420
421         case PORT_DUMP:
422             /*
423              * PORT-DUMP
424              *   handle
425              *   port
426              *   host
427              *   features
428              *   disk
429              *   device
430              *   level
431              *   dumpdate
432              *   progname
433              *   amandad_path
434              *   client_username
435              *   client_port
436              *   ssh_keys
437              *   security_driver
438              *   data_path
439              *   dataport_list
440              *   options
441              */
442             a = 1; /* skip "PORT-DUMP" */
443
444             if(a >= cmdargs->argc) {
445                 error(_("error [dumper PORT-DUMP: not enough args: handle]"));
446                 /*NOTREACHED*/
447             }
448             handle = newstralloc(handle, cmdargs->argv[a++]);
449
450             if(a >= cmdargs->argc) {
451                 error(_("error [dumper PORT-DUMP: not enough args: port]"));
452                 /*NOTREACHED*/
453             }
454             header_port = (in_port_t)atoi(cmdargs->argv[a++]);
455
456             if(a >= cmdargs->argc) {
457                 error(_("error [dumper PORT-DUMP: not enough args: hostname]"));
458                 /*NOTREACHED*/
459             }
460             hostname = newstralloc(hostname, cmdargs->argv[a++]);
461
462             if(a >= cmdargs->argc) {
463                 error(_("error [dumper PORT-DUMP: not enough args: features]"));
464                 /*NOTREACHED*/
465             }
466             am_release_feature_set(their_features);
467             their_features = am_string_to_feature(cmdargs->argv[a++]);
468
469             if(a >= cmdargs->argc) {
470                 error(_("error [dumper PORT-DUMP: not enough args: diskname]"));
471                 /*NOTREACHED*/
472             }
473             diskname = newstralloc(diskname, cmdargs->argv[a++]);
474             if (qdiskname != NULL)
475                 amfree(qdiskname);
476             qdiskname = quote_string(diskname);
477             b64disk = amxml_format_tag("disk", diskname);
478
479             if(a >= cmdargs->argc) {
480                 error(_("error [dumper PORT-DUMP: not enough args: device]"));
481                 /*NOTREACHED*/
482             }
483             device = newstralloc(device, cmdargs->argv[a++]);
484             b64device = amxml_format_tag("diskdevice", device);
485             if(strcmp(device,"NODEVICE") == 0)
486                 amfree(device);
487
488             if(a >= cmdargs->argc) {
489                 error(_("error [dumper PORT-DUMP: not enough args: level]"));
490                 /*NOTREACHED*/
491             }
492             level = atoi(cmdargs->argv[a++]);
493
494             if(a >= cmdargs->argc) {
495                 error(_("error [dumper PORT-DUMP: not enough args: dumpdate]"));
496                 /*NOTREACHED*/
497             }
498             dumpdate = newstralloc(dumpdate, cmdargs->argv[a++]);
499
500             if(a >= cmdargs->argc) {
501                 error(_("error [dumper PORT-DUMP: not enough args: program]"));
502                 /*NOTREACHED*/
503             }
504             progname = newstralloc(progname, cmdargs->argv[a++]);
505
506             if(a >= cmdargs->argc) {
507                 error(_("error [dumper PORT-DUMP: not enough args: amandad_path]"));
508                 /*NOTREACHED*/
509             }
510             amandad_path = newstralloc(amandad_path, cmdargs->argv[a++]);
511
512             if(a >= cmdargs->argc) {
513                 error(_("error [dumper PORT-DUMP: not enough args: client_username]"));
514             }
515             client_username = newstralloc(client_username, cmdargs->argv[a++]);
516
517             if(a >= cmdargs->argc) {
518                 error(_("error [dumper PORT-DUMP: not enough args: client_port]"));
519             }
520             client_port = newstralloc(client_port, cmdargs->argv[a++]);
521
522             if(a >= cmdargs->argc) {
523                 error(_("error [dumper PORT-DUMP: not enough args: ssh_keys]"));
524             }
525             ssh_keys = newstralloc(ssh_keys, cmdargs->argv[a++]);
526
527             if(a >= cmdargs->argc) {
528                 error(_("error [dumper PORT-DUMP: not enough args: auth]"));
529             }
530             auth = newstralloc(auth, cmdargs->argv[a++]);
531
532             if(a >= cmdargs->argc) {
533                 error(_("error [dumper PORT-DUMP: not enough args: data_path]"));
534             }
535             data_path = data_path_from_string(cmdargs->argv[a++]);
536
537             if(a >= cmdargs->argc) {
538                 error(_("error [dumper PORT-DUMP: not enough args: dataport_list]"));
539             }
540             dataport_list = newstralloc(dataport_list, cmdargs->argv[a++]);
541
542             if(a >= cmdargs->argc) {
543                 error(_("error [dumper PORT-DUMP: not enough args: max_warnings]"));
544             }
545             max_warnings = atoi(cmdargs->argv[a++]);
546
547             if(a >= cmdargs->argc) {
548                 error(_("error [dumper PORT-DUMP: not enough args: options]"));
549             }
550             options = newstralloc(options, cmdargs->argv[a++]);
551
552             if(a != cmdargs->argc) {
553                 error(_("error [dumper PORT-DUMP: too many args: %d != %d]"),
554                       cmdargs->argc, a);
555                 /*NOTREACHED*/
556             }
557
558             /* Double-check that 'localhost' resolves properly */
559             if ((res = resolve_hostname("localhost", 0, NULL, NULL) != 0)) {
560                 errstr = newvstrallocf(errstr,
561                                      _("could not resolve localhost: %s"),
562                                      gai_strerror(res));
563                 q = quote_string(errstr);
564                 putresult(FAILED, "%s %s\n", handle, q);
565                 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
566                         dumper_timestamp, level, errstr);
567                 amfree(q);
568                 break;
569             }
570
571             /* connect outf to chunker/taper port */
572
573             g_debug(_("Sending header to localhost:%d\n"), header_port);
574             outfd = stream_client("localhost", header_port,
575                                   STREAM_BUFSIZE, 0, NULL, 0);
576             if (outfd == -1) {
577                 
578                 errstr = newvstrallocf(errstr, _("port open: %s"),
579                                       strerror(errno));
580                 q = quote_string(errstr);
581                 putresult(FAILED, "%s %s\n", handle, q);
582                 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
583                         dumper_timestamp, level, errstr);
584                 amfree(q);
585                 break;
586             }
587             databuf_init(&db, outfd);
588             g_databuf = &db;
589
590             if (am_has_feature(their_features, fe_req_xml))
591                 xml_check_options(options); /* note: modifies globals */
592             else
593                 check_options(options); /* note: modifies globals */
594
595             rc = startup_dump(hostname,
596                               diskname,
597                               device,
598                               level,
599                               dumpdate,
600                               progname,
601                               amandad_path,
602                               client_username,
603                               client_port,
604                               ssh_keys,
605                               auth,
606                               options);
607             if (rc != 0) {
608                 q = quote_string(errstr);
609                 putresult(rc == 2? FAILED : TRYAGAIN, "%s %s\n",
610                     handle, q);
611                 if (rc == 2)
612                     log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
613                         dumper_timestamp, level, errstr);
614                 amfree(q);
615             } else {
616                 do_dump(&db);
617                 /* try to clean up any defunct processes, since Amanda doesn't
618                    wait() for them explicitly */
619                 while(waitpid(-1, NULL, WNOHANG)> 0);
620             }
621
622             amfree(amandad_path);
623             amfree(client_username);
624             amfree(client_port);
625             amfree(device);
626             amfree(b64device);
627             amfree(qdiskname);
628             amfree(b64disk);
629
630             break;
631
632         default:
633             if(cmdargs->argc >= 1) {
634                 q = quote_string(cmdargs->argv[0]);
635             } else {
636                 q = stralloc(_("(no input?)"));
637             }
638             putresult(BAD_COMMAND, "%s\n", q);
639             amfree(q);
640             break;
641         }
642
643         if (outfd != -1)
644             aclose(outfd);
645     } while(cmdargs->cmd != QUIT);
646     free_cmdargs(cmdargs);
647
648     log_add(L_INFO, "pid-done %ld", (long)getpid());
649
650     am_release_feature_set(our_features);
651     amfree(our_feature_string);
652     amfree(errstr);
653     amfree(dumper_timestamp);
654     amfree(handle);
655     amfree(hostname);
656     amfree(qdiskname);
657     amfree(diskname);
658     amfree(device);
659     amfree(dumpdate);
660     amfree(progname);
661     amfree(srvcompprog);
662     amfree(clntcompprog);
663     amfree(srv_encrypt);
664     amfree(clnt_encrypt);
665     amfree(srv_decrypt_opt);
666     amfree(clnt_decrypt_opt);
667     amfree(options);
668
669     dbclose();
670     return (0); /* exit */
671 }
672
673
674 /*
675  * Initialize a databuf.  Takes a writeable file descriptor.
676  */
677 static void
678 databuf_init(
679     struct databuf *    db,
680     int                 fd)
681 {
682
683     db->fd = fd;
684     db->datain = db->dataout = db->datalimit = NULL;
685     db->compresspid = -1;
686     db->encryptpid = -1;
687 }
688
689
690 /*
691  * Updates the buffer pointer for the input data buffer.  The buffer is
692  * written regardless of how much data is present, since we know we
693  * are writing to a socket (to chunker) and there is no need to maintain
694  * any boundaries.
695  */
696 static int
697 databuf_write(
698     struct databuf *    db,
699     const void *        buf,
700     size_t              size)
701 {
702     db->buf = (char *)buf;
703     db->datain = db->datalimit = db->buf + size;
704     db->dataout = db->buf;
705     return databuf_flush(db);
706 }
707
708 /*
709  * Write out the buffer to chunker.
710  */
711 static int
712 databuf_flush(
713     struct databuf *    db)
714 {
715     size_t written;
716     char *m;
717
718     /*
719      * If there's no data, do nothing.
720      */
721     if (db->dataout >= db->datain) {
722         return 0;
723     }
724
725     /*
726      * Write out the buffer
727      */
728     written = full_write(db->fd, db->dataout,
729                         (size_t)(db->datain - db->dataout));
730     if (written > 0) {
731         db->dataout += written;
732         dumpbytes += (off_t)written;
733     }
734     if (dumpbytes >= (off_t)1024) {
735         dumpsize += (dumpbytes / (off_t)1024);
736         dumpbytes %= (off_t)1024;
737     }
738     if (written == 0) {
739         int save_errno = errno;
740         m = vstrallocf(_("data write: %s"), strerror(save_errno));
741         amfree(errstr);
742         errstr = quote_string(m);
743         amfree(m);
744         errno = save_errno;
745         return -1;
746     }
747     db->datain = db->dataout = db->buf;
748     return 0;
749 }
750
751 static int dump_result;
752 static int status;
753 #define GOT_INFO_ENDLINE        (1 << 0)
754 #define GOT_SIZELINE            (1 << 1)
755 #define GOT_ENDLINE             (1 << 2)
756 #define HEADER_DONE             (1 << 3)
757
758
759 static void
760 process_dumpeof(void)
761 {
762     /* process any partial line in msgbuf? !!! */
763     add_msg_data(NULL, 0);
764     if(!ISSET(status, GOT_SIZELINE) && dump_result < 2) {
765         /* make a note if there isn't already a failure */
766         g_fprintf(errf,
767                 _("? %s: strange [missing size line from sendbackup]\n"),
768                 get_pname());
769         if(errstr == NULL) {
770             errstr = stralloc(_("missing size line from sendbackup"));
771         }
772         dump_result = max(dump_result, 2);
773     }
774
775     if(!ISSET(status, GOT_ENDLINE) && dump_result < 2) {
776         g_fprintf(errf,
777                 _("? %s: strange [missing end line from sendbackup]\n"),
778                 get_pname());
779         if(errstr == NULL) {
780             errstr = stralloc(_("missing end line from sendbackup"));
781         }
782         dump_result = max(dump_result, 2);
783     }
784 }
785
786 /*
787  * Parse an information line from the client.
788  * We ignore unknown parameters and only remember the last
789  * of any duplicates.
790  */
791 static void
792 parse_info_line(
793     char *str)
794 {
795     static const struct {
796         const char *name;
797         char *value;
798         size_t len;
799     } fields[] = {
800         { "BACKUP", file.program, SIZEOF(file.program) },
801         { "APPLICATION", file.application, SIZEOF(file.application) },
802         { "RECOVER_CMD", file.recover_cmd, SIZEOF(file.recover_cmd) },
803         { "COMPRESS_SUFFIX", file.comp_suffix, SIZEOF(file.comp_suffix) },
804         { "SERVER_CUSTOM_COMPRESS", file.srvcompprog, SIZEOF(file.srvcompprog) },
805         { "CLIENT_CUSTOM_COMPRESS", file.clntcompprog, SIZEOF(file.clntcompprog) },
806         { "SERVER_ENCRYPT", file.srv_encrypt, SIZEOF(file.srv_encrypt) },
807         { "CLIENT_ENCRYPT", file.clnt_encrypt, SIZEOF(file.clnt_encrypt) },
808         { "SERVER_DECRYPT_OPTION", file.srv_decrypt_opt, SIZEOF(file.srv_decrypt_opt) },
809         { "CLIENT_DECRYPT_OPTION", file.clnt_decrypt_opt, SIZEOF(file.clnt_decrypt_opt) }
810     };
811     char *name, *value;
812     size_t i;
813
814     if (strcmp(str, "end") == 0) {
815         SET(status, GOT_INFO_ENDLINE);
816         return;
817     }
818
819     name = strtok(str, "=");
820     if (name == NULL)
821         return;
822     value = strtok(NULL, "");
823     if (value == NULL)
824         return;
825
826     for (i = 0; i < SIZEOF(fields) / SIZEOF(fields[0]); i++) {
827         if (strcmp(name, fields[i].name) == 0) {
828             strncpy(fields[i].value, value, fields[i].len - 1);
829             fields[i].value[fields[i].len - 1] = '\0';
830             break;
831         }
832     }
833 }
834
835 static void
836 process_dumpline(
837     const char *        str)
838 {
839     char *buf, *tok;
840
841     buf = stralloc(str);
842
843     switch (*buf) {
844     case '|':
845         /* normal backup output line */
846         break;
847     case '?':
848         /* sendbackup detected something strange */
849         dump_result = max(dump_result, 1);
850         break;
851     case 's':
852         /* a sendbackup line, just check them all since there are only 5 */
853         tok = strtok(buf, " ");
854         if (tok == NULL || strcmp(tok, "sendbackup:") != 0)
855             goto bad_line;
856
857         tok = strtok(NULL, " ");
858         if (tok == NULL)
859             goto bad_line;
860
861         if (strcmp(tok, "start") == 0) {
862             break;
863         }
864
865         if (strcmp(tok, "size") == 0) {
866             tok = strtok(NULL, "");
867             if (tok != NULL) {
868                 origsize = OFF_T_ATOI(tok);
869                 SET(status, GOT_SIZELINE);
870             }
871             break;
872         }
873
874         if (strcmp(tok, "no-op") == 0) {
875             amfree(buf);
876             return;
877         }
878
879         if (strcmp(tok, "end") == 0) {
880             SET(status, GOT_ENDLINE);
881             break;
882         }
883
884         if (strcmp(tok, "warning") == 0) {
885             dump_result = max(dump_result, 1);
886             break;
887         }
888
889         if (strcmp(tok, "error") == 0) {
890             SET(status, GOT_ENDLINE);
891             dump_result = max(dump_result, 2);
892
893             tok = strtok(NULL, "");
894             if (!errstr) { /* report first error line */
895                 if (tok == NULL || *tok != '[') {
896                     errstr = newvstrallocf(errstr, _("bad remote error: %s"),
897                                            str);
898                 } else {
899                     char *enderr;
900
901                     tok++;      /* skip over '[' */
902                     if ((enderr = strchr(tok, ']')) != NULL)
903                         *enderr = '\0';
904                     errstr = newstralloc(errstr, tok);
905                 }
906             }
907             break;
908         }
909
910         if (strcmp(tok, "info") == 0) {
911             tok = strtok(NULL, "");
912             if (tok != NULL)
913                 parse_info_line(tok);
914             break;
915         }
916         /* else we fall through to bad line */
917     default:
918 bad_line:
919         /* prefix with ?? */
920         g_fprintf(errf, "??");
921         dump_result = max(dump_result, 1);
922         break;
923     }
924     g_fprintf(errf, "%s\n", str);
925     errf_lines++;
926     amfree(buf);
927 }
928
929 static void
930 add_msg_data(
931     const char *        str,
932     size_t              len)
933 {
934     char *line, *ch;
935     size_t buflen;
936
937     if (msg.buf != NULL)
938         buflen = strlen(msg.buf);
939     else
940         buflen = 0;
941
942     /*
943      * If our argument is NULL, then we need to flush out any remaining
944      * bits and return.
945      */
946     if (str == NULL) {
947         if (buflen == 0)
948             return;
949         g_fprintf(errf,_("? %s: error [partial line in msgbuf: %zu bytes]\n"),
950             get_pname(), buflen);
951         g_fprintf(errf,_("? %s: error [partial line in msgbuf: \"%s\"]\n"),
952             get_pname(), msg.buf);
953         msg.buf[0] = '\0';
954         return;
955     }
956
957     /*
958      * Expand the buffer if it can't hold the new contents.
959      */
960     if ((buflen + len + 1) > msg.size) {
961         char *newbuf;
962         size_t newsize;
963
964 /* round up to next y, where y is a power of 2 */
965 #define ROUND(x, y)     (((x) + (y) - 1) & ~((y) - 1))
966
967         newsize = ROUND(buflen + (ssize_t)len + 1, 256);
968         newbuf = alloc(newsize);
969
970         if (msg.buf != NULL) {
971             strncpy(newbuf, msg.buf, newsize);
972             amfree(msg.buf);
973         } else
974             newbuf[0] = '\0';
975         msg.buf = newbuf;
976         msg.size = newsize;
977     }
978
979     /*
980      * If there was a partial line from the last call, then
981      * append the new data to the end.
982      */
983     strncat(msg.buf, str, len);
984
985     /*
986      * Process all lines in the buffer
987      * scanning line for unqouted newline.
988      */
989     for (ch = line = msg.buf; *ch != '\0'; ch++) {
990         if (*ch == '\n') {
991             /*
992              * Found a newline.  Terminate and process line.
993              */
994             *ch = '\0';
995             process_dumpline(line);
996             line = ch + 1;
997         }
998     }
999
1000     /*
1001      * If we did not process all of the data, move it to the front
1002      * of the buffer so it is there next time.
1003      */
1004     if (*line != '\0') {
1005         buflen = strlen(line);
1006         memmove(msg.buf, line, (size_t)buflen + 1);
1007     } else {
1008         msg.buf[0] = '\0';
1009     }
1010 }
1011
1012
1013 static int
1014 log_msgout(
1015     logtype_t   typ)
1016 {
1017     char *line;
1018     int   count = 0;
1019     int   to_unlink = 1;
1020
1021     fflush(errf);
1022     if (fseeko(errf, 0L, SEEK_SET) < 0) {
1023         dbprintf(_("log_msgout: warning - seek failed: %s\n"), strerror(errno));
1024     }
1025     while ((line = agets(errf)) != NULL) {
1026         if (max_warnings > 0 && errf_lines >= max_warnings && count >= max_warnings) {
1027             log_add(typ, "Look in the '%s' file for full error messages", errfname);
1028             to_unlink = 0;
1029             break;
1030         }
1031         if (line[0] != '\0') {
1032                 log_add(typ, "%s", line);
1033         }
1034         amfree(line);
1035         count++;
1036     }
1037     amfree(line);
1038
1039     return to_unlink;
1040 }
1041
1042 /* ------------- */
1043
1044 /*
1045  * Fill in the rest of the tape header
1046  */
1047 static void
1048 finish_tapeheader(
1049     dumpfile_t *file)
1050 {
1051
1052     assert(ISSET(status, HEADER_DONE));
1053
1054     file->type = F_DUMPFILE;
1055     strncpy(file->datestamp, dumper_timestamp, sizeof(file->datestamp) - 1);
1056     strncpy(file->name, hostname, SIZEOF(file->name) - 1);
1057     strncpy(file->disk, diskname, SIZEOF(file->disk) - 1);
1058     file->dumplevel = level;
1059     file->blocksize = DISK_BLOCK_BYTES;
1060
1061     /*
1062      * If we're doing the compression here, we need to override what
1063      * sendbackup told us the compression was.
1064      */
1065     if (srvcompress != COMP_NONE) {
1066         file->compressed = 1;
1067 #ifndef UNCOMPRESS_OPT
1068 #define UNCOMPRESS_OPT  ""
1069 #endif
1070         if (srvcompress == COMP_SERVER_CUST) {
1071             g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1072                      " %s %s |", srvcompprog, "-d");
1073             strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1);
1074             file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1075             strncpy(file->srvcompprog, srvcompprog, SIZEOF(file->srvcompprog) - 1);
1076             file->srvcompprog[SIZEOF(file->srvcompprog) - 1] = '\0';
1077         } else if ( srvcompress == COMP_CUST ) {
1078             g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1079                      " %s %s |", clntcompprog, "-d");
1080             strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1);
1081             file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1082             strncpy(file->clntcompprog, clntcompprog, SIZEOF(file->clntcompprog));
1083             file->clntcompprog[SIZEOF(file->clntcompprog) - 1] = '\0';
1084         } else {
1085             g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1086                 " %s %s |", UNCOMPRESS_PATH, UNCOMPRESS_OPT);
1087             strncpy(file->comp_suffix, COMPRESS_SUFFIX,SIZEOF(file->comp_suffix) - 1);
1088             file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1089         }
1090     } else {
1091         if (file->comp_suffix[0] == '\0') {
1092             file->compressed = 0;
1093             assert(SIZEOF(file->comp_suffix) >= 2);
1094             strncpy(file->comp_suffix, "N", SIZEOF(file->comp_suffix) - 1);
1095             file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1096         } else {
1097             file->compressed = 1;
1098         }
1099     }
1100     /* take care of the encryption header here */
1101     if (srvencrypt != ENCRYPT_NONE) {
1102       file->encrypted= 1;
1103       if (srvencrypt == ENCRYPT_SERV_CUST) {
1104         if (srv_decrypt_opt) {
1105           g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1106                    " %s %s |", srv_encrypt, srv_decrypt_opt); 
1107           strncpy(file->srv_decrypt_opt, srv_decrypt_opt, SIZEOF(file->srv_decrypt_opt) - 1);
1108           file->srv_decrypt_opt[SIZEOF(file->srv_decrypt_opt) - 1] = '\0';
1109         } else {
1110           g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1111                    " %s |", srv_encrypt); 
1112           file->srv_decrypt_opt[0] = '\0';
1113         }
1114         strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1);
1115         file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1116         strncpy(file->srv_encrypt, srv_encrypt, SIZEOF(file->srv_encrypt) - 1);
1117         file->srv_encrypt[SIZEOF(file->srv_encrypt) - 1] = '\0';
1118       } else if ( srvencrypt == ENCRYPT_CUST ) {
1119         if (clnt_decrypt_opt) {
1120           g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1121                    " %s %s |", clnt_encrypt, clnt_decrypt_opt);
1122           strncpy(file->clnt_decrypt_opt, clnt_decrypt_opt,
1123                   SIZEOF(file->clnt_decrypt_opt));
1124           file->clnt_decrypt_opt[SIZEOF(file->clnt_decrypt_opt) - 1] = '\0';
1125         } else {
1126           g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1127                    " %s |", clnt_encrypt);
1128           file->clnt_decrypt_opt[0] = '\0';
1129         }
1130         g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1131                  " %s %s |", clnt_encrypt, clnt_decrypt_opt);
1132         strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1);
1133         file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1134         strncpy(file->clnt_encrypt, clnt_encrypt, SIZEOF(file->clnt_encrypt) - 1);
1135         file->clnt_encrypt[SIZEOF(file->clnt_encrypt) - 1] = '\0';
1136       }
1137     } else {
1138       if (file->encrypt_suffix[0] == '\0') {
1139         file->encrypted = 0;
1140         assert(SIZEOF(file->encrypt_suffix) >= 2);
1141         strncpy(file->encrypt_suffix, "N", SIZEOF(file->encrypt_suffix) - 1);
1142         file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1143       } else {
1144         file->encrypted= 1;
1145       }
1146     }
1147     if (dle_str)
1148         file->dle_str = stralloc(dle_str);
1149     else
1150         file->dle_str = NULL;
1151 }
1152
1153 /*
1154  * Send an Amanda dump header to the output file.
1155  */
1156 static ssize_t
1157 write_tapeheader(
1158     int         outfd,
1159     dumpfile_t *file)
1160 {
1161     char * buffer;
1162     size_t written;
1163
1164     if (debug_dumper > 1)
1165         dump_dumpfile_t(file);
1166     buffer = build_header(file, NULL, DISK_BLOCK_BYTES);
1167     if (!buffer) /* this shouldn't happen */
1168         error(_("header does not fit in %zd bytes"), (size_t)DISK_BLOCK_BYTES);
1169
1170     written = full_write(outfd, buffer, DISK_BLOCK_BYTES);
1171     amfree(buffer);
1172     if(written == DISK_BLOCK_BYTES)
1173         return 0;
1174
1175     return -1;
1176 }
1177
1178 int indexout = -1;
1179
1180 static int
1181 do_dump(
1182     struct databuf *db)
1183 {
1184     char *indexfile_tmp = NULL;
1185     char *indexfile_real = NULL;
1186     char level_str[NUM_STR_SIZE];
1187     char *time_str;
1188     char *fn;
1189     char *q;
1190     times_t runtime;
1191     double dumptime;    /* Time dump took in secs */
1192     pid_t indexpid = -1;
1193     char *m;
1194     int to_unlink = 1;
1195
1196     startclock();
1197
1198     if (msg.buf) msg.buf[0] = '\0';     /* reset msg buffer */
1199     status = 0;
1200     dump_result = 0;
1201     dumpbytes = dumpsize = headersize = origsize = (off_t)0;
1202     fh_init(&file);
1203
1204     g_snprintf(level_str, SIZEOF(level_str), "%d", level);
1205     time_str = get_timestamp_from_time(0);
1206     fn = sanitise_filename(diskname);
1207     errf_lines = 0;
1208     errfname = newvstralloc(errfname,
1209                             AMANDA_DBGDIR,
1210                             "/log.error", NULL);
1211     mkdir(errfname, 0700);
1212     errfname = newvstralloc(errfname,
1213                             AMANDA_DBGDIR,
1214                             "/log.error/", hostname,
1215                             ".", fn,
1216                             ".", level_str,
1217                             ".", time_str,
1218                             ".errout",
1219                             NULL);
1220     amfree(fn);
1221     amfree(time_str);
1222     if((errf = fopen(errfname, "w+")) == NULL) {
1223         errstr = newvstrallocf(errstr, "errfile open \"%s\": %s",
1224                               errfname, strerror(errno));
1225         amfree(errfname);
1226         goto failed;
1227     }
1228
1229     if (streams[INDEXFD].fd != NULL) {
1230         indexfile_real = getindexfname(hostname, diskname, dumper_timestamp, level);
1231         indexfile_tmp = stralloc2(indexfile_real, ".tmp");
1232
1233         if (mkpdir(indexfile_tmp, 0755, (uid_t)-1, (gid_t)-1) == -1) {
1234            errstr = newvstrallocf(errstr,
1235                                  _("err create %s: %s"),
1236                                  indexfile_tmp,
1237                                  strerror(errno));
1238            amfree(indexfile_real);
1239            amfree(indexfile_tmp);
1240            goto failed;
1241         }
1242         indexout = open(indexfile_tmp, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1243         if (indexout == -1) {
1244             errstr = newvstrallocf(errstr, _("err open %s: %s"),
1245                         indexfile_tmp, strerror(errno));
1246             goto failed;
1247         } else {
1248             if (runcompress(indexout, &indexpid, COMP_BEST, "index compress") < 0) {
1249                 aclose(indexout);
1250                 goto failed;
1251             }
1252         }
1253         indexfderror = 0;
1254         /*
1255          * Schedule the indexfd for relaying to the index file
1256          */
1257         security_stream_read(streams[INDEXFD].fd, read_indexfd, &indexout);
1258     }
1259
1260     /*
1261      * We only need to process messages initially.  Once we have done
1262      * the header, we will start processing data too.
1263      */
1264     security_stream_read(streams[MESGFD].fd, read_mesgfd, db);
1265     set_datafd = 0;
1266
1267     /*
1268      * Setup a read timeout
1269      */
1270     timeout(conf_dtimeout);
1271
1272     /*
1273      * Start the event loop.  This will exit when all three events
1274      * (read the mesgfd, read the datafd, and timeout) are removed.
1275      */
1276     event_loop(0);
1277
1278     if (!ISSET(status, HEADER_DONE)) {
1279         dump_result = max(dump_result, 2);
1280         if (!errstr) errstr = stralloc(_("got no header information"));
1281     }
1282
1283     dumpsize -= headersize;             /* don't count the header */
1284     if (dumpsize <= (off_t)0 && data_path == DATA_PATH_AMANDA) {
1285         dumpsize = (off_t)0;
1286         dump_result = max(dump_result, 2);
1287         if (!errstr) errstr = stralloc(_("got no data"));
1288     }
1289
1290     if (data_path == DATA_PATH_DIRECTTCP) {
1291         dumpsize = origsize;
1292     }
1293
1294     if (!ISSET(status, HEADER_DONE)) {
1295         dump_result = max(dump_result, 2);
1296         if (!errstr) errstr = stralloc(_("got no header information"));
1297     }
1298
1299     if (dumpsize == 0 && data_path == DATA_PATH_AMANDA) {
1300         dump_result = max(dump_result, 2);
1301         if (!errstr) errstr = stralloc(_("got no data"));
1302     }
1303
1304     if (indexfile_tmp) {
1305         amwait_t index_status;
1306
1307         /*@i@*/ aclose(indexout);
1308         waitpid(indexpid,&index_status,0);
1309         log_add(L_INFO, "pid-done %ld", (long)indexpid);
1310         if (rename(indexfile_tmp, indexfile_real) != 0) {
1311             log_add(L_WARNING, _("could not rename \"%s\" to \"%s\": %s"),
1312                     indexfile_tmp, indexfile_real, strerror(errno));
1313         }
1314         amfree(indexfile_tmp);
1315         amfree(indexfile_real);
1316     }
1317
1318     /* copy the header in a file on the index dir */
1319     if (ISSET(status, HEADER_DONE)) {
1320         FILE *a;
1321         char *s;
1322         char *f = getheaderfname(hostname, diskname, dumper_timestamp, level);
1323         a = fopen(f,"w");
1324         if (a) {
1325             s = build_header(&file, NULL, DISK_BLOCK_BYTES);
1326             fprintf(a,"%s", s);
1327             g_free(s);
1328             fclose(a);
1329         }
1330         g_free(f);
1331     }
1332
1333     if (db->compresspid != -1 && dump_result < 2) {
1334         amwait_t  wait_status;
1335         char *errmsg = NULL;
1336
1337         waitpid(db->compresspid, &wait_status, 0);
1338         if (WIFSIGNALED(wait_status)) {
1339             errmsg = g_strdup_printf(_("%s terminated with signal %d"),
1340                                      "compress", WTERMSIG(wait_status));
1341         } else if (WIFEXITED(wait_status)) {
1342             if (WEXITSTATUS(wait_status) != 0) {
1343                 errmsg = g_strdup_printf(_("%s exited with status %d"),
1344                                          "compress", WEXITSTATUS(wait_status));
1345             }
1346         } else {
1347             errmsg = g_strdup_printf(_("%s got bad exit"),
1348                                      "compress");
1349         }
1350         if (errmsg) {
1351             g_fprintf(errf, _("? %s\n"), errmsg);
1352             g_debug("%s", errmsg);
1353             dump_result = max(dump_result, 2);
1354             if (!errstr)
1355                 errstr = errmsg;
1356             else
1357                 g_free(errmsg);
1358         }
1359         log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1360         db->compresspid = -1;
1361     }
1362
1363     if (db->encryptpid != -1 && dump_result < 2) {
1364         amwait_t  wait_status;
1365         char *errmsg = NULL;
1366
1367         waitpid(db->encryptpid, &wait_status, 0);
1368         if (WIFSIGNALED(wait_status)) {
1369             errmsg = g_strdup_printf(_("%s terminated with signal %d"),
1370                                      "encrypt", WTERMSIG(wait_status));
1371         } else if (WIFEXITED(wait_status)) {
1372             if (WEXITSTATUS(wait_status) != 0) {
1373                 errmsg = g_strdup_printf(_("%s exited with status %d"),
1374                                          "encrypt", WEXITSTATUS(wait_status));
1375             }
1376         } else {
1377             errmsg = g_strdup_printf(_("%s got bad exit"),
1378                                      "encrypt");
1379         }
1380         if (errmsg) {
1381             g_fprintf(errf, _("? %s\n"), errmsg);
1382             g_debug("%s", errmsg);
1383             dump_result = max(dump_result, 2);
1384             if (!errstr)
1385                 errstr = errmsg;
1386             else
1387                 g_free(errmsg);
1388         }
1389         log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1390         db->encryptpid  = -1;
1391     }
1392
1393     if (dump_result > 1)
1394         goto failed;
1395
1396     runtime = stopclock();
1397     dumptime = g_timeval_to_double(runtime);
1398
1399     amfree(errstr);
1400     errstr = alloc(128);
1401     g_snprintf(errstr, 128, _("sec %s kb %lld kps %3.1lf orig-kb %lld"),
1402         walltime_str(runtime),
1403         (long long)dumpsize,
1404         (isnormal(dumptime) ? ((double)dumpsize / (double)dumptime) : 0.0),
1405         (long long)origsize);
1406     m = vstrallocf("[%s]", errstr);
1407     q = quote_string(m);
1408     amfree(m);
1409     putresult(DONE, _("%s %lld %lld %lu %s\n"), handle,
1410                 (long long)origsize,
1411                 (long long)dumpsize,
1412                 (unsigned long)((double)dumptime+0.5), q);
1413     amfree(q);
1414
1415     switch(dump_result) {
1416     case 0:
1417         log_add(L_SUCCESS, "%s %s %s %d [%s]", hostname, qdiskname, dumper_timestamp, level, errstr);
1418
1419         break;
1420
1421     case 1:
1422         log_start_multiline();
1423         log_add(L_STRANGE, "%s %s %d [%s]", hostname, qdiskname, level, errstr);
1424         to_unlink = log_msgout(L_STRANGE);
1425         log_end_multiline();
1426
1427         break;
1428     }
1429
1430     if (errf)
1431         afclose(errf);
1432     if (errfname) {
1433         if (to_unlink)
1434             unlink(errfname);
1435         amfree(errfname);
1436     }
1437
1438     if (data_path == DATA_PATH_AMANDA)
1439         aclose(db->fd);
1440
1441     amfree(errstr);
1442     dumpfile_free_data(&file);
1443
1444     return 1;
1445
1446 failed:
1447     m = vstrallocf("[%s]", errstr);
1448     q = quote_string(m);
1449     putresult(FAILED, "%s %s\n", handle, q);
1450     amfree(q);
1451     amfree(m);
1452
1453     aclose(db->fd);
1454     /* kill all child process */
1455     if (db->compresspid != -1) {
1456         g_fprintf(stderr,_("%s: kill compress command\n"),get_pname());
1457         if (kill(db->compresspid, SIGTERM) < 0) {
1458             if (errno != ESRCH) {
1459                 g_fprintf(stderr,_("%s: can't kill compress command: %s\n"), 
1460                     get_pname(), strerror(errno));
1461             } else {
1462                 log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1463             }
1464         }
1465         else {
1466             waitpid(db->compresspid,NULL,0);
1467             log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1468         }
1469     }
1470
1471     if (db->encryptpid != -1) {
1472         g_fprintf(stderr,_("%s: kill encrypt command\n"),get_pname());
1473         if (kill(db->encryptpid, SIGTERM) < 0) {
1474             if (errno != ESRCH) {
1475                 g_fprintf(stderr,_("%s: can't kill encrypt command: %s\n"), 
1476                     get_pname(), strerror(errno));
1477             } else {
1478                 log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1479             }
1480         }
1481         else {
1482             waitpid(db->encryptpid,NULL,0);
1483             log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1484         }
1485     }
1486
1487     if (indexpid != -1) {
1488         g_fprintf(stderr,_("%s: kill index command\n"),get_pname());
1489         if (kill(indexpid, SIGTERM) < 0) {
1490             if (errno != ESRCH) {
1491                 g_fprintf(stderr,_("%s: can't kill index command: %s\n"), 
1492                     get_pname(),strerror(errno));
1493             } else {
1494                 log_add(L_INFO, "pid-done %ld", (long)indexpid);
1495             }
1496         }
1497         else {
1498             waitpid(indexpid,NULL,0);
1499             log_add(L_INFO, "pid-done %ld", (long)indexpid);
1500         }
1501     }
1502
1503     log_start_multiline();
1504     log_add(L_FAIL, _("%s %s %s %d [%s]"), hostname, qdiskname, dumper_timestamp,
1505             level, errstr);
1506     if (errf) {
1507         to_unlink = log_msgout(L_FAIL);
1508     }
1509     log_end_multiline();
1510
1511     if (errf)
1512         afclose(errf);
1513     if (errfname) {
1514         if (to_unlink)
1515             unlink(errfname);
1516         amfree(errfname);
1517     }
1518
1519     if (indexfile_tmp) {
1520         unlink(indexfile_tmp);
1521         amfree(indexfile_tmp);
1522         amfree(indexfile_real);
1523     }
1524
1525     amfree(errstr);
1526     dumpfile_free_data(&file);
1527
1528     return 0;
1529 }
1530
1531 /*
1532  * Callback for reads on the mesgfd stream
1533  */
1534 static void
1535 read_mesgfd(
1536     void *      cookie,
1537     void *      buf,
1538     ssize_t     size)
1539 {
1540     struct databuf *db = cookie;
1541
1542     assert(db != NULL);
1543
1544     switch (size) {
1545     case -1:
1546         errstr = newvstrallocf(errstr, _("mesg read: %s"),
1547             security_stream_geterror(streams[MESGFD].fd));
1548         dump_result = 2;
1549         stop_dump();
1550         return;
1551
1552     case 0:
1553         /*
1554          * EOF.  Just shut down the mesg stream.
1555          */
1556         process_dumpeof();
1557         security_stream_close(streams[MESGFD].fd);
1558         streams[MESGFD].fd = NULL;
1559         /*
1560          * If the data fd and index fd has also shut down, then we're done.
1561          */
1562         if ((set_datafd == 0 || streams[DATAFD].fd == NULL) && 
1563             streams[INDEXFD].fd == NULL)
1564             stop_dump();
1565         return;
1566
1567     default:
1568         assert(buf != NULL);
1569         add_msg_data(buf, (size_t)size);
1570         break;
1571     }
1572
1573     if (ISSET(status, GOT_INFO_ENDLINE) && !ISSET(status, HEADER_DONE)) {
1574         /* Use the first in the dataport_list */
1575         in_port_t data_port;
1576         char *data_host = dataport_list;
1577         char *s;
1578
1579         s = strchr(dataport_list, ',');
1580         if (s) *s = '\0';  /* use first data_port */
1581         s = strrchr(dataport_list, ':');
1582         *s = '\0';
1583         s++;
1584         data_port = atoi(s);
1585
1586         SET(status, HEADER_DONE);
1587         /* time to do the header */
1588         finish_tapeheader(&file);
1589         if (write_tapeheader(db->fd, &file)) {
1590             errstr = newvstrallocf(errstr, _("write_tapeheader: %s"), 
1591                                   strerror(errno));
1592             dump_result = 2;
1593             stop_dump();
1594             return;
1595         }
1596         aclose(db->fd);
1597         if (data_path == DATA_PATH_AMANDA) {
1598             g_debug(_("Sending data to %s:%d\n"), data_host, data_port);
1599             db->fd = stream_client(data_host, data_port,
1600                                    STREAM_BUFSIZE, 0, NULL, 0);
1601             if (db->fd == -1) {
1602                 errstr = newvstrallocf(errstr,
1603                                        _("Can't open data output stream: %s"),
1604                                        strerror(errno));
1605                 dump_result = 2;
1606                 stop_dump();
1607                 return;
1608             }
1609         }
1610
1611         dumpsize += (off_t)DISK_BLOCK_KB;
1612         headersize += (off_t)DISK_BLOCK_KB;
1613
1614         if (srvencrypt == ENCRYPT_SERV_CUST) {
1615             if (runencrypt(db->fd, &db->encryptpid, srvencrypt) < 0) {
1616                 dump_result = 2;
1617                 stop_dump();
1618                 return;
1619             }
1620         }
1621         /*
1622          * Now, setup the compress for the data output, and start
1623          * reading the datafd.
1624          */
1625         if ((srvcompress != COMP_NONE) && (srvcompress != COMP_CUST)) {
1626             if (runcompress(db->fd, &db->compresspid, srvcompress, "data compress") < 0) {
1627                 dump_result = 2;
1628                 stop_dump();
1629                 return;
1630             }
1631         }
1632         security_stream_read(streams[DATAFD].fd, read_datafd, db);
1633         set_datafd = 1;
1634     }
1635
1636     /*
1637      * Reset the timeout for future reads
1638      */
1639     timeout(conf_dtimeout);
1640 }
1641
1642 /*
1643  * Callback for reads on the datafd stream
1644  */
1645 static void
1646 read_datafd(
1647     void *      cookie,
1648     void *      buf,
1649     ssize_t     size)
1650 {
1651     struct databuf *db = cookie;
1652
1653     assert(db != NULL);
1654
1655     /*
1656      * The read failed.  Error out
1657      */
1658     if (size < 0) {
1659         errstr = newvstrallocf(errstr, _("data read: %s"),
1660             security_stream_geterror(streams[DATAFD].fd));
1661         dump_result = 2;
1662         aclose(db->fd);
1663         stop_dump();
1664         return;
1665     }
1666
1667     /* The header had better be written at this point */
1668     assert(ISSET(status, HEADER_DONE));
1669
1670     /*
1671      * EOF.  Stop and return.
1672      */
1673     if (size == 0) {
1674         databuf_flush(db);
1675         if (dumpbytes != (off_t)0) {
1676             dumpsize += (off_t)1;
1677         }
1678         security_stream_close(streams[DATAFD].fd);
1679         streams[DATAFD].fd = NULL;
1680         aclose(db->fd);
1681         /*
1682          * If the mesg fd and index fd has also shut down, then we're done.
1683          */
1684         if (streams[MESGFD].fd == NULL && streams[INDEXFD].fd == NULL)
1685             stop_dump();
1686         return;
1687     }
1688
1689     /*
1690      * We read something.  Add it to the databuf and reschedule for
1691      * more data.
1692      */
1693     assert(buf != NULL);
1694     if (databuf_write(db, buf, (size_t)size) < 0) {
1695         int save_errno = errno;
1696         errstr = newvstrallocf(errstr, _("data write: %s"), strerror(save_errno));
1697         dump_result = 2;
1698         stop_dump();
1699         return;
1700     }
1701
1702     /*
1703      * Reset the timeout for future reads
1704      */
1705     timeout(conf_dtimeout);
1706 }
1707
1708 /*
1709  * Callback for reads on the index stream
1710  */
1711 static void
1712 read_indexfd(
1713     void *      cookie,
1714     void *      buf,
1715     ssize_t     size)
1716 {
1717     int fd;
1718
1719     assert(cookie != NULL);
1720     fd = *(int *)cookie;
1721
1722     if (size < 0) {
1723         errstr = newvstrallocf(errstr, _("index read: %s"),
1724             security_stream_geterror(streams[INDEXFD].fd));
1725         dump_result = 2;
1726         stop_dump();
1727         return;
1728     }
1729
1730     /*
1731      * EOF.  Stop and return.
1732      */
1733     if (size == 0) {
1734         security_stream_close(streams[INDEXFD].fd);
1735         streams[INDEXFD].fd = NULL;
1736         /*
1737          * If the mesg fd has also shut down, then we're done.
1738          */
1739         if ((set_datafd == 0 || streams[DATAFD].fd == NULL) &&
1740              streams[MESGFD].fd == NULL)
1741             stop_dump();
1742         aclose(indexout);
1743         return;
1744     }
1745
1746     assert(buf != NULL);
1747
1748     /*
1749      * We ignore error while writing to the index file.
1750      */
1751     if (full_write(fd, buf, (size_t)size) < (size_t)size) {
1752         /* Ignore error, but schedule another read. */
1753         if(indexfderror == 0) {
1754             indexfderror = 1;
1755             log_add(L_INFO, _("Index corrupted for %s:%s"), hostname, qdiskname);
1756         }
1757     }
1758 }
1759
1760 static void
1761 handle_filter_stderr(
1762     void *cookie)
1763 {
1764     filter_t *filter = cookie;
1765     ssize_t   nread;
1766     char     *b, *p;
1767     gint64    len;
1768
1769     if (filter->buffer == NULL) {
1770         /* allocate initial buffer */
1771         filter->buffer = g_malloc(2048);
1772         filter->first = 0;
1773         filter->size = 0;
1774         filter->allocated_size = 2048;
1775     } else if (filter->first > 0) {
1776         if (filter->allocated_size - filter->size - filter->first < 1024) {
1777             memmove(filter->buffer, filter->buffer + filter->first,
1778                                     filter->size);
1779             filter->first = 0;
1780         }
1781     } else if (filter->allocated_size - filter->size < 1024) {
1782         /* double the size of the buffer */
1783         filter->allocated_size *= 2;
1784         filter->buffer = g_realloc(filter->buffer, filter->allocated_size);
1785     }
1786
1787     nread = read(filter->fd, filter->buffer + filter->first + filter->size,
1788                              filter->allocated_size - filter->first - filter->size - 2);
1789
1790     if (nread <= 0) {
1791         event_release(filter->event);
1792         aclose(filter->fd);
1793         if (filter->size > 0 && filter->buffer[filter->first + filter->size - 1] != '\n') {
1794             /* Add a '\n' at end of buffer */
1795             filter->buffer[filter->first + filter->size] = '\n';
1796             filter->size++;
1797         }
1798     } else {
1799         filter->size += nread;
1800     }
1801
1802     /* process all complete lines */
1803     b = filter->buffer + filter->first;
1804     filter->buffer[filter->first + filter->size] = '\0';
1805     while (b < filter->buffer + filter->first + filter->size &&
1806            (p = strchr(b, '\n')) != NULL) {
1807         *p = '\0';
1808         g_fprintf(errf, _("? %s: %s\n"), filter->name, b);
1809         if (errstr == NULL) {
1810             errstr = stralloc(b);
1811         }
1812         len = p - b + 1;
1813         filter->first += len;
1814         filter->size -= len;
1815         b = p + 1;
1816         dump_result = max(dump_result, 1);
1817     }
1818
1819     if (nread <= 0) {
1820         g_free(filter->buffer);
1821         g_free(filter);
1822     }
1823 }
1824
1825 /*
1826  * Startup a timeout in the event handler.  If the arg is 0,
1827  * then remove the timeout.
1828  */
1829 static event_handle_t *ev_timeout = NULL;
1830 static time_t timeout_time;
1831
1832 static void
1833 timeout(
1834     time_t seconds)
1835 {
1836     timeout_time = time(NULL) + seconds;
1837
1838     /*
1839      * remove a timeout if seconds is 0
1840      */
1841     if (seconds == 0) {
1842         if (ev_timeout != NULL) {
1843             event_release(ev_timeout);
1844             ev_timeout = NULL;
1845         }
1846         return;
1847     }
1848
1849     /*
1850      * schedule a timeout if it not already scheduled
1851      */
1852     if (ev_timeout == NULL) {
1853         ev_timeout = event_register((event_id_t)seconds, EV_TIME,
1854                                      timeout_callback, NULL);
1855     }
1856 }
1857
1858 /*
1859  * This is the callback for timeout().  If this is reached, then we
1860  * have a data timeout.
1861  */
1862 static void
1863 timeout_callback(
1864     void *      unused)
1865 {
1866     time_t now = time(NULL);
1867     (void)unused;       /* Quiet unused parameter warning */
1868
1869     if (ev_timeout != NULL) {
1870         event_release(ev_timeout);
1871         ev_timeout = NULL;
1872     }
1873
1874     if (timeout_time > now) { /* not a data timeout yet */
1875         ev_timeout = event_register((event_id_t)(timeout_time-now), EV_TIME,
1876                                     timeout_callback, NULL);
1877         return;
1878     }
1879
1880     assert(unused == NULL);
1881     errstr = newstralloc(errstr, _("data timeout"));
1882     dump_result = 2;
1883     stop_dump();
1884 }
1885
1886 /*
1887  * This is called when everything needs to shut down so event_loop()
1888  * will exit.
1889  */
1890 static void
1891 stop_dump(void)
1892 {
1893     int             i;
1894     struct cmdargs *cmdargs = NULL;
1895
1896     /* Check if I have a pending ABORT command */
1897     cmdargs = get_pending_cmd();
1898     if (cmdargs) {
1899         if (cmdargs->cmd != ABORT) {
1900             error(_("beurk %d"), cmdargs->cmd);
1901         }
1902         amfree(errstr);
1903         errstr = stralloc(cmdargs->argv[1]);
1904         free_cmdargs(cmdargs);
1905     }
1906
1907     for (i = 0; i < NSTREAMS; i++) {
1908         if (streams[i].fd != NULL) {
1909             security_stream_close(streams[i].fd);
1910             streams[i].fd = NULL;
1911         }
1912     }
1913     aclose(indexout);
1914     aclose(g_databuf->fd);
1915     timeout(0);
1916 }
1917
1918
1919 /*
1920  * Runs compress with the first arg as its stdout.  Returns
1921  * 0 on success or negative if error, and it's pid via the second
1922  * argument.  The outfd arg is dup2'd to the pipe to the compress
1923  * process.
1924  */
1925 static int
1926 runcompress(
1927     int         outfd,
1928     pid_t *     pid,
1929     comp_t      comptype,
1930     char       *name)
1931 {
1932     int outpipe[2], rval;
1933     int errpipe[2];
1934     filter_t *filter;
1935
1936     assert(outfd >= 0);
1937     assert(pid != NULL);
1938
1939     /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
1940     if (pipe(outpipe) < 0) {
1941         errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
1942         return (-1);
1943     }
1944
1945     /* errpipe[0] is pipe's output, outpipe[1] is input. */
1946     if (pipe(errpipe) < 0) {
1947         errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
1948         return (-1);
1949     }
1950
1951     if (comptype != COMP_SERVER_CUST) {
1952         g_debug("execute: %s %s", COMPRESS_PATH,
1953                 comptype == COMP_BEST ? COMPRESS_BEST_OPT : COMPRESS_FAST_OPT);
1954     } else {
1955         g_debug("execute: %s", srvcompprog);
1956     }
1957     switch (*pid = fork()) {
1958     case -1:
1959         errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
1960         aclose(outpipe[0]);
1961         aclose(outpipe[1]);
1962         aclose(errpipe[0]);
1963         aclose(errpipe[1]);
1964         return (-1);
1965     default:
1966         rval = dup2(outpipe[1], outfd);
1967         if (rval < 0)
1968             errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
1969         aclose(outpipe[1]);
1970         aclose(outpipe[0]);
1971         aclose(errpipe[1]);
1972         filter = g_new0(filter_t, 1);
1973         filter->fd = errpipe[0];
1974         filter->name = name;
1975         filter->buffer = NULL;
1976         filter->size = 0;
1977         filter->allocated_size = 0;
1978         filter->event = event_register((event_id_t)filter->fd, EV_READFD,
1979                                        handle_filter_stderr, filter);
1980         return (rval);
1981     case 0:
1982         close(outpipe[1]);
1983         close(errpipe[0]);
1984         if (dup2(outpipe[0], 0) < 0) {
1985             error(_("err dup2 in: %s"), strerror(errno));
1986             /*NOTREACHED*/
1987         }
1988         if (dup2(outfd, 1) == -1) {
1989             error(_("err dup2 out: %s"), strerror(errno));
1990             /*NOTREACHED*/
1991         }
1992         if (dup2(errpipe[1], 2) == -1) {
1993             error(_("err dup2 err: %s"), strerror(errno));
1994             /*NOTREACHED*/
1995         }
1996         if (comptype != COMP_SERVER_CUST) {
1997             char *base = stralloc(COMPRESS_PATH);
1998             log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
1999             amfree(base);
2000             safe_fd(-1, 0);
2001             set_root_privs(-1);
2002             execlp(COMPRESS_PATH, COMPRESS_PATH, (  comptype == COMP_BEST ?
2003                 COMPRESS_BEST_OPT : COMPRESS_FAST_OPT), (char *)NULL);
2004             error(_("error: couldn't exec %s: %s"), COMPRESS_PATH, strerror(errno));
2005             /*NOTREACHED*/
2006         } else if (*srvcompprog) {
2007             char *base = stralloc(srvcompprog);
2008             log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2009             amfree(base);
2010             safe_fd(-1, 0);
2011             set_root_privs(-1);
2012             execlp(srvcompprog, srvcompprog, (char *)0);
2013             error(_("error: couldn't exec server custom compression '%s'.\n"), srvcompprog);
2014             /*NOTREACHED*/
2015         }
2016     }
2017     /*NOTREACHED*/
2018     return (-1);
2019 }
2020
2021 /*
2022  * Runs encrypt with the first arg as its stdout.  Returns
2023  * 0 on success or negative if error, and it's pid via the second
2024  * argument.  The outfd arg is dup2'd to the pipe to the encrypt
2025  * process.
2026  */
2027 static int
2028 runencrypt(
2029     int         outfd,
2030     pid_t *     pid,
2031     encrypt_t   encrypttype)
2032 {
2033     int outpipe[2], rval;
2034     int errpipe[2];
2035     filter_t *filter;
2036
2037     assert(outfd >= 0);
2038     assert(pid != NULL);
2039
2040     /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
2041     if (pipe(outpipe) < 0) {
2042         errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2043         return (-1);
2044     }
2045
2046     /* errpipe[0] is pipe's output, outpipe[1] is input. */
2047     if (pipe(errpipe) < 0) {
2048         errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2049         return (-1);
2050     }
2051
2052     g_debug("execute: %s", srv_encrypt);
2053     switch (*pid = fork()) {
2054     case -1:
2055         errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
2056         aclose(outpipe[0]);
2057         aclose(outpipe[1]);
2058         aclose(errpipe[0]);
2059         aclose(errpipe[1]);
2060         return (-1);
2061     default: {
2062         char *base;
2063         rval = dup2(outpipe[1], outfd);
2064         if (rval < 0)
2065             errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
2066         aclose(outpipe[1]);
2067         aclose(outpipe[0]);
2068         aclose(errpipe[1]);
2069         filter = g_new0(filter_t, 1);
2070         filter->fd = errpipe[0];
2071         base = g_strdup(srv_encrypt);
2072         filter->name = g_strdup(basename(base));
2073         amfree(base);
2074         filter->buffer = NULL;
2075         filter->size = 0;
2076         filter->allocated_size = 0;
2077         filter->event = event_register((event_id_t)filter->fd, EV_READFD,
2078                                        handle_filter_stderr, filter);
2079         return (rval);
2080         }
2081     case 0: {
2082         char *base;
2083         if (dup2(outpipe[0], 0) < 0) {
2084             error(_("err dup2 in: %s"), strerror(errno));
2085             /*NOTREACHED*/
2086         }
2087         if (dup2(outfd, 1) < 0 ) {
2088             error(_("err dup2 out: %s"), strerror(errno));
2089             /*NOTREACHED*/
2090         }
2091         if (dup2(errpipe[1], 2) == -1) {
2092             error(_("err dup2 err: %s"), strerror(errno));
2093             /*NOTREACHED*/
2094         }
2095         close(errpipe[0]);
2096         base = stralloc(srv_encrypt);
2097         log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2098         amfree(base);
2099         safe_fd(-1, 0);
2100         if ((encrypttype == ENCRYPT_SERV_CUST) && *srv_encrypt) {
2101             set_root_privs(-1);
2102             execlp(srv_encrypt, srv_encrypt, (char *)0);
2103             error(_("error: couldn't exec server custom encryption '%s'.\n"), srv_encrypt);
2104             /*NOTREACHED*/
2105         }
2106         }
2107     }
2108     /*NOTREACHED*/
2109     return (-1);
2110 }
2111
2112
2113 /* -------------------- */
2114
2115 static void
2116 sendbackup_response(
2117     void *              datap,
2118     pkt_t *             pkt,
2119     security_handle_t * sech)
2120 {
2121     int ports[NSTREAMS], *response_error = datap, i;
2122     char *p;
2123     char *tok;
2124     char *extra;
2125
2126     assert(response_error != NULL);
2127     assert(sech != NULL);
2128
2129     security_close_connection(sech, hostname);
2130
2131     if (pkt == NULL) {
2132         errstr = newvstrallocf(errstr, _("[request failed: %s]"),
2133             security_geterror(sech));
2134         *response_error = 1;
2135         return;
2136     }
2137
2138     extra = NULL;
2139     memset(ports, 0, SIZEOF(ports));
2140     if (pkt->type == P_NAK) {
2141 #if defined(PACKET_DEBUG)
2142         g_fprintf(stderr, _("got nak response:\n----\n%s\n----\n\n"), pkt->body);
2143 #endif
2144
2145         tok = strtok(pkt->body, " ");
2146         if (tok == NULL || strcmp(tok, "ERROR") != 0)
2147             goto bad_nak;
2148
2149         tok = strtok(NULL, "\n");
2150         if (tok != NULL) {
2151             errstr = newvstrallocf(errstr, "NAK: %s", tok);
2152             *response_error = 1;
2153         } else {
2154 bad_nak:
2155             errstr = newvstrallocf(errstr, "request NAK");
2156             *response_error = 2;
2157         }
2158         return;
2159     }
2160
2161     if (pkt->type != P_REP) {
2162         errstr = newvstrallocf(errstr, _("received strange packet type %s: %s"),
2163             pkt_type2str(pkt->type), pkt->body);
2164         *response_error = 1;
2165         return;
2166     }
2167
2168     dbprintf(_("got response:\n----\n%s\n----\n\n"), pkt->body);
2169
2170     for(i = 0; i < NSTREAMS; i++) {
2171         ports[i] = -1;
2172         streams[i].fd = NULL;
2173     }
2174
2175     p = pkt->body;
2176     while((tok = strtok(p, " \n")) != NULL) {
2177         p = NULL;
2178
2179         /*
2180          * Error response packets have "ERROR" followed by the error message
2181          * followed by a newline.
2182          */
2183         if (strcmp(tok, "ERROR") == 0) {
2184             tok = strtok(NULL, "\n");
2185             if (tok == NULL)
2186                 tok = _("[bogus error packet]");
2187             errstr = newvstrallocf(errstr, "%s", tok);
2188             *response_error = 2;
2189             return;
2190         }
2191
2192         /*
2193          * Regular packets have CONNECT followed by three streams
2194          */
2195         if (strcmp(tok, "CONNECT") == 0) {
2196
2197             /*
2198              * Parse the three stream specifiers out of the packet.
2199              */
2200             for (i = 0; i < NSTREAMS; i++) {
2201                 tok = strtok(NULL, " ");
2202                 if (tok == NULL || strcmp(tok, streams[i].name) != 0) {
2203                     extra = vstrallocf(
2204                                 _("CONNECT token is \"%s\": expected \"%s\""),
2205                                 tok ? tok : "(null)",
2206                                 streams[i].name);
2207                     goto parse_error;
2208                 }
2209                 tok = strtok(NULL, " \n");
2210                 if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) {
2211                     extra = vstrallocf(
2212                         _("CONNECT %s token is \"%s\": expected a port number"),
2213                         streams[i].name, tok ? tok : "(null)");
2214                     goto parse_error;
2215                 }
2216             }
2217             continue;
2218         }
2219
2220         /*
2221          * OPTIONS [options string] '\n'
2222          */
2223         if (strcmp(tok, "OPTIONS") == 0) {
2224             tok = strtok(NULL, "\n");
2225             if (tok == NULL) {
2226                 extra = vstrallocf(_("OPTIONS token is missing"));
2227                 goto parse_error;
2228             }
2229
2230             while((p = strchr(tok, ';')) != NULL) {
2231                 char ch;
2232                 *p++ = '\0';
2233                 if(strncmp_const_skip(tok, "features=", tok, ch) == 0) {
2234                     char *u = strchr(tok, ';');
2235                     ch = ch;
2236                     if (u)
2237                        *u = '\0';
2238                     am_release_feature_set(their_features);
2239                     if((their_features = am_string_to_feature(tok)) == NULL) {
2240                         errstr = newvstrallocf(errstr,
2241                                               _("OPTIONS: bad features value: %s"),
2242                                               tok);
2243                         goto parse_error;
2244                     }
2245                     if (u)
2246                        *u = ';';
2247                 }
2248                 tok = p;
2249             }
2250             continue;
2251         }
2252
2253         extra = vstrallocf(_("next token is \"%s\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\""),
2254                           tok ? tok : "(null)");
2255         goto parse_error;
2256     }
2257
2258     if (dumper_kencrypt == KENCRYPT_WILL_DO)
2259         dumper_kencrypt = KENCRYPT_YES;
2260
2261     /*
2262      * Connect the streams to their remote ports
2263      */
2264     for (i = 0; i < NSTREAMS; i++) {
2265         if (ports[i] == -1)
2266             continue;
2267         streams[i].fd = security_stream_client(sech, ports[i]);
2268         if (streams[i].fd == NULL) {
2269             errstr = newvstrallocf(errstr,
2270                 _("[could not connect %s stream: %s]"),
2271                 streams[i].name,
2272                 security_geterror(sech));
2273             goto connect_error;
2274         }
2275     }
2276
2277     /*
2278      * Authenticate the streams
2279      */
2280     for (i = 0; i < NSTREAMS; i++) {
2281         if (streams[i].fd == NULL)
2282             continue;
2283         if (security_stream_auth(streams[i].fd) < 0) {
2284             errstr = newvstrallocf(errstr,
2285                 _("[could not authenticate %s stream: %s]"),
2286                 streams[i].name, 
2287                 security_stream_geterror(streams[i].fd));
2288             goto connect_error;
2289         }
2290     }
2291
2292     /*
2293      * The MESGFD and DATAFD streams are mandatory.  If we didn't get
2294      * them, complain.
2295      */
2296     if (streams[MESGFD].fd == NULL || streams[DATAFD].fd == NULL) {
2297         errstr = newvstrallocf(errstr, _("[couldn't open MESG or INDEX streams]"));
2298         goto connect_error;
2299     }
2300
2301     /* everything worked */
2302     *response_error = 0;
2303     return;
2304
2305 parse_error:
2306     errstr = newvstrallocf(errstr,
2307                           _("[parse of reply message failed: %s]"),
2308                           extra ? extra : _("(no additional information)"));
2309     amfree(extra);
2310     *response_error = 2;
2311     return;
2312
2313 connect_error:
2314     stop_dump();
2315     *response_error = 1;
2316 }
2317
2318 static char *
2319 dumper_get_security_conf(
2320     char *      string,
2321     void *      arg)
2322 {
2323         (void)arg;      /* Quiet unused parameter warning */
2324
2325         if(!string || !*string)
2326                 return(NULL);
2327
2328         if(strcmp(string, "krb5principal")==0) {
2329                 return(getconf_str(CNF_KRB5PRINCIPAL));
2330         } else if(strcmp(string, "krb5keytab")==0) {
2331                 return(getconf_str(CNF_KRB5KEYTAB));
2332         } else if(strcmp(string, "amandad_path")==0) {
2333                 return (amandad_path);
2334         } else if(strcmp(string, "client_username")==0) {
2335                 return (client_username);
2336         } else if(strcmp(string, "client_port")==0) {
2337                 return (client_port);
2338         } else if(strcmp(string, "ssh_keys")==0) {
2339                 return (ssh_keys);
2340         } else if(strcmp(string, "kencrypt")==0) {
2341                 if (dumper_kencrypt == KENCRYPT_YES)
2342                     return ("yes");
2343                 else
2344                     return (NULL);
2345         }
2346         return(NULL);
2347 }
2348
2349 static int
2350 startup_dump(
2351     const char *hostname,
2352     const char *disk,
2353     const char *device,
2354     int         level,
2355     const char *dumpdate,
2356     const char *progname,
2357     const char *amandad_path,
2358     const char *client_username,
2359     const char *client_port,
2360     const char *ssh_keys,
2361     const char *auth,
2362     const char *options)
2363 {
2364     char level_string[NUM_STR_SIZE];
2365     char *req = NULL;
2366     int response_error;
2367     const security_driver_t *secdrv;
2368     char *application_api;
2369     int has_features;
2370     int has_hostname;
2371     int has_device;
2372     int has_config;
2373
2374     (void)disk;                 /* Quiet unused parameter warning */
2375     (void)amandad_path;         /* Quiet unused parameter warning */
2376     (void)client_username;      /* Quiet unused parameter warning */
2377     (void)client_port;          /* Quiet unused parameter warning */
2378     (void)ssh_keys;             /* Quiet unused parameter warning */
2379     (void)auth;                 /* Quiet unused parameter warning */
2380
2381     has_features = am_has_feature(their_features, fe_req_options_features);
2382     has_hostname = am_has_feature(their_features, fe_req_options_hostname);
2383     has_config   = am_has_feature(their_features, fe_req_options_config);
2384     has_device   = am_has_feature(their_features, fe_sendbackup_req_device);
2385
2386     /*
2387      * Default to bsd authentication if none specified.  This is gross.
2388      *
2389      * Options really need to be pre-parsed into some sort of structure
2390      * much earlier, and then flattened out again before transmission.
2391      */
2392
2393     g_snprintf(level_string, SIZEOF(level_string), "%d", level);
2394     if(strcmp(progname, "DUMP") == 0
2395        || strcmp(progname, "GNUTAR") == 0) {
2396         application_api = "";
2397     } else {
2398         application_api = "BACKUP ";
2399     }
2400     req = vstralloc("SERVICE sendbackup\n",
2401                     "OPTIONS ",
2402                     has_features ? "features=" : "",
2403                     has_features ? our_feature_string : "",
2404                     has_features ? ";" : "",
2405                     has_hostname ? "hostname=" : "",
2406                     has_hostname ? hostname : "",
2407                     has_hostname ? ";" : "",
2408                     has_config   ? "config=" : "",
2409                     has_config   ? get_config_name() : "",
2410                     has_config   ? ";" : "",
2411                     "\n",
2412                     NULL);
2413
2414     amfree(dle_str);
2415     if (am_has_feature(their_features, fe_req_xml)) {
2416         char *p = NULL;
2417         char *pclean;
2418         vstrextend(&p, "<dle>\n", NULL);
2419         if (*application_api != '\0') {
2420             vstrextend(&p, "  <program>APPLICATION</program>\n", NULL);
2421         } else {
2422             vstrextend(&p, "  <program>", progname, "</program>\n", NULL);
2423         }
2424         vstrextend(&p, "  ", b64disk, "\n", NULL);
2425         if (device && has_device) {
2426             vstrextend(&p, "  ", b64device, "\n",
2427                        NULL);
2428         }
2429         vstrextend(&p, "  <level>", level_string, "</level>\n", NULL);
2430         vstrextend(&p, options+1, "</dle>\n", NULL);
2431         pclean = clean_dle_str_for_client(p, their_features);
2432         vstrextend(&req, pclean, NULL);
2433         amfree(pclean);
2434         dle_str = p;
2435     } else if (*application_api != '\0') {
2436         errstr = newvstrallocf(errstr,
2437                 _("[does not support application-api]"));
2438         amfree(req);
2439         return 2;
2440     } else {
2441         if (auth == NULL) {
2442             auth = "BSD";
2443         }
2444         vstrextend(&req,
2445                    progname,
2446                    " ", qdiskname,
2447                    " ", device && has_device ? device : "",
2448                    " ", level_string,
2449                    " ", dumpdate,
2450                    " OPTIONS ", options,
2451                    "\n",
2452                    NULL);
2453     }
2454
2455     dbprintf(_("send request:\n----\n%s\n----\n\n"), req);
2456     secdrv = security_getdriver(auth);
2457     if (secdrv == NULL) {
2458         errstr = newvstrallocf(errstr,
2459                 _("[could not find security driver '%s']"), auth);
2460         amfree(req);
2461         return 2;
2462     }
2463
2464     protocol_sendreq(hostname, secdrv, dumper_get_security_conf, req,
2465         STARTUP_TIMEOUT, sendbackup_response, &response_error);
2466
2467     amfree(req);
2468
2469     protocol_run();
2470     return (response_error);
2471 }