## utils/text_export/text_export.c

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

## DEFINITIONS

This source file includes following functions.

1. dump_fputs
2. get_program_name
3. syntax
4. parse_options
5. load_classes
6. output_object
7. seperate_time_t
8. 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.5 2002/04/16 11:53:00 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 int Dump_Short = 0;
      45
      46 /* structure holding information used to connect to SQL server */
      47 struct database_info {
      48     char *hostname;
      49     int port;
      50     char *database;
      51     char *user;
      52     char *password;
      53 };
      54
      55 /* structure for class */
      56 struct class {
      57     char *name;
      58     FILE *fp;
      59     char *short_name;
      60     FILE *short_fp;
      61 };
      62
      63 /* output functions which track amount of data written */
      64 #define dump_putc(c,stream)  (Amt_Dumped++, putc((c),(stream)))
      65 void
      66 dump_fputs (const char *s, FILE *stream)
         /* [<][>][^][v][top][bottom][index][help] */
      67 {
      68     Amt_Dumped += fputs(s, stream);
      69 }
      70
      71 /* extracts the program name from command-line arguments */
      72 void
      73 get_program_name (int argc, char **argv)
         /* [<][>][^][v][top][bottom][index][help] */
      74 {
      75     char *p;
      76
      77     if (argc <= 0) {
      78         fprintf(stderr, "ERROR: unable to determine program name\n");
      79         exit(1);
      80     }
      81
      82     p = strrchr(argv[0], '/');
      83     if (p == NULL) {
      84         Program_Name = argv[0];
      85     } else {
      86         Program_Name = p+1;
      87     }
      88 }
      89
      90 void
      91 syntax ()
         /* [<][>][^][v][top][bottom][index][help] */
      92 {
      93     fprintf(stderr,
      94         "Syntax: %s [-v] [-h hostname] [-P port] [-u user] [-p password] [-s]"
      95         "database\n", Program_Name);
      96 }
      97
      98 /* exits on error */
      99 void
     100 parse_options (int argc, char **argv, struct database_info *db, int *dump_short)
         /* [<][>][^][v][top][bottom][index][help] */
     101 {
     102     int opt;
     103
     104     /* defaults */
     105     db->hostname = "localhost";
     106     db->port = 0;
     107     db->user = "";
     108     db->password = "";
     109     *dump_short = 0;
     110
     111     /* parse command line arguments with the ever-handy getopt() */
     112     while ((opt = getopt(argc, argv, "vh:u:p:P:s")) != -1) {
     113         switch (opt) {
     114             case 'v':
     115                 Verbose++;
     116                 break;
     117             case 'h':
     118                 db->hostname = optarg;
     119                 break;
     120             case 'P':
     121                 db->port = atoi(optarg);
     122                 break;
     123             case 'u':
     124                 db->user = optarg;
     125                 break;
     126             case 'p':
     127                 db->password = optarg;
     128                 break;
     129             case 's':
     130                 *dump_short = 1;
     131                 break;
     132             case '?':
     133                 syntax();
     134                 exit(1);
     135         }
     136     }
     137
     138     /* check remaining argument count */
     139     argc -= optind;
     140     argv += optind;
     141     if (argc != 1) {
     142         syntax();
     143         exit(1);
     144     }
     145
     146     /* remaining argument should be database name */
     147     db->database = argv[0];
     148 }
     149
     150 int
     151 load_classes (struct class **c)
         /* [<][>][^][v][top][bottom][index][help] */
     152 {
     153     char* const *class_names;
     154     int num_classes;
     155     struct class *tmp;
     156     int i;
     157     char fname[64];
     158
     159     class_names = DF_get_class_names();
     160     num_classes = 0;
     161     while (class_names[num_classes] != NULL) {
     162         num_classes++;
     163     }
     164     wr_malloc((void *)&tmp, sizeof(struct class) * num_classes);
     165
     166     for (i=0; i<num_classes; i++) {
     167         tmp[i].name = class_names[i];
     168
     169         assert(strlen(tmp[i].name) < 60);
     170         strcpy(fname, "db.");
     171         strcat(fname, tmp[i].name);
     172         tmp[i].fp = fopen(fname, "w+");
     173         if (tmp[i].fp == NULL) {
     174             fprintf(stderr, "%s: error opening file \"%s\"\n",
     175                 Program_Name, fname);
     176             exit(1);
     177         }
     178
     179         if (Dump_Short) {
     180             tmp[i].short_name =
     181                 DF_get_class_code(DF_class_name2type(class_names[i]));
     182             assert(strlen(tmp[i].short_name) < 60);
     183             strcpy(fname, "db.");
     184             strcat(fname, tmp[i].short_name);
     185             tmp[i].short_fp = fopen(fname, "w+");
     186             if (tmp[i].short_fp == NULL) {
     187                 fprintf(stderr, "%s: error opening file \"%s\"\n",
     188                     Program_Name, fname);
     189                 exit(1);
     190             }
     191         } else {
     192             tmp[i].short_name = NULL;
     193             tmp[i].short_fp = NULL;
     194         }
     195     }
     196
     197     *c = tmp;
     198     return num_classes;
     199 }
     200
     201 /* outputs the object to the appropriate files */
     202 void
     203 output_object (char *object, struct class *c, int num_classes)
         /* [<][>][^][v][top][bottom][index][help] */
     204 {
     205     char *p;
     206     int i;
     207
     208     p = strchr(object, ':');
     209     if (p == NULL) {
     210         fprintf(stderr,
     211             "%s: format error in database; no colon in object, \"%s\"\n",
     212             Program_Name, object);
     213         exit(1);
     214     }
     215     *p = '\0';
     216
     217     for (i=0; i<num_classes; i++) {
     218         if (strcmp(c[i].name, object) == 0) {
     219             *p = ':';
     220             dump_fputs(object, c[i].fp);
     221             dump_putc('\n', c[i].fp);
     222             if (Dump_Short) {
     223                 p = QI_fast_output(object);
     224                 dump_fputs(p, c[i].short_fp);
     225                 free(p);
     226                 dump_putc('\n', c[i].short_fp);
     227             }
     228             return;
     229         }
     230     }
     231
     232     fprintf(stderr, "%s: unknown class of object found, \"%s\"\n",
     233         Program_Name, object);
     234     exit(1);
     235 }
     236
     237 void
     238 seperate_time_t (int n, int *hours, int *minutes, int *seconds)
         /* [<][>][^][v][top][bottom][index][help] */
     239 {
     240     *hours = n / (60 * 60);
     241     n %= (60 * 60);
     242     *minutes = n / 60;
     243     n %= 60;
     244     *seconds = n;
     245 }
     246
     247 /* program entry point */
     248 int
     249 main (int argc, char **argv)
         /* [<][>][^][v][top][bottom][index][help] */
     250 {
     251     struct database_info db;
     252     er_ret_t ret;
     253     SQ_connection_t *sql;
     254     int num_classes;
     255     struct class *classes;
     256     SQ_result_set_t *rs;
     257     SQ_row_t *row;
     258     int num_object;
     259     time_t start, end;
     260     const struct tm *now;
     261     char tmp[64];
     262     double runtime;
     263     int h, m, s;
     264
     265     /* turn off output buffering (why isn't this the default?) */
     266     setbuf(stdout, NULL);
     267
     268     /* record our program's name for any future use */
     269     get_program_name(argc, argv);
     270
     271     /* parse our command line */
     272     parse_options(argc, argv, &db, &Dump_Short);
     273     if (Verbose) {
     274         printf("\n");
     275         printf("Command line options\n");
     276         printf("   database: %s\n", db.database);
     277         printf("   hostname: %s\n", db.hostname);
     278         if (db.port) {
     279             printf("       port: %d\n", db.port);
     280         } else {
     281             printf("       port: <default>\n");
     282         }
     283         printf("       user: %s\n", (*db.user == '\0') ? "<default>" : db.user);
     284         printf("   password: <hidden>\n");
     285         printf(" dump short: %s\n", Dump_Short ? "yes" : "no");
     286     }
     287
     288     /* connect to the server */
     289
     290     if (Verbose) {
     291         printf("\n");
     292         printf("Connecting to server...\n");
     293     }
     294
     295     ret = SQ_try_connection(&sql,
     296         db.hostname, db.port, db.database, db.user, db.password);
     297     if (!NOERR(ret)) {
     298         fprintf(stderr, "%s: error connecting to database; %s\n", Program_Name,
     299             SQ_error(sql));
     300         exit(1);
     301     }
     302
     303     if (Verbose) {
     304         printf("Connected.\n");
     305     }
     306
     307
     308     /* submit our query */
     309     if (Verbose) {
     310         printf("\n");
     311         printf("Submitting query...\n");
     312     }
     313
     314     if (SQ_execute_query_nostore(sql,
     315         "SELECT object FROM last "
     316         "WHERE (thread_id=0) AND (object_type<>100) AND (object<>\"\")",
     317         &rs) != 0)
     318     {
     319        fprintf(stderr, "%s: error with query; %s\n", Program_Name,
     320            SQ_error(sql));
     321        exit(1);
     322     }
     323
     324     if (Verbose) {
     325         printf("Submitted.\n");
     326     }
     327
     328
     329     /* initialize our class information (also creates output files) */
     330     num_classes = load_classes(&classes);
     331
     332     /* record start time */
     333     time(&start);
     334
     335     if (Verbose) {
     336         printf("\n");
     337         printf("Loaded %d classes\n", num_classes);
     338         printf("Created %d output files\n",
     339             Dump_Short ? (num_classes * 2) : num_classes);
     340         printf("\n");
     341         now = localtime(&start);
     342         strftime(tmp, sizeof(tmp), "Dump starting... %Y-%m-%d %H:%M:%S %Z",
     343             now);
     344         puts(tmp);
     345     }
     346
     347
     348     /* read our MySQL data */
     349     num_object = 0;
     350     while ((row = SQ_row_next(rs)) != NULL) {
     351         char *object = SQ_get_column_string_nocopy(rs, row, 0);
     352         output_object(object, classes, num_classes);
     353         num_object++;
     354     }
     355
     356     /* close up shop */
     357     time(&end);
     358
     359     /* output final results, if any */
     360     if (Verbose) {
     361         now = localtime(&end);
     362         strftime(tmp, sizeof(tmp), "Dump finished... %Y-%m-%d %H:%M:%S %Z",
     363             now);
     364         puts(tmp);
     365         runtime = difftime(end, start);
     366         seperate_time_t((int)(runtime + 0.5), &h, &m, &s);
     367         printf("Wrote %d objects in %d:%02d:%02d\n", num_object, h, m, s);
     368         printf(" %12.2f objects/second\n", num_object/runtime);
     369         printf(" %12.2f byte/second\n", Amt_Dumped/runtime);
     370         printf("\n");
     371     }
     372
     373     /* assume that 0 outputs is an error */
     374     if (num_object == 0) {
     375         fprintf(stderr, "No objects dumped, exiting with error\n");
     376         exit(1);
     377     }
     378
     379     return 0;
     380 }
     381

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