utils/text_export/text_export.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- dump_putc
- dump_fputs
- get_program_name
- syntax
- parse_options
- load_classes
- output_object
- seperate_time_t
- main
1 /* text_export - output RIP database into text files of RPSL objects */
2
3 /*
4 Copyright (c) 2000,2001,2002 RIPE NCC
5
6
7 All Rights Reserved
8
9 Permission to use, copy, modify, and distribute this software and its
10 documentation for any purpose and without fee is hereby granted,
11 provided that the above copyright notice appear in all copies and that
12 both that copyright notice and this permission notice appear in
13 supporting documentation, and that the name of the author not be
14 used in advertising or publicity pertaining to distribution of the
15 software without specific, written prior permission.
16
17 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
18 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
19 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
20 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 */
24
25 /* $Id: text_export.c,v 1.4 2002/02/19 17:22:47 shane Exp $ */
26
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <time.h>
33 #include <assert.h>
34
35 #include "mysql_driver.h"
36 #include "defs.h"
37 #include "memwrap.h"
38 #include "query_instructions.h"
39
40 /* global variables */
41 char *Program_Name;
42 int Verbose = 0;
43 long long Amt_Dumped = 0;
44
45 /* structure holding information used to connect to SQL server */
46 struct database_info {
47 char *hostname;
48 int port;
49 char *database;
50 char *user;
51 char *password;
52 };
53
54 /* structure for class */
55 struct class {
56 char *name;
57 FILE *fp;
58 char *short_name;
59 FILE *short_fp;
60 };
61
62 /* output functions which track amount of data written */
63 #define dump_putc(c,stream) (Amt_Dumped++, putc((c),(stream)))
/* [<][>][^][v][top][bottom][index][help] */
64 void dump_fputs(const char *s, FILE *stream)
/* [<][>][^][v][top][bottom][index][help] */
65 {
66 Amt_Dumped += fputs(s, stream);
67 }
68
69 /* extracts the program name from command-line arguments */
70 void get_program_name(int argc, char **argv)
/* [<][>][^][v][top][bottom][index][help] */
71 {
72 char *p;
73
74 if (argc <= 0) {
75 fprintf(stderr, "ERROR: unable to determine program name\n");
76 exit(1);
77 }
78
79 p = strrchr(argv[0], '/');
80 if (p == NULL) {
81 Program_Name = argv[0];
82 } else {
83 Program_Name = p+1;
84 }
85 }
86
87 void syntax()
/* [<][>][^][v][top][bottom][index][help] */
88 {
89 fprintf(stderr,
90 "Syntax: %s [-v] [-h hostname] [-P port] [-u user] [-p password] "
91 "database\n", Program_Name);
92 }
93
94 /* exits on error */
95 void parse_options(int argc, char **argv, struct database_info *db)
/* [<][>][^][v][top][bottom][index][help] */
96 {
97 int opt;
98
99 /* defaults */
100 db->hostname = "localhost";
101 db->port = 0;
102 db->user = "";
103 db->password = "";
104
105 /* parse command line arguments with the ever-handy getopt() */
106 while ((opt = getopt(argc, argv, "vh:u:p:P:")) != -1) {
107 switch (opt) {
108 case 'v':
109 Verbose++;
110 break;
111 case 'h':
112 db->hostname = optarg;
113 break;
114 case 'P':
115 db->port = atoi(optarg);
116 break;
117 case 'u':
118 db->user = optarg;
119 break;
120 case 'p':
121 db->password = optarg;
122 break;
123 case '?':
124 syntax();
125 exit(1);
126 }
127 }
128
129 /* check remaining argument count */
130 argc -= optind;
131 argv += optind;
132 if (argc != 1) {
133 syntax();
134 exit(1);
135 }
136
137 /* remaining argument should be database name */
138 db->database = argv[0];
139 }
140
141 int load_classes(struct class **c)
/* [<][>][^][v][top][bottom][index][help] */
142 {
143 char* const *class_names;
144 int num_classes;
145 struct class *tmp;
146 int i;
147 char fname[64];
148
149 class_names = DF_get_class_names();
150 num_classes = 0;
151 while (class_names[num_classes] != NULL) {
152 num_classes++;
153 }
154 wr_malloc((void *)&tmp, sizeof(struct class) * num_classes);
155
156 for (i=0; i<num_classes; i++) {
157 tmp[i].name = class_names[i];
158 tmp[i].short_name =
159 DF_get_class_code(DF_class_name2type(class_names[i]));
160
161 assert(strlen(tmp[i].name) < 60);
162 strcpy(fname, "db.");
163 strcat(fname, tmp[i].name);
164 tmp[i].fp = fopen(fname, "w+");
165 if (tmp[i].fp == NULL) {
166 fprintf(stderr, "%s: error opening file \"%s\"\n",
167 Program_Name, fname);
168 exit(1);
169 }
170
171 assert(strlen(tmp[i].short_name) < 60);
172 strcpy(fname, "db.");
173 strcat(fname, tmp[i].short_name);
174 tmp[i].short_fp = fopen(fname, "w+");
175 if (tmp[i].short_fp == NULL) {
176 fprintf(stderr, "%s: error opening file \"%s\"\n",
177 Program_Name, fname);
178 exit(1);
179 }
180 }
181
182 *c = tmp;
183 return num_classes;
184 }
185
186 /* outputs the object to the appropriate files */
187 void output_object(char *object, struct class *c, int num_classes)
/* [<][>][^][v][top][bottom][index][help] */
188 {
189 char *p;
190 int i;
191
192 p = strchr(object, ':');
193 if (p == NULL) {
194 fprintf(stderr,
195 "%s: format error in database; no colon in object, \"%s\"\n",
196 Program_Name, object);
197 exit(1);
198 }
199 *p = '\0';
200
201 for (i=0; i<num_classes; i++) {
202 if (strcmp(c[i].name, object) == 0) {
203 *p = ':';
204 dump_fputs(object, c[i].fp);
205 dump_putc('\n', c[i].fp);
206 p = QI_fast_output(object);
207 dump_fputs(p, c[i].short_fp);
208 free(p);
209 dump_putc('\n', c[i].short_fp);
210 return;
211 }
212 }
213
214 fprintf(stderr, "%s: unknown class of object found, \"%s\"\n",
215 Program_Name, object);
216 exit(1);
217 }
218
219 void seperate_time_t(int n, int *hours, int *minutes, int *seconds)
/* [<][>][^][v][top][bottom][index][help] */
220 {
221 *hours = n / (60 * 60);
222 n %= (60 * 60);
223 *minutes = n / 60;
224 n %= 60;
225 *seconds = n;
226 }
227
228 /* program entry point */
229 int main(int argc, char **argv)
/* [<][>][^][v][top][bottom][index][help] */
230 {
231 struct database_info db;
232 er_ret_t ret;
233 SQ_connection_t *sql;
234 int num_classes;
235 struct class *classes;
236 SQ_result_set_t *rs;
237 SQ_row_t *row;
238 int num_object;
239 time_t start, end;
240 const struct tm *now;
241 char tmp[64];
242 double runtime;
243 int h, m, s;
244
245 /* turn off output buffering (why isn't this the default?) */
246 setbuf(stdout, NULL);
247
248 /* record our program's name for any future use */
249 get_program_name(argc, argv);
250
251 /* parse our command line */
252 parse_options(argc, argv, &db);
253 if (Verbose) {
254 printf("\n");
255 printf("Command line options\n");
256 printf(" database: %s\n", db.database);
257 printf(" hostname: %s\n", db.hostname);
258 if (db.port) {
259 printf(" port: %d\n", db.port);
260 } else {
261 printf(" port: <default>\n");
262 }
263 printf(" user: %s\n", (*db.user == '\0') ? "<default>" : db.user);
264 printf(" password: <hidden>\n");
265 }
266
267 /* connect to the server */
268
269 if (Verbose) {
270 printf("\n");
271 printf("Connecting to server...\n");
272 }
273
274 ret = SQ_try_connection(&sql,
275 db.hostname, db.port, db.database, db.user, db.password);
276 if (!NOERR(ret)) {
277 fprintf(stderr, "%s: error connecting to database; %s\n", Program_Name,
278 SQ_error(sql));
279 exit(1);
280 }
281
282 if (Verbose) {
283 printf("Connected.\n");
284 }
285
286
287 /* submit our query */
288 if (Verbose) {
289 printf("\n");
290 printf("Submitting query...\n");
291 }
292
293 if (SQ_execute_query_nostore(sql,
294 "SELECT object FROM last "
295 "WHERE (thread_id=0) AND (object_type<>100) AND (object<>\"\")",
296 &rs) != 0)
297 {
298 fprintf(stderr, "%s: error with query; %s\n", Program_Name,
299 SQ_error(sql));
300 exit(1);
301 }
302
303 if (Verbose) {
304 printf("Submitted.\n");
305 }
306
307
308 /* initialize our class information (also creates output files) */
309 num_classes = load_classes(&classes);
310
311 /* record start time */
312 time(&start);
313
314 if (Verbose) {
315 printf("\n");
316 printf("Loaded %d classes\n", num_classes);
317 printf("Created %d output files\n", num_classes * 2);
318 printf("\n");
319 now = localtime(&start);
320 strftime(tmp, sizeof(tmp), "Dump starting... %Y-%m-%d %H:%M:%S %Z",
321 now);
322 puts(tmp);
323 }
324
325
326 /* read our MySQL data */
327 num_object = 0;
328 while ((row = SQ_row_next(rs)) != NULL) {
329 char *object = SQ_get_column_string_nocopy(rs, row, 0);
330 output_object(object, classes, num_classes);
331 num_object++;
332 }
333
334 /* close up shop */
335 time(&end);
336
337 /* output final results, if any */
338 if (Verbose) {
339 now = localtime(&end);
340 strftime(tmp, sizeof(tmp), "Dump finished... %Y-%m-%d %H:%M:%S %Z",
341 now);
342 puts(tmp);
343 runtime = difftime(end, start);
344 seperate_time_t((int)(runtime + 0.5), &h, &m, &s);
345 printf("Wrote %d objects in %d:%02d:%02d\n", num_object, h, m, s);
346 printf(" %12.2f objects/second\n", num_object/runtime);
347 printf(" %12.2f byte/second\n", Amt_Dumped/runtime);
348 printf("\n");
349 }
350
351 /* assume that 0 outputs is an error */
352 if (num_object == 0) {
353 fprintf(stderr, "No objects dumped, exiting with error\n");
354 exit(1);
355 }
356
357 return 0;
358 }
359