## utils/text_export/text_export.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. dump_putc
2. dump_fputs
3. get_program_name
4. syntax
5. parse_options
6. load_classes
7. output_object
8. seperate_time_t
9. main

       1 /* text_export - output RIP database into text files of RPSL objects */
       2
       3 /*
       4 Copyright (c) 2000                      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.3 2000/11/29 18:26:35 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

/* [<][>][^][v][top][bottom][index][help] */