00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00058 int source;
00059
00060 int sink;
00061 };
00062
00063 const char* program;
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
00181 if (strstr(program, "cdef"))
00182 cfg->sink = SINK_CDEF;
00183
00184 for(i = 1; i < argc; ++i) {
00185 int state = PARSE_UNKNOWN;
00186
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
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
00278 struct config_t cfg;
00279
00280 int ret;
00281
00282
00283 program = argv[0];
00284 ret = parse_conf(argc, argv, &cfg);
00285 if(!ret)
00286 {
00287
00288 uuid_output_fn_t uuid_output_fn = NULL;
00289
00290 uuid_t uuid;
00291 memset(uuid, 0, sizeof(uuid));
00292
00293
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
00320 if(uuid_output_fn)
00321 printf("%s\n", uuid_output_fn(uuid));
00322 }
00323
00324 return ret;
00325 }