tools/klone/main.c

00001 /*
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: main.c,v 1.44 2008/10/18 17:23:32 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <sys/stat.h>
00013 #ifdef HAVE_SYS_DIR
00014 #include <sys/dir.h>
00015 #endif
00016 #include <sys/types.h>
00017 #include <dirent.h>
00018 #include <stdlib.h>
00019 #include <ctype.h>
00020 #include <stdio.h>
00021 #include <fcntl.h>
00022 #ifdef HAVE_UNISTD
00023 #include <unistd.h>
00024 #endif
00025 #ifdef HAVE_GETOPT
00026 #include <getopt.h>
00027 #endif
00028 #include <u/libu.h>
00029 #include <klone/os.h>
00030 #include <klone/request.h>
00031 #include <klone/response.h>
00032 #include <klone/translat.h>
00033 #include <klone/utils.h>
00034 #include <klone/run.h>
00035 #include <klone/mime_map.h>
00036 #include <klone/version.h>
00037 #include "pm.h"
00038 
00039 int facility = LOG_LOCAL0;
00040 
00041 /* command list enums */
00042 enum command_e { CMD_UNKNOWN, CMD_TRANS, CMD_IMPORT };
00043 
00044 /* runtime flags */
00045 enum flags_e { FLAG_NONE, FLAG_VERBOSE };
00046 
00047 typedef struct 
00048 {
00049     char *file_in, *file_out;   /* [trans] input, output file       */
00050     char *depend_out;           /* [trans] depend output file       */
00051     char *uri;                  /* [trans] translated file uri      */
00052     int verbose;                /* >0 when verbose mode is on       */
00053     char **arg;                 /* argv                             */
00054     size_t narg;                /* argc                             */
00055     int cmd;                    /* command to run                   */
00056     char *base_uri;             /* site base uri                    */
00057     int encrypt;                /* >0 when encryption is enabled    */
00058     int compress;               /* >0 when compress is enabled      */
00059     pm_t *comp_patt;            /* compress file pattern            */
00060     pm_t *enc_patt;             /* encrypt file pattern             */
00061     pm_t *excl_patt;            /* exclude file pattern             */
00062     char *key_file;             /* encryption key file name         */
00063     io_t *iom, *iod, *ior;      /* io makefile, io deps             */
00064     size_t ndir, nfile;         /* dir and file count               */
00065     size_t nexcl;               /* # of excluded files (-x)         */
00066 } context_t;
00067 
00068 context_t *ctx;
00069 
00070 #define KL1_FILE_FMT "pg_%s.%s"
00071 
00072 #define usage_if(expr)  if(expr) usage(); 
00073 
00074 static void usage(void)
00075 {
00076     static const char * us = 
00077 "Usage: klone [-hvV] -c COMMAND OPTIONS ARGUMENTS\n"
00078 "Version: %s - Copyright (c) 2005-2012 KoanLogic s.r.l.\n"
00079 "All rights reserved.\n"
00080 "\n"
00081 "       -h            display this help\n"
00082 "       -v            verbose mode\n"
00083 "       -V            print KLone version and exit\n"
00084 "       -c command    command to execute (see COMMAND LIST)\n"
00085 "\n"
00086 "\n"
00087 "    COMMAND LIST:\n"
00088 "       import        import a directory tree in the embedded filesystem\n"
00089 "       translate     convert a file or a dynamic web page to a C file\n"
00090 "\n"
00091 "\n"
00092 "    COMMANDS SYNTAX:\n"
00093 "\n"
00094 "       import OPTIONS dir\n"
00095 "         -b URI      base URI\n"
00096 "         -x pattern  exclude all files whose URI match the given pattern (*)\n"
00097 #ifdef SSL_ON
00098 "         -e pattern  encrypt all files whose URI match the given pattern (*)\n"
00099 "         -k key_file encryption key filename\n"
00100 "                     (KLONE_CIPHER_KEY environ var is used if not provided)\n"
00101 #endif
00102 #ifdef HAVE_LIBZ
00103 "         -z          compress all compressable content (based on MIME types)\n"
00104 "         -Z pattern  compress all files whose URI match the given pattern (*)\n"
00105 #endif
00106 "         dir         directory tree path\n"
00107 "\n"
00108 "         (*) may be used more then once\n"
00109 "\n"
00110 "       translate OPTIONS\n"
00111 #ifdef SSL_ON
00112 "         -E          encrypt file content\n"
00113 #endif
00114 "         -i file     input file\n"
00115 #ifdef SSL_ON
00116 "         -k key_file encryption key filename\n"
00117 #endif
00118 "         -o file     output file\n"
00119 "         -u URI      URI of translated page\n"
00120 #ifdef HAVE_LIBZ
00121 "         -z          compress file content\n"
00122 #endif
00123 "\n";
00124 
00125     fprintf(stderr, us, klone_version());
00126 
00127     exit(EXIT_FAILURE);
00128 }
00129 
00130 static void remove_trailing_slash(char *s)
00131 {
00132     size_t len;
00133     
00134     dbg_ifb (s == NULL) return;
00135     
00136     len = strlen(s);
00137     if(len && s[len - 1] == '/')
00138         s[len - 1] = 0;
00139 }
00140 
00141 static int parse_opt(int argc, char **argv)
00142 {
00143     int ret;
00144     char opts[512];
00145 
00146     if(argc == 1)
00147         usage();
00148 
00149     /* common switches */
00150     strcpy(opts, "hvVx:b:i:o:u:c:d:");
00151 
00152     /* encryption switches */
00153 #ifdef SSL_ON
00154     strcat(opts, "k:e:E");
00155 #endif
00156 
00157     /* compression switches */
00158 #ifdef HAVE_LIBZ
00159     strcat(opts, "zZ:");
00160 #endif
00161 
00162     while((ret = getopt(argc, argv, opts)) != -1)
00163     {
00164         switch(ret)
00165         {
00166         case 'v': /* verbose on */
00167             ctx->verbose++;
00168             break;
00169         case 'V': /* print name/version info and exit */
00170             u_print_version_and_exit();
00171             break;
00172 
00173 #ifdef SSL_ON
00174         case 'E': /* encryption on */
00175             ctx->encrypt = 1;
00176             break;
00177         case 'e': /* encrypt file pattern */
00178             dbg_err_if(pm_add(ctx->enc_patt, u_strdup(optarg)));
00179             break;
00180         case 'k': /* encryption key filename */
00181             ctx->key_file = u_strdup(optarg);
00182             warn_err_if(ctx->key_file == NULL);
00183             break;
00184 #endif
00185 
00186 #ifdef HAVE_LIBZ
00187         case 'Z': /* compress file pattern */
00188             ctx->compress = 1;
00189             dbg_err_if(pm_add(ctx->comp_patt, u_strdup(optarg)));
00190             break;
00191         case 'z': /* compress */
00192             ctx->compress = 1;
00193             break;
00194 #endif
00195         case 'c': /* command */
00196             if(!strcasecmp(optarg, "import"))
00197                 ctx->cmd = CMD_IMPORT;
00198             else if(!strcasecmp(optarg, "translate"))
00199                 ctx->cmd = CMD_TRANS;
00200             else
00201                 con_err("unknown command: %s", optarg);
00202             break;
00203         case 'i': /* input file */
00204             ctx->file_in = u_strdup(optarg);
00205             warn_err_if(ctx->file_in == NULL);
00206             break;
00207         case 'x': /* exclude pattern */
00208             dbg_err_if(pm_add(ctx->excl_patt, u_strdup(optarg)));
00209             break;
00210         case 'b': /* base_uri */
00211             ctx->base_uri = u_strdup(optarg);
00212             warn_err_if(ctx->base_uri == NULL);
00213 
00214             if(ctx->base_uri[0] != '/')
00215                 klone_die("base URI must be absolute "
00216                           "(i.e. must start with a '/')");
00217 
00218             remove_trailing_slash(ctx->base_uri);
00219 
00220             break;
00221         case 'o': /* output file */
00222             ctx->file_out = u_strdup(optarg);
00223             warn_err_if(ctx->file_out == NULL);
00224             break;
00225         case 'd': /* kld depend output file */
00226             ctx->depend_out = u_strdup(optarg);
00227             warn_err_if(ctx->depend_out == NULL);
00228             break;
00229         case 'u': /* translated page uri */
00230             /* skip the first char to avoid MSYS path translation bug
00231              * (see klone-site.c) */
00232             ctx->uri = u_strdup(1+optarg);
00233             warn_err_if(ctx->uri == NULL);
00234 
00235             if(ctx->uri[0] != '/')
00236                 klone_die("URI must be absolute (i.e. must start with a '/')");
00237 
00238             remove_trailing_slash(ctx->uri);
00239 
00240             break;
00241         default:
00242         case 'h': 
00243             usage();
00244         }
00245     }
00246 
00247     klone_die_if(ctx->cmd == 0, "missing command argument (-c)");
00248     ctx->narg = argc - optind;  /* # of args left */
00249     ctx->arg = argv + optind;   
00250 
00251     return 0;
00252 err:
00253     return ~0;
00254 }
00255 
00256 static int set_key_from_file(trans_info_t *pti, const char *key_file)
00257 {
00258     io_t *io = NULL;
00259 
00260     dbg_err_if (pti == NULL);
00261     dbg_err_if (key_file == NULL);
00262     
00263     dbg_err_if(u_file_open(key_file, O_RDONLY, &io));
00264 
00265     dbg_err_if(io_read(io, pti->key, CODEC_CIPHER_KEY_LEN) <= 0);
00266     
00267     io_free(io);
00268 
00269     return 0;
00270 err:
00271     return ~0;
00272 }
00273 
00274 static int command_trans(void)
00275 {
00276     trans_info_t ti;
00277     const mime_map_t *mm;
00278     struct stat st;
00279     char *key_env;
00280     int key_found = 0;
00281 
00282     if(ctx->narg != 0)
00283         usage();    /* no argument allowed */
00284 
00285     memset(&ti, 0, sizeof(trans_info_t));
00286 
00287     klone_die_if(!ctx->file_in, "input file name required (-i file)");
00288     klone_die_if(!ctx->file_out, "output file name required (-o file)");
00289     klone_die_if(!ctx->uri, "translated page URI required (-u uri)");
00290 
00291     if(ctx->verbose)
00292         u_con("translating %s to %s (uri: %s)", ctx->file_in, ctx->file_out, 
00293             ctx->uri);
00294 
00295     /* input file */
00296     u_strlcpy(ti.file_in, ctx->file_in, sizeof ti.file_in);
00297 
00298     /* output file */
00299     u_strlcpy(ti.file_out, ctx->file_out, sizeof ti.file_out);
00300 
00301     /* kld depend file */
00302     if(ctx->depend_out)
00303         u_strlcpy(ti.depend_out, ctx->depend_out, sizeof ti.depend_out);
00304 
00305     /* uri */
00306     u_strlcpy(ti.uri, ctx->uri, sizeof ti.uri);
00307 
00308     /* zero out the key (some byte could not be overwritten with small keys) */
00309     memset(ti.key, 0, CODEC_CIPHER_KEY_BUFSZ);
00310 
00311     /* sanity checks */
00312     con_err_ifm(ctx->key_file && !ctx->encrypt, "-k used but -E is missing");
00313 
00314     /* encryption key */
00315     key_env = getenv("KLONE_CIPHER_KEY");
00316     if(key_env && strlen(key_env))
00317     {
00318         con_err_ifm(strlen(key_env) != CODEC_CIPHER_KEY_LEN,
00319                 "wrong key length; the encryption key must be %d bytes long",
00320                 CODEC_CIPHER_KEY_LEN);
00321 
00322         key_found = 1;
00323                 memcpy(ti.key, key_env, strlen(key_env));
00324     }
00325 
00326     /* if -k has been used the overwrite KLONE_CIPHER_KEY env var (if present)*/
00327     if(ctx->key_file)
00328     {
00329         key_found = 1;
00330         con_err_ifm(set_key_from_file(&ti, ctx->key_file), 
00331             "error reading key file [%s]", ctx->key_file);
00332     }
00333 
00334     if(ctx->encrypt)
00335     {
00336         if(!key_found)
00337             con_err("encryption key required (use -k or KLONE_CIPHER_KEY "
00338                     "environ variable)");
00339         ti.encrypt = 1;
00340     }
00341 
00342     /* set MIME type */
00343     if((mm = u_get_mime_map(ctx->file_in)) != NULL)
00344         u_strlcpy(ti.mime_type, mm->mime_type, sizeof ti.mime_type);
00345     else
00346         u_strlcpy(ti.mime_type, "application/octet-stream", 
00347                 sizeof ti.mime_type);
00348 
00349     /* compress if requested and the file is compressable (by MIME type) */
00350     if(ctx->compress)
00351         ti.comp = 1;
00352 
00353     /* be sure that the input file exists */
00354     klone_die_if(stat(ctx->file_in, &st), "input file not found");
00355 
00356     ti.file_size = st.st_size;
00357     ti.mtime = st.st_mtime; 
00358 
00359     /* translate it */
00360     dbg_err_if(translate(&ti));
00361 
00362     return 0;
00363 err:
00364     /* delete output file on error */
00365     u_remove(ti.file_out);
00366     u_con(" ");
00367     return ~0;
00368 }
00369 
00370 static int is_cpp(const char *file_in)
00371 {
00372     size_t l;
00373 
00374     dbg_err_if (file_in == NULL);
00375 
00376     l = strlen(file_in);
00377     if(l < 4)
00378         return 0;
00379 
00380     /* if the file name ends with "[Cc][Cc]" consider it a c++ file */
00381     if(tolower(file_in[--l]) == 'c' && tolower(file_in[--l]) == 'c')
00382         return 1; /* c++ */
00383 
00384 err:
00385     return 0;
00386 }
00387 
00388 
00389 static int cb_file(struct dirent *de, const char *path , void *arg)
00390 {
00391     static const char *prefix = "$(srcdir)";
00392     const mime_map_t *mm;
00393     char uri_md5[MD5_DIGEST_BUFSZ];
00394     char file_in[U_FILENAME_MAX], uri[URI_BUFSZ], *base_uri = (char*)arg;
00395     char fullpath[U_FILENAME_MAX];
00396     const char *ext;
00397     int is_a_script, enc = 0, zip = 0;
00398 
00399     dbg_err_if (de == NULL);
00400     dbg_err_if (path == NULL);
00401     dbg_err_if (arg == NULL);
00402 
00403     dbg_err_if(u_snprintf(fullpath, U_FILENAME_MAX, "%s/%s", path, de->d_name));
00404 
00405     /* input filename (makefile-style) */
00406     dbg_err_if(translate_makefile_filepath(fullpath, prefix, file_in, 
00407         sizeof(file_in)));
00408 
00409     /* base uri */
00410     dbg_err_if(u_snprintf(uri, URI_BUFSZ, "%s/%s", base_uri, de->d_name));
00411     dbg_err_if(u_md5(uri, strlen(uri), uri_md5));
00412 
00413     /* if the URI match the given exclude pattern then skip it */
00414     if(!pm_is_empty(ctx->excl_patt) && pm_match(ctx->excl_patt, uri))
00415     {
00416         if(ctx->verbose)
00417             u_con("%s skipped", uri);
00418 
00419         ctx->nexcl++;
00420 
00421         return 0; /* skip it */
00422     } 
00423 
00424     is_a_script = translate_is_a_script(de->d_name);
00425 
00426     ctx->nfile++;
00427 
00428     /* if the URI match the given encrypt pattern then encrypt it */
00429     if(!pm_is_empty(ctx->enc_patt) && pm_match(ctx->enc_patt, uri))
00430         enc = 1;
00431 
00432     if(ctx->compress) /* -z or -Z have been used */
00433     {
00434         /* if the URI match the given compress pattern then compress it */
00435         if(!pm_is_empty(ctx->comp_patt))
00436         {   /* compression enabled basing on file URI pattern */
00437             if(pm_match(ctx->comp_patt, uri))
00438                 zip = 1;
00439         } else {
00440             /* compression enabled basing on URI MIME types */
00441             if((mm = u_get_mime_map(uri)) != NULL)
00442                 zip = mm->comp;
00443         }
00444     }
00445 
00446     /* print out some info */
00447     if(ctx->verbose == 1)
00448         u_con("%s (encrypted: %s, compressed: %s)", 
00449             uri, enc ? "yes" : "no", zip ? "yes" : "no");
00450     else if(ctx->verbose > 1)
00451         u_con("%s -> %s (encrypted: %s, compressed: %s)", 
00452             file_in + strlen(prefix), uri, 
00453             enc ? "yes" : "no", zip ? "yes" : "no");
00454 
00455     ext = u_match_ext(file_in, "klx") ? "cc" : "c";
00456 
00457     dbg_err_if(io_printf(ctx->iom, " \\\n" KL1_FILE_FMT, uri_md5, ext) < 0);
00458 
00459     dbg_err_if(io_printf(ctx->ior, "KLONE_REGISTER(action,%s);\n", uri_md5) <0);
00460 
00461     /* we're adding a '/' before the uri (that will be removed by klone.exe) 
00462      * to avoid MSYS (win32) automatic path translation oddity */
00463     dbg_err_if(io_printf(ctx->iod, 
00464             "\n" KL1_FILE_FMT 
00465             ": %s\n\t$(KLONE) -c translate -i $< -o $@ %s -u /%s %s %s %s %s\n"
00466             "%s", /* compiler depend-file generation command */
00467             uri_md5, ext, file_in, 
00468             is_a_script ? "-d $@.kld" : "",
00469             uri, 
00470             zip ? "-z" : "",
00471             enc ? "-E" : "", 
00472             enc && ctx->key_file ? "-k" : "", 
00473             enc && ctx->key_file ? ctx->key_file  : "",
00474             is_a_script ? "\t$(MKDEP) -f $@.d $(CFLAGS) -a $@\n" : ""
00475             ) < 0);
00476 
00477     /* include depend files */
00478     if(is_a_script)
00479     {
00480         dbg_err_if(io_printf(ctx->iod, "\n-include " KL1_FILE_FMT ".kld\n", 
00481             uri_md5, ext) < 0);
00482         dbg_err_if(io_printf(ctx->iod, "\n-include " KL1_FILE_FMT ".d\n", 
00483             uri_md5, ext) < 0);
00484     }
00485 
00486     return 0;
00487 err:
00488     return ~0;
00489 }
00490 
00491 static int cb_dir(struct dirent *de, const char *path , void *arg)
00492 {
00493     char dir[U_FILENAME_MAX], base_uri[URI_BUFSZ], *cur_uri = (char*)arg;
00494 
00495     dbg_err_if (de == NULL);
00496     dbg_err_if (path == NULL);
00497     dbg_err_if (arg == NULL);
00498     
00499     ctx->ndir++;
00500 
00501     dbg_err_if(u_snprintf(dir, U_FILENAME_MAX, "%s/%s", path, de->d_name));
00502 
00503     dbg_err_if(u_snprintf(base_uri, URI_BUFSZ, "%s/%s", cur_uri, de->d_name));
00504 
00505     u_foreach_dir_item(dir, S_IFREG, cb_file, (void*)base_uri);
00506 
00507     u_foreach_dir_item(dir, S_IFDIR, cb_dir, (void*)base_uri);
00508 
00509     return 0;
00510 err:
00511     return ~0;
00512 }
00513 
00514 static int print_register_header(io_t *out)
00515 {
00516     dbg_err_if (out == NULL);
00517  
00518     dbg_err_if(io_printf(out, "#include <klone_conf.h>\n") < 0);
00519     dbg_err_if(io_printf(out, "#include <klone/hook.h>\n") < 0);
00520     dbg_err_if(io_printf(out, "static void do_register(int);\n") < 0);
00521     dbg_err_if(io_printf(out, "void unregister_pages(void);\n") < 0);
00522     dbg_err_if(io_printf(out, "void register_pages(void);\n") < 0);
00523 
00524     dbg_err_if(io_printf(out, 
00525         "void unregister_pages(void) { \n"
00526         "do_register(0); }\n"
00527         ) < 0);
00528     dbg_err_if(io_printf(out, 
00529         "void register_pages(void) { \n"
00530         "do_register(1);\n"
00531         "#ifdef ENABLE_HOOKS\n"
00532         "    hooks_setup(); \n"
00533         "#endif \n"
00534         "}\n") < 0);
00535     dbg_err_if(io_printf(out, 
00536         "static void do_register(int action) {\n") < 0);
00537     dbg_err_if(io_printf(out,
00538         "#define KLONE_REGISTER(a, md5)     \\\n"
00539         "    do {                           \\\n"
00540         "    void module_init_##md5(void);  \\\n"
00541         "    void module_term_##md5(void);  \\\n"
00542         "    if(a) module_init_##md5();     \\\n"
00543         "    else module_term_##md5();      \\\n"
00544         "    } while(0)                     \n") < 0);
00545 
00546     return 0;
00547 err:
00548     return ~0;
00549 }
00550 
00551 static int print_register_footer(io_t *out)
00552 {
00553     dbg_err_if (out == NULL);
00554 
00555     dbg_err_if(io_printf(out, "#undef KLONE_REGISTER\n") < 0);
00556     dbg_err_if(io_printf(out, "}\n") < 0);
00557 
00558     return 0;
00559 err:
00560     return ~0;
00561 }
00562 
00563 static int trans_site(char *root_dir, char *base_uri)
00564 {
00565     dbg_err_if (root_dir == NULL);
00566     dbg_err_if (base_uri == NULL);
00567     
00568     /* makefile */
00569     dbg_err_if(u_file_open("autogen.mk", O_CREAT | O_TRUNC | O_WRONLY, 
00570                 &ctx->iom));
00571     dbg_err_if(u_file_open("autogen.dps", O_CREAT | O_TRUNC | O_WRONLY, 
00572                 &ctx->iod));
00573 
00574     dbg_err_if(u_file_open("register.c", O_CREAT | O_TRUNC | O_WRONLY, 
00575                 &ctx->ior));
00576 
00577     dbg_err_if(print_register_header(ctx->ior));
00578 
00579     dbg_err_if(io_printf(ctx->iom, "embfs_rootdir=%s\n", root_dir) < 0);
00580     dbg_err_if(io_printf(ctx->iom, "autogen_src= ") < 0);
00581 
00582     /* for each file call cb_file */
00583     u_foreach_dir_item(root_dir, S_IFREG, cb_file, base_uri);
00584     /* for each directory call cb_dir */
00585     u_foreach_dir_item(root_dir, S_IFDIR, cb_dir, base_uri);
00586 
00587     dbg_err_if(print_register_footer(ctx->ior));
00588 
00589     io_free(ctx->ior);
00590     io_free(ctx->iod);
00591     io_free(ctx->iom);
00592 
00593     return 0;
00594 err:
00595     if(ctx->ior)
00596         io_free(ctx->ior);
00597     if(ctx->iod)
00598         io_free(ctx->iod);
00599     if(ctx->iom)
00600         io_free(ctx->iom);
00601     return ~0;
00602 }
00603 
00604 static int command_import(void)
00605 {
00606     char *root_dir, *base_uri;
00607 
00608     if(ctx->narg != 1)
00609         usage();    /* just on directory expected */
00610 
00611     root_dir = ctx->arg[0];
00612     dbg_err_if(root_dir == NULL);
00613 
00614     if((base_uri = ctx->base_uri) == NULL)
00615     {
00616         base_uri = u_strdup("");
00617         dbg_err_if (base_uri == NULL);
00618     }
00619 
00620     dbg_err_if(trans_site(root_dir, base_uri));
00621 
00622     u_con("%lu dirs and %lu files imported, %lu files skipped", 
00623             (unsigned long) ctx->ndir, (unsigned long) ctx->nfile, 
00624             (unsigned long) ctx->nexcl);
00625 
00626     return 0;
00627 err:
00628     u_con("import error");
00629     return ~0;
00630 }
00631 
00632 static int dispatch_command(void)
00633 {
00634     switch(ctx->cmd)
00635     {
00636     case CMD_TRANS:
00637         dbg_err_if(command_trans());
00638         break;
00639     case CMD_IMPORT:
00640         dbg_err_if(command_import());
00641         break;
00642     default:
00643         con_err("unknown command");
00644     }
00645 
00646     return 0;
00647 err:
00648     return ~0;
00649 }
00650 
00651 int main(int argc, char **argv)
00652 {
00653     context_t context;
00654 
00655     ctx = &context;
00656 
00657     /* zero-out the context */
00658     memset(ctx, 0, sizeof(context_t));
00659 
00660     /* init pattern matching objects */
00661     dbg_err_if(pm_create(&ctx->comp_patt));
00662     dbg_err_if(pm_create(&ctx->enc_patt));
00663     dbg_err_if(pm_create(&ctx->excl_patt));
00664 
00665     /* parse command line switches and set ctx->cmd and params */
00666     dbg_err_if(parse_opt(argc, argv));
00667 
00668     /* run the command */
00669     dbg_err_if(dispatch_command());
00670 
00671     return EXIT_SUCCESS;
00672 err:
00673     return EXIT_FAILURE;
00674 }

←Products
Copyright © 2005-2012 - KoanLogic S.r.l. - All rights reserved