avoid using tmpnam() for security reasons.
[metze/wireshark/wip.git] / mergecap.c
1 /* Combine two dump files, either by appending or by merging by timestamp
2  *
3  * $Id: mergecap.c,v 1.22 2004/06/29 20:59:23 ulfl Exp $
4  *
5  * Written by Scott Renfro <scott@renfro.org> based on
6  * editcap by Richard Sharpe and Guy Harris
7  *
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <glib.h>
17
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21
22 #ifdef HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
25
26 #include <string.h>
27 #include "wtap.h"
28
29 #ifdef NEED_GETOPT_H
30 #include "getopt.h"
31 #endif
32
33 #include "cvsversion.h"
34 #include "merge.h"
35
36 #ifdef HAVE_IO_H
37 # include <io.h>
38 #endif
39
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43
44
45 /*
46  * Show the usage
47  */
48 static void
49 usage(void)
50 {
51   int i;
52   const char *string;
53
54   printf("Usage: mergecap [-hva] [-s <snaplen>] [-T <encap type>]\n");
55   printf("          [-F <capture type>] -w <outfile> <infile> [...]\n\n");
56   printf("  where\t-h produces this help listing.\n");
57   printf("       \t-v verbose operation, default is silent\n");
58   printf("       \t-a files should be concatenated, not merged\n");
59   printf("       \t     Default merges based on frame timestamps\n");
60   printf("       \t-s <snaplen>: truncate packets to <snaplen> bytes of data\n");
61   printf("       \t-w <outfile>: sets output filename to <outfile>\n");
62   printf("       \t-T <encap type> encapsulation type to use:\n");
63   for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
64       string = wtap_encap_short_string(i);
65       if (string != NULL)
66         printf("       \t     %s - %s\n",
67           string, wtap_encap_string(i));
68   }
69   printf("       \t     default is the same as the first input file\n");
70   printf("       \t-F <capture type> capture file type to write:\n");
71   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
72     if (wtap_dump_can_open(i))
73       printf("       \t     %s - %s\n",
74         wtap_file_type_short_string(i), wtap_file_type_string(i));
75   }
76   printf("       \t     default is libpcap\n");
77 }
78
79
80
81 int
82 main(int argc, char *argv[])
83 {
84   extern char *optarg;
85   extern int   optind;
86   int          opt;
87   char        *p;
88   gboolean     do_append     = FALSE;
89   int          in_file_count = 0;
90   merge_in_file_t   *in_files      = NULL;
91   merge_out_file_t   out_file;
92   int          err;
93   char        *out_filename;
94
95   /* initialize out_file */
96   out_file.fd         = 0;
97   out_file.pdh        = NULL;              /* wiretap dumpfile */
98   out_file.file_type  = WTAP_FILE_PCAP;    /* default to "libpcap" */
99   out_file.frame_type = -2;                /* leave type alone */
100   out_file.snaplen    = 0;                 /* no limit */
101   out_file.count      = 1;                 /* frames output */
102
103   merge_verbose = VERBOSE_ERRORS;
104
105   /* Process the options first */
106   while ((opt = getopt(argc, argv, "hvas:T:F:w:")) != -1) {
107
108     switch (opt) {
109     case 'w':
110           out_filename = optarg;
111       break;
112
113     case 'a':
114       do_append = !do_append;
115       break;
116
117     case 'T':
118       out_file.frame_type = wtap_short_string_to_encap(optarg);
119       if (out_file.frame_type < 0) {
120         fprintf(stderr, "mergecap: \"%s\" is not a valid encapsulation type\n",
121             optarg);
122         exit(1);
123       }
124       break;
125
126     case 'F':
127       out_file.file_type = wtap_short_string_to_file_type(optarg);
128       if (out_file.file_type < 0) {
129         fprintf(stderr, "mergecap: \"%s\" is not a valid capture file type\n",
130             optarg);
131         exit(1);
132       }
133       break;
134
135     case 'v':
136       merge_verbose = VERBOSE_ALL;
137       break;
138
139     case 's':
140       out_file.snaplen = strtol(optarg, &p, 10);
141       if (p == optarg || *p != '\0') {
142         fprintf(stderr, "mergecap: \"%s\" is not a valid snapshot length\n",
143             optarg);
144         exit(1);
145       }
146       break;
147
148     case 'h':
149       printf("mergecap version %s"
150 #ifdef CVSVERSION
151           " (" CVSVERSION ")"
152 #endif
153           "\n", VERSION);
154       usage();
155       exit(0);
156       break;
157
158     case '?':              /* Bad options if GNU getopt */
159       usage();
160       exit(1);
161       break;
162
163     }
164
165   }
166
167   /* check for proper args; at a minimum, must have an output
168    * filename and one input file
169    */
170   in_file_count = argc - optind;
171   if (!out_filename) {
172     fprintf(stderr, "mergecap: an output filename must be set with -w\n");
173     fprintf(stderr, "          run with -h for help\n");
174     exit(1);
175   }
176
177   /* open the input files */
178   in_file_count = merge_open_in_files(in_file_count, &argv[optind], &in_files, &err);
179   if (in_file_count < 1) {
180     fprintf(stderr, "mergecap: No valid input files\n");
181     exit(1);
182   }
183
184   /* set the outfile frame type */
185   if (out_file.frame_type == -2)
186     out_file.frame_type = merge_select_frame_type(in_file_count, in_files);
187
188   /* open the outfile */
189   if (strncmp(out_filename, "-", 2) == 0) {  
190     /* use stdout as the outfile */
191     out_file.fd = 1 /*stdout*/;
192   } else {
193     /* open the outfile */
194     out_file.fd = open(out_filename, O_BINARY | O_WRONLY);
195   }
196   if(out_file.fd == -1) {
197     fprintf(stderr, "mergecap: couldn't open output file\n");
198     exit(1);
199   }  
200     
201   /* prepare the outfile */
202   if (!merge_open_outfile(&out_file, merge_max_snapshot_length(in_file_count, in_files), &err)) {
203     merge_close_in_files(in_file_count, in_files);
204     exit(1);
205   }
206
207   /* do the merge (or append) */
208   if (do_append)
209     merge_append_files(in_file_count, in_files, &out_file, &err);
210   else
211     merge_files(in_file_count, in_files, &out_file, &err);
212
213   merge_close_in_files(in_file_count, in_files);
214   merge_close_outfile(&out_file);
215
216   free(in_files);
217
218   return 0;
219 }