uuidgen.c

00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * uuidgen - UUID generator and preprocessor for XPLC
00004  * Copyright (C) 2005, Net Integration Technologies, Inc.
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public License
00008  * as published by the Free Software Foundation; either version 2.1 of
00009  * the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  *
00020  * As a special exception, you may use this file as part of a free
00021  * software library without restriction.  Specifically, if other files
00022  * instantiate templates or use macros or inline functions from this
00023  * file, or you compile this file and link it with other files to
00024  * produce an executable, this file does not by itself cause the
00025  * resulting executable to be covered by the GNU Lesser General Public
00026  * License.  This exception does not however invalidate any other
00027  * reasons why the executable file might be covered by the GNU Lesser
00028  * General Public License.
00029  */
00030 
00031 #include <assert.h>
00032 #include <errno.h>
00033 #ifdef HAVE_STDLIB_H
00034 # include <stdlib.h>
00035 #endif
00036 #include <stdio.h>
00037 #ifdef HAVE_STRING_H
00038 # include <string.h>
00039 #endif
00040 #ifdef HAVE_UNISTD_H
00041 # include <unistd.h>
00042 #endif
00043 #include <uuid/uuid.h>
00044 
00045 #include "include/autoconf.h"
00046 
00047 #define SOURCE_NONE -1
00048 #define SOURCE_AUTO 0
00049 #define SOURCE_RANDOM 1
00050 #define SOURCE_TIME 2
00051 
00052 #define SINK_NONE -1
00053 #define SINK_UUID 0
00054 #define SINK_CDEF 1
00055 
00056 struct config_t {
00057   /* What kind of randomness source do we use? */
00058   int source;
00059   /* What kind of output are we generating? */
00060   int sink;
00061 };
00062 
00063 const char* program;            /* Program name */
00064 
00065 #define PARSE_INVALID -1
00066 #define PARSE_UNKNOWN 0
00067 #define PARSE_FLAGS 1
00068 #define PARSE_SHORT_OPTIONS 2
00069 #define PARSE_LONG_OPTION 3
00070 
00071 
00072 void print_help(const char* program) {
00073   printf("Usage: %s [OPTION]\n", program);
00074   printf("Generate a new universally unique identifier (UUID)\n");
00075   printf("\n"
00076          "  -c, --cdef\toutput C structure for XPLC\n"
00077          "  -r, --random\tgenerate random-based UUID\n"
00078          "  -t, --time\tgenerate time-based UUID\n"
00079          "  -u, --uuid\thuman-readable output\n"
00080          "      --help\tdisplay this help and exit\n"
00081          "      --version\toutput version information and exit\n"
00082          "\n");
00083   printf("When called without options, this programme will generate a "
00084          "universally\n"
00085          "unique identifier (UUID), and output it as requested.\n");
00086   printf("\n"
00087          "Report bugs to <" PACKAGE_BUGREPORT ">.\n");
00088 }
00089 
00090 
00091 void print_version(const char* program) {
00092   printf("XPLC uuidgen version " PACKAGE_VERSION "\n"
00093          "Written by Simon Law.\n"
00094          "\n"
00095          "Copyright (C) 2005, Net Integration Technologies, Inc.\n"
00096          "This is free software; see the source for copying conditions.  "
00097          "There is NO\n"
00098          "warranty; not even for MERCHANTABILITY or FITNESS FOR A "
00099          "PARTICULAR PURPOSE.\n");
00100 }
00101 
00102 
00103 int parse_short_option(const int flag, struct config_t* cfg) {
00104   if(!cfg) {
00105     fprintf(stderr,
00106             "%s: Programmer error at %s:%d\n", program, __FILE__, __LINE__);
00107     abort();
00108   }
00109 
00110   switch(flag) {
00111   case 'c':
00112     cfg->sink = SINK_CDEF;
00113     break;
00114   case 'r':
00115     cfg->source = SOURCE_RANDOM;
00116     break;
00117   case 't':
00118     cfg->source = SOURCE_TIME;
00119     break;
00120   case 'u':
00121     cfg->sink = SINK_UUID;
00122     break;
00123   case -1:
00124     cfg->source = SOURCE_NONE;
00125     cfg->sink = SINK_NONE;
00126     print_help(program);
00127     return -1;
00128   case -2:
00129     cfg->source = SOURCE_NONE;
00130     cfg->sink = SINK_NONE;
00131     print_version(program);
00132     return -1;
00133   default:
00134     fprintf(stderr,
00135             "%s: invalid option -- %c\n"
00136             "Try `%s --help' for more information.\n",
00137             program, flag, program);
00138     return 1;
00139   }
00140   return 0;
00141 }
00142 
00143 
00144 int parse_long_option(const char* option, struct config_t* cfg) {
00145   int ret;
00146   if(!strcmp(option + 2, "help"))
00147     ret = parse_short_option(-1, cfg);
00148   else if(!strcmp(option + 2, "version"))
00149     ret = parse_short_option(-2, cfg);
00150   else if(!strcmp(option + 2, "cdef"))
00151     ret = parse_short_option('c', cfg);
00152   else if(!strcmp(option + 2, "random"))
00153     ret = parse_short_option('r', cfg);
00154   else if(!strcmp(option + 2, "time"))
00155     ret = parse_short_option('t', cfg);
00156   else if(!strcmp(option + 2, "uuid"))
00157     ret = parse_short_option('u', cfg);
00158   else {
00159     fprintf(stderr,
00160             "%s: unrecognised option `%s'\n"
00161             "Try `%s --help' for more information.\n",
00162             program, option, program);
00163     ret = 1;
00164   }
00165   return ret;
00166 }
00167 
00168 
00169 int parse_conf(int argc, char** argv, struct config_t* cfg) {
00170   int i;
00171 
00172   if(!cfg) {
00173     fprintf(stderr,
00174             "%s: Programmer error at %s:%d\n", program, __FILE__, __LINE__);
00175     abort();
00176   }
00177 
00178   memset(cfg, 0, sizeof(*cfg));
00179 
00180   /* By default, uuidcdef outputs a SINK_CDEF */
00181   if (strstr(program, "cdef"))
00182     cfg->sink = SINK_CDEF;
00183 
00184   for(i = 1; i < argc; ++i) {
00185     int state = PARSE_UNKNOWN;
00186     /* Iterate through the option and decide what to do with it */
00187     char* c;
00188     for(c = argv[i]; c; c && ++c) {
00189       switch(state) {
00190       case PARSE_INVALID:
00191         fprintf(stderr,
00192                 "%s: unrecognised option `%s'\n"
00193                 "Try `%s --help' for more information.\n",
00194                 program, argv[i], program);
00195         return 1;
00196       case PARSE_FLAGS:
00197         switch(*c) {
00198         case '-':
00199           state = PARSE_LONG_OPTION;
00200           break;
00201         default:
00202           state = PARSE_SHORT_OPTIONS;
00203           --c;
00204         }
00205         break;
00206       case PARSE_SHORT_OPTIONS:
00207         if(*c) {
00208           int ret = parse_short_option(*c, cfg);
00209           if(ret > 0)
00210             return ret;
00211           else if(ret < 0)
00212             return 0;
00213         } else
00214           c = NULL;
00215         break;
00216       case PARSE_LONG_OPTION: {
00217         int ret = parse_long_option(argv[i], cfg);
00218         if(ret > 0)
00219           return ret;
00220         else if(ret < 0)
00221           return 0;
00222         c = NULL;
00223         break;
00224       }
00225       default:
00226         switch(*c) {
00227         case '-':
00228           state = PARSE_FLAGS;
00229           break;
00230         default:
00231           state = PARSE_INVALID;
00232         }
00233       }
00234     }
00235   }
00236 
00237   return 0;
00238 }
00239 
00240 
00241 typedef const char* (*uuid_output_fn_t)(const uuid_t);
00242 static char uuid_unparse_buf[60];
00243 const char* uuid_unparse_x_(const uuid_t uuid) {
00244   /* This function implicitly trusts uuid_unparse. */
00245   unsigned int a, b, c, d, e, f, g, h, i, j, k;
00246   int ret;
00247   uuid_unparse(uuid, uuid_unparse_buf);
00248   ret = sscanf(uuid_unparse_buf,
00249                "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00250                &a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k);
00251   if(ret != 11) {
00252     uuid_unparse_buf[59] = '\0';
00253     fprintf(stderr,
00254             "%s: libuuid error at %s:%d\n", program, __FILE__, __LINE__);
00255     fprintf(stderr,
00256             "uuid_unparse() returned `%s'.\n", uuid_unparse_buf);
00257     abort();
00258   }
00259   sprintf(uuid_unparse_buf,
00260           "{0x%08x, "
00261           "0x%04x, "
00262           "0x%04x, "
00263           "{0x%02x, 0x%02x, "
00264           "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}}",
00265           a, b, c, d, e, f, g, h, i, j, k);
00266   return uuid_unparse_buf;
00267 }
00268 const char* uuid_unparse_(const uuid_t uuid) {
00269   uuid_unparse(uuid, uuid_unparse_buf);
00270   return uuid_unparse_buf;
00271 }
00272 
00273 
00274 #define BUFFER_SIZE 100
00275 #define LENGTH 36
00276 int main(int argc, char** argv) {
00277   /* Configuration */
00278   struct config_t cfg;
00279   /* Return value */
00280   int ret;
00281 
00282   /* Parse the command line arguments */
00283   program = argv[0];
00284   ret = parse_conf(argc, argv, &cfg);
00285   if(!ret)
00286   {
00287     /* Function that will generate the correct output */
00288     uuid_output_fn_t uuid_output_fn = NULL;
00289     /* Static buffer to hold the UUID. */
00290     uuid_t uuid;
00291     memset(uuid, 0, sizeof(uuid));
00292 
00293     /* Generate the UUID, using the method requested. */
00294     switch(cfg.source) {
00295     case SOURCE_RANDOM:
00296       uuid_generate_random(uuid);
00297       break;
00298     case SOURCE_TIME:
00299       uuid_generate_time(uuid);
00300       break;
00301     case SOURCE_AUTO:
00302       uuid_generate(uuid);
00303       break;
00304     default:
00305       ;
00306     }
00307 
00308     switch(cfg.sink) {
00309     case SINK_CDEF:
00310       uuid_output_fn = &uuid_unparse_x_;
00311       break;
00312     case SINK_UUID:
00313       uuid_output_fn = &uuid_unparse_;
00314       break;
00315     default:
00316       uuid_output_fn = NULL;
00317     }
00318 
00319     /* Do the right kind of output, using the method requested. */
00320     if(uuid_output_fn)
00321       printf("%s\n", uuid_output_fn(uuid));
00322   }
00323 
00324   return ret;
00325 }

Generated on Thu May 25 21:51:02 2006 for WvStreams by  doxygen 1.4.6