extract.c (27868B)
1 /* 2 This file is part of libextractor. 3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff 4 5 libextractor is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 libextractor is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libextractor; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 /** 21 * @file main/extract.c 22 * @brief command-line tool to run GNU libextractor 23 * @author Christian Grothoff 24 */ 25 #include "platform.h" 26 #include "extractor.h" 27 #include "getopt.h" 28 #include <signal.h> 29 30 #define YES 1 31 #define NO 0 32 33 34 /** 35 * Which keyword types should we print? 36 */ 37 static int *print; 38 39 /** 40 * How verbose are we supposed to be? 41 */ 42 static int verbose; 43 44 /** 45 * Run plugins in-process. 46 */ 47 static int in_process; 48 49 /** 50 * Read file contents into memory, then feed them to extractor. 51 */ 52 static int from_memory; 53 54 #ifndef WINDOWS 55 /** 56 * Install a signal handler to ignore SIGPIPE. 57 */ 58 static void 59 ignore_sigpipe () 60 { 61 struct sigaction oldsig; 62 struct sigaction sig; 63 64 memset (&sig, 0, sizeof (struct sigaction)); 65 sig.sa_handler = SIG_IGN; 66 sigemptyset (&sig.sa_mask); 67 #ifdef SA_INTERRUPT 68 sig.sa_flags = SA_INTERRUPT; /* SunOS */ 69 #else 70 sig.sa_flags = SA_RESTART; 71 #endif 72 if (0 != sigaction (SIGPIPE, &sig, &oldsig)) 73 fprintf (stderr, 74 "Failed to install SIGPIPE handler: %s\n", strerror (errno)); 75 } 76 77 78 #endif 79 80 81 /** 82 * Information about command-line options. 83 */ 84 struct Help 85 { 86 /** 87 * Single-character option name, '\0' for none. 88 */ 89 char shortArg; 90 91 /** 92 * Long name of the option. 93 */ 94 const char *longArg; 95 96 /** 97 * Name of the mandatory argument, NULL for no argument. 98 */ 99 const char *mandatoryArg; 100 101 /** 102 * Help text for the option. 103 */ 104 const char *description; 105 }; 106 107 108 /** 109 * Indentation for descriptions. 110 */ 111 #define BORDER 29 112 113 114 /** 115 * Display help text (--help). 116 * 117 * @param general binary name 118 * @param description program description 119 * @param opt program options (NULL-terminated array) 120 */ 121 static void 122 format_help (const char *general, 123 const char *description, 124 const struct Help *opt) 125 { 126 size_t slen; 127 unsigned int i; 128 ssize_t j; 129 size_t ml; 130 size_t p; 131 char scp[80]; 132 const char *trans; 133 134 printf (_ ("Usage: %s\n%s\n\n"), 135 gettext (general), 136 gettext (description)); 137 printf (_ ( 138 "Arguments mandatory for long options are also mandatory for short options.\n")); 139 slen = 0; 140 i = 0; 141 while (NULL != opt[i].description) 142 { 143 if (0 == opt[i].shortArg) 144 printf (" "); 145 else 146 printf (" -%c, ", 147 opt[i].shortArg); 148 printf ("--%s", 149 opt[i].longArg); 150 slen = 8 + strlen (opt[i].longArg); 151 if (NULL != opt[i].mandatoryArg) 152 { 153 printf ("=%s", 154 opt[i].mandatoryArg); 155 slen += 1 + strlen (opt[i].mandatoryArg); 156 } 157 if (slen > BORDER) 158 { 159 printf ("\n%*s", BORDER, ""); 160 slen = BORDER; 161 } 162 if (slen < BORDER) 163 { 164 printf ("%*s", (int) (BORDER - slen), ""); 165 slen = BORDER; 166 } 167 trans = gettext (opt[i].description); 168 ml = strlen (trans); 169 p = 0; 170 OUTER: 171 while (ml - p > 78 - slen) 172 { 173 for (j = p + 78 - slen; j>p; j--) 174 { 175 if (isspace ( (unsigned char) trans[j])) 176 { 177 memcpy (scp, 178 &trans[p], 179 j - p); 180 scp[j - p] = '\0'; 181 printf ("%s\n%*s", 182 scp, 183 BORDER + 2, 184 ""); 185 p = j + 1; 186 slen = BORDER + 2; 187 goto OUTER; 188 } 189 } 190 /* could not find space to break line */ 191 memcpy (scp, 192 &trans[p], 193 78 - slen); 194 scp[78 - slen] = '\0'; 195 printf ("%s\n%*s", 196 scp, 197 BORDER + 2, 198 ""); 199 slen = BORDER + 2; 200 p = p + 78 - slen; 201 } 202 /* print rest */ 203 if (p < ml) 204 printf ("%s\n", 205 &trans[p]); 206 i++; 207 } 208 } 209 210 211 /** 212 * Run --help. 213 */ 214 static void 215 print_help () 216 { 217 static struct Help help[] = { 218 { 'b', "bibtex", NULL, 219 gettext_noop ("print output in bibtex format") }, 220 { 'g', "grep-friendly", NULL, 221 gettext_noop ( 222 "produce grep-friendly output (all results on one line per file)") }, 223 { 'h', "help", NULL, 224 gettext_noop ("print this help") }, 225 { 'i', "in-process", NULL, 226 gettext_noop ("run plugins in-process (simplifies debugging)") }, 227 { 'm', "from-memory", NULL, 228 gettext_noop ( 229 "read data from file into memory and extract from memory") }, 230 { 'l', "library", "LIBRARY", 231 gettext_noop ("load an extractor plugin named LIBRARY") }, 232 { 'L', "list", NULL, 233 gettext_noop ("list all keyword types") }, 234 { 'n', "nodefault", NULL, 235 gettext_noop ("do not use the default set of extractor plugins") }, 236 { 'p', "print", "TYPE", 237 gettext_noop ( 238 "print only keywords of the given TYPE (use -L to get a list)") }, 239 { 'v', "version", NULL, 240 gettext_noop ("print the version number") }, 241 { 'V', "verbose", NULL, 242 gettext_noop ("be verbose") }, 243 { 'x', "exclude", "TYPE", 244 gettext_noop ("do not print keywords of the given TYPE") }, 245 { 0, NULL, NULL, NULL }, 246 }; 247 format_help (_ ("extract [OPTIONS] [FILENAME]*"), 248 _ ("Extract metadata from files."), 249 help); 250 251 } 252 253 254 #if HAVE_ICONV 255 #include "iconv.c" 256 #endif 257 258 /** 259 * Print a keyword list to a file. 260 * 261 * @param cls closure, not used 262 * @param plugin_name name of the plugin that produced this value; 263 * special values can be used (i.e. '<zlib>' for zlib being 264 * used in the main libextractor library and yielding 265 * meta data). 266 * @param type libextractor-type describing the meta data 267 * @param format basic format information about data 268 * @param data_mime_type mime-type of data (not of the original file); 269 * can be NULL (if mime-type is not known) 270 * @param data actual meta-data found 271 * @param data_len number of bytes in data 272 * @return 0 to continue extracting, 1 to abort 273 */ 274 static int 275 print_selected_keywords (void *cls, 276 const char *plugin_name, 277 enum EXTRACTOR_MetaType type, 278 enum EXTRACTOR_MetaFormat format, 279 const char *data_mime_type, 280 const char *data, 281 size_t data_len) 282 { 283 char *keyword; 284 #if HAVE_ICONV 285 iconv_t cd; 286 #endif 287 const char *stype; 288 const char *mt; 289 290 if ( (type >= EXTRACTOR_metatype_get_max ()) || 291 (type < 0) ) 292 return 0; /* invalid type */ 293 if (YES != print[type]) 294 return 0; 295 if (verbose > 3) 296 fprintf (stdout, 297 _ ("Found by `%s' plugin:\n"), 298 plugin_name); 299 mt = EXTRACTOR_metatype_to_string (type); 300 stype = (NULL == mt) ? _ ("unknown") : gettext (mt); 301 switch (format) 302 { 303 case EXTRACTOR_METAFORMAT_UNKNOWN: 304 fprintf (stdout, 305 _ ("%s - (unknown, %u bytes)\n"), 306 stype, 307 (unsigned int) data_len); 308 break; 309 case EXTRACTOR_METAFORMAT_UTF8: 310 if (0 == data_len) 311 break; 312 #if HAVE_ICONV 313 cd = iconv_open (nl_langinfo (CODESET), "UTF-8"); 314 if (((iconv_t) -1) != cd) 315 keyword = iconv_helper (cd, 316 data, 317 data_len); 318 else 319 #endif 320 keyword = strdup (data); 321 if (NULL != keyword) 322 { 323 fprintf (stdout, 324 "%s - %s\n", 325 stype, 326 keyword); 327 free (keyword); 328 } 329 #if HAVE_ICONV 330 if (((iconv_t) -1) != cd) 331 iconv_close (cd); 332 #endif 333 break; 334 case EXTRACTOR_METAFORMAT_BINARY: 335 fprintf (stdout, 336 _ ("%s - (binary, %u bytes)\n"), 337 stype, 338 (unsigned int) data_len); 339 break; 340 case EXTRACTOR_METAFORMAT_C_STRING: 341 fprintf (stdout, 342 "%s - %.*s\n", 343 stype, 344 (int) data_len, 345 data); 346 break; 347 default: 348 break; 349 } 350 return 0; 351 } 352 353 354 /** 355 * Print a keyword list to a file without new lines. 356 * 357 * @param cls closure, not used 358 * @param plugin_name name of the plugin that produced this value; 359 * special values can be used (i.e. '<zlib>' for zlib being 360 * used in the main libextractor library and yielding 361 * meta data). 362 * @param type libextractor-type describing the meta data 363 * @param format basic format information about data 364 * @param data_mime_type mime-type of data (not of the original file); 365 * can be NULL (if mime-type is not known) 366 * @param data actual meta-data found 367 * @param data_len number of bytes in data 368 * @return 0 to continue extracting, 1 to abort 369 */ 370 static int 371 print_selected_keywords_grep_friendly (void *cls, 372 const char *plugin_name, 373 enum EXTRACTOR_MetaType type, 374 enum EXTRACTOR_MetaFormat format, 375 const char *data_mime_type, 376 const char *data, 377 size_t data_len) 378 { 379 char *keyword; 380 #if HAVE_ICONV 381 iconv_t cd; 382 #endif 383 const char *mt; 384 385 if (YES != print[type]) 386 return 0; 387 mt = EXTRACTOR_metatype_to_string (type); 388 if (NULL == mt) 389 mt = gettext_noop ("unknown"); 390 switch (format) 391 { 392 case EXTRACTOR_METAFORMAT_UNKNOWN: 393 break; 394 case EXTRACTOR_METAFORMAT_UTF8: 395 if (0 == data_len) 396 return 0; 397 if (verbose > 1) 398 fprintf (stdout, 399 "%s: ", 400 gettext (mt)); 401 #if HAVE_ICONV 402 cd = iconv_open (nl_langinfo (CODESET), "UTF-8"); 403 if (((iconv_t) -1) != cd) 404 keyword = iconv_helper (cd, 405 data, 406 data_len); 407 else 408 #endif 409 keyword = strdup (data); 410 if (NULL != keyword) 411 { 412 fprintf (stdout, 413 "`%s' ", 414 keyword); 415 free (keyword); 416 } 417 #if HAVE_ICONV 418 if (((iconv_t) -1) != cd) 419 iconv_close (cd); 420 #endif 421 break; 422 case EXTRACTOR_METAFORMAT_BINARY: 423 break; 424 case EXTRACTOR_METAFORMAT_C_STRING: 425 if (verbose > 1) 426 fprintf (stdout, 427 "%s ", 428 gettext (mt)); 429 fprintf (stdout, 430 "`%.*s'", 431 (int) data_len, 432 data); 433 break; 434 default: 435 break; 436 } 437 return 0; 438 } 439 440 441 /** 442 * Entry in the map we construct for each file. 443 */ 444 struct BibTexMap 445 { 446 /** 447 * Name in bibTeX 448 */ 449 const char *bibTexName; 450 451 /** 452 * Meta type for the value. 453 */ 454 enum EXTRACTOR_MetaType le_type; 455 456 /** 457 * The value itself. 458 */ 459 char *value; 460 }; 461 462 463 /** 464 * Type of the entry for bibtex. 465 */ 466 static char *entry_type; 467 468 /** 469 * Mapping between bibTeX strings, libextractor 470 * meta data types and values for the current document. 471 */ 472 static struct BibTexMap btm[] = { 473 { "title", EXTRACTOR_METATYPE_TITLE, NULL}, 474 { "year", EXTRACTOR_METATYPE_PUBLICATION_YEAR, NULL }, 475 { "author", EXTRACTOR_METATYPE_AUTHOR_NAME, NULL }, 476 { "book", EXTRACTOR_METATYPE_BOOK_TITLE, NULL}, 477 { "edition", EXTRACTOR_METATYPE_BOOK_EDITION, NULL}, 478 { "chapter", EXTRACTOR_METATYPE_BOOK_CHAPTER_NUMBER, NULL}, 479 { "journal", EXTRACTOR_METATYPE_JOURNAL_NAME, NULL}, 480 { "volume", EXTRACTOR_METATYPE_JOURNAL_VOLUME, NULL}, 481 { "number", EXTRACTOR_METATYPE_JOURNAL_NUMBER, NULL}, 482 { "pages", EXTRACTOR_METATYPE_PAGE_COUNT, NULL }, 483 { "pages", EXTRACTOR_METATYPE_PAGE_RANGE, NULL }, 484 { "school", EXTRACTOR_METATYPE_AUTHOR_INSTITUTION, NULL}, 485 { "publisher", EXTRACTOR_METATYPE_PUBLISHER, NULL }, 486 { "address", EXTRACTOR_METATYPE_PUBLISHER_ADDRESS, NULL }, 487 { "institution", EXTRACTOR_METATYPE_PUBLISHER_INSTITUTION, NULL }, 488 { "series", EXTRACTOR_METATYPE_PUBLISHER_SERIES, NULL}, 489 { "month", EXTRACTOR_METATYPE_PUBLICATION_MONTH, NULL }, 490 { "url", EXTRACTOR_METATYPE_URL, NULL}, 491 { "note", EXTRACTOR_METATYPE_COMMENT, NULL}, 492 { "eprint", EXTRACTOR_METATYPE_BIBTEX_EPRINT, NULL }, 493 { "type", EXTRACTOR_METATYPE_PUBLICATION_TYPE, NULL }, 494 { NULL, 0, NULL } 495 }; 496 497 498 /** 499 * Clean up the bibtex processor in preparation for the next round. 500 */ 501 static void 502 cleanup_bibtex () 503 { 504 unsigned int i; 505 506 for (i = 0; NULL != btm[i].bibTexName; i++) 507 { 508 free (btm[i].value); 509 btm[i].value = NULL; 510 } 511 free (entry_type); 512 entry_type = NULL; 513 } 514 515 516 /** 517 * Callback function for printing meta data in bibtex format. 518 * 519 * @param cls closure, not used 520 * @param plugin_name name of the plugin that produced this value; 521 * special values can be used (i.e. '<zlib>' for zlib being 522 * used in the main libextractor library and yielding 523 * meta data). 524 * @param type libextractor-type describing the meta data 525 * @param format basic format information about data 526 * @param data_mime_type mime-type of data (not of the original file); 527 * can be NULL (if mime-type is not known) 528 * @param data actual meta-data found 529 * @param data_len number of bytes in data 530 * @return 0 to continue extracting (always) 531 */ 532 static int 533 print_bibtex (void *cls, 534 const char *plugin_name, 535 enum EXTRACTOR_MetaType type, 536 enum EXTRACTOR_MetaFormat format, 537 const char *data_mime_type, 538 const char *data, 539 size_t data_len) 540 { 541 if (0 == data_len) 542 return 0; 543 if (YES != print[type]) 544 return 0; 545 if (EXTRACTOR_METAFORMAT_UTF8 != format) 546 return 0; 547 if (EXTRACTOR_METATYPE_BIBTEX_ENTRY_TYPE == type) 548 { 549 entry_type = strndup (data, 550 data_len); 551 return 0; 552 } 553 for (unsigned int i = 0; 554 NULL != btm[i].bibTexName; 555 i++) 556 if ( (NULL == btm[i].value) && 557 (btm[i].le_type == type) ) 558 btm[i].value = strndup (data, 559 data_len); 560 return 0; 561 } 562 563 564 /** 565 * Print the computed bibTeX entry. 566 * 567 * @param fn file for which the entry was created. 568 */ 569 static void 570 finish_bibtex (const char *fn) 571 { 572 ssize_t n; 573 const char *et; 574 char temp[20]; 575 576 if (NULL != entry_type) 577 et = entry_type; 578 else 579 et = "misc"; 580 if ( (NULL == btm[0].value) || 581 (NULL == btm[1].value) || 582 (NULL == btm[2].value) ) 583 fprintf (stdout, 584 "@%s %s { ", 585 et, 586 fn); 587 else 588 { 589 snprintf (temp, 590 sizeof (temp), 591 "%.5s%.5s%.5s", 592 btm[2].value, 593 btm[1].value, 594 btm[0].value); 595 for (n = strlen (temp) - 1; n>=0; n--) 596 if (! isalnum ( (unsigned char) temp[n]) ) 597 temp[n] = '_'; 598 else 599 temp[n] = tolower ( (unsigned char) temp[n]); 600 fprintf (stdout, 601 "@%s %s { ", 602 et, 603 temp); 604 } 605 for (unsigned int i = 0; NULL != btm[i].bibTexName; i++) 606 if (NULL != btm[i].value) 607 fprintf (stdout, 608 "\t%s = {%s},\n", 609 btm[i].bibTexName, 610 btm[i].value); 611 fprintf (stdout, 612 "%s", 613 "}\n\n"); 614 } 615 616 617 #ifdef WINDOWS 618 static int 619 _wchar_to_str (const wchar_t *wstr, 620 char **retstr, 621 UINT cp) 622 { 623 char *str; 624 int len, lenc; 625 BOOL lossy = FALSE; 626 DWORD error; 627 628 SetLastError (0); 629 len = WideCharToMultiByte (cp, 630 0, 631 wstr, 632 -1, 633 NULL, 634 0, 635 NULL, 636 (cp == CP_UTF8 || 637 cp == CP_UTF7) 638 ? NULL 639 : &lossy); 640 error = GetLastError (); 641 if (len <= 0) 642 return -1; 643 644 str = malloc (sizeof (char) * len); 645 646 SetLastError (0); 647 lenc = WideCharToMultiByte (cp, 648 0, 649 wstr, 650 -1, 651 str, 652 len, 653 NULL, 654 (cp == CP_UTF8 || 655 cp == CP_UTF7) 656 ? NULL 657 : &lossy); 658 error = GetLastError (); 659 if (lenc != len) 660 { 661 free (str); 662 return -3; 663 } 664 *retstr = str; 665 if (lossy) 666 return 1; 667 return 0; 668 } 669 670 671 #endif 672 673 674 /** 675 * Makes a copy of argv that consists of a single memory chunk that can be 676 * freed with a single call to free (); 677 */ 678 static char ** 679 _make_continuous_arg_copy (int argc, 680 char *const *argv) 681 { 682 size_t argvsize = 0; 683 int i; 684 char **new_argv; 685 char *p; 686 687 for (i = 0; i < argc; i++) 688 argvsize += strlen (argv[i]) + 1 + sizeof (char *); 689 new_argv = malloc (argvsize + sizeof (char *)); 690 if (NULL == new_argv) 691 return NULL; 692 p = (char *) &new_argv[argc + 1]; 693 for (i = 0; i < argc; i++) 694 { 695 new_argv[i] = p; 696 strcpy (p, argv[i]); 697 p += strlen (argv[i]) + 1; 698 } 699 new_argv[argc] = NULL; 700 return (char **) new_argv; 701 } 702 703 704 /** 705 * Returns utf-8 encoded arguments. 706 * Returned argv has u8argv[u8argc] == NULL. 707 * Returned argv is a single memory block, and can be freed with a single 708 * free () call. 709 * 710 * @param argc argc (as given by main()) 711 * @param argv argv (as given by main()) 712 * @param u8argc a location to store new argc in (though it's th same as argc) 713 * @param u8argv a location to store new argv in 714 * @return 0 on success, -1 on failure 715 */ 716 static int 717 _get_utf8_args (int argc, 718 char *const *argv, 719 int *u8argc, 720 char ***u8argv) 721 { 722 #ifdef WINDOWS 723 wchar_t *wcmd; 724 wchar_t **wargv; 725 int wargc; 726 char **split_u8argv; 727 728 wcmd = GetCommandLineW (); 729 if (NULL == wcmd) 730 return -1; 731 wargv = CommandLineToArgvW (wcmd, 732 &wargc); 733 if (NULL == wargv) 734 return -1; 735 736 split_u8argv = malloc (wargc * sizeof (char *)); 737 if (NULL == split_u8argv) 738 return -1; 739 for (unsigned int i = 0; i < wargc; i++) 740 { 741 if (0 != 742 _wchar_to_str (wargv[i], 743 &split_u8argv[i], 744 CP_UTF8)) 745 { 746 int e = errno; 747 748 for (unsigned int j = 0; j < i; j++) 749 free (split_u8argv[j]); 750 free (split_u8argv); 751 LocalFree (wargv); 752 errno = e; 753 return -1; 754 } 755 } 756 757 *u8argv = _make_continuous_arg_copy (wargc, 758 split_u8argv); 759 if (NULL == *u8argv) 760 { 761 free (split_u8argv); 762 return -1; 763 } 764 *u8argc = wargc; 765 766 for (unsigned int i = 0; i < wargc; i++) 767 free (split_u8argv[i]); 768 free (split_u8argv); 769 #else 770 *u8argv = _make_continuous_arg_copy (argc, 771 argv); 772 if (NULL == *u8argv) 773 return -1; 774 *u8argc = argc; 775 #endif 776 return 0; 777 } 778 779 780 /** 781 * Main function for the 'extract' tool. Invoke with a list of 782 * filenames to extract keywords from. 783 * 784 * @param argc number of arguments in argv 785 * @param argv command line options and filename to run on 786 * @return 0 on success 787 */ 788 int 789 main (int argc, 790 char *argv[]) 791 { 792 unsigned int i; 793 struct EXTRACTOR_PluginList *plugins; 794 int option_index; 795 int c; 796 char *libraries = NULL; 797 int nodefault = NO; 798 int defaultAll = YES; 799 int bibtex = NO; 800 int grepfriendly = NO; 801 int ret = 0; 802 EXTRACTOR_MetaDataProcessor processor = NULL; 803 char **utf8_argv; 804 int utf8_argc; 805 806 #if ENABLE_NLS 807 setlocale (LC_ALL, ""); 808 textdomain (PACKAGE); 809 #endif 810 #ifndef WINDOWS 811 ignore_sigpipe (); 812 #endif 813 if (NULL == (print = malloc (sizeof (int) * EXTRACTOR_metatype_get_max ()))) 814 { 815 fprintf (stderr, 816 "malloc failed: %s\n", 817 strerror (errno)); 818 return 1; 819 } 820 for (i = 0; i < EXTRACTOR_metatype_get_max (); i++) 821 print[i] = YES; /* default: print everything */ 822 823 if (0 != _get_utf8_args (argc, argv, 824 &utf8_argc, &utf8_argv)) 825 { 826 fprintf (stderr, 827 "Failed to get arguments: %s\n", 828 strerror (errno)); 829 return 1; 830 } 831 832 while (1) 833 { 834 static struct option long_options[] = { 835 {"bibtex", 0, 0, 'b'}, 836 {"grep-friendly", 0, 0, 'g'}, 837 {"help", 0, 0, 'h'}, 838 {"in-process", 0, 0, 'i'}, 839 {"from-memory", 0, 0, 'm'}, 840 {"list", 0, 0, 'L'}, 841 {"library", 1, 0, 'l'}, 842 {"nodefault", 0, 0, 'n'}, 843 {"print", 1, 0, 'p'}, 844 {"verbose", 0, 0, 'V'}, 845 {"version", 0, 0, 'v'}, 846 {"exclude", 1, 0, 'x'}, 847 {0, 0, 0, 0} 848 }; 849 option_index = 0; 850 c = getopt_long (utf8_argc, 851 utf8_argv, 852 "abghiml:Lnp:vVx:", 853 long_options, 854 &option_index); 855 856 if (c == -1) 857 break; /* No more flags to process */ 858 switch (c) 859 { 860 case 'b': 861 bibtex = YES; 862 if (NULL != processor) 863 { 864 fprintf (stderr, 865 "%s", 866 _ ( 867 "Illegal combination of options, cannot combine multiple styles of printing.\n")) 868 ; 869 free (utf8_argv); 870 return 0; 871 } 872 processor = &print_bibtex; 873 break; 874 case 'g': 875 grepfriendly = YES; 876 if (NULL != processor) 877 { 878 fprintf (stderr, 879 "%s", 880 _ ( 881 "Illegal combination of options, cannot combine multiple styles of printing.\n")) 882 ; 883 free (utf8_argv); 884 return 0; 885 } 886 processor = &print_selected_keywords_grep_friendly; 887 break; 888 case 'h': 889 print_help (); 890 free (utf8_argv); 891 return 0; 892 case 'i': 893 in_process = YES; 894 break; 895 case 'm': 896 from_memory = YES; 897 break; 898 case 'l': 899 libraries = optarg; 900 break; 901 case 'L': 902 i = 0; 903 while (NULL != EXTRACTOR_metatype_to_string (i)) 904 printf ("%s\n", 905 gettext (EXTRACTOR_metatype_to_string (i++))); 906 free (utf8_argv); 907 return 0; 908 case 'n': 909 nodefault = YES; 910 break; 911 case 'p': 912 if (NULL == optarg) 913 { 914 fprintf (stderr, 915 _ ( 916 "You must specify an argument for the `%s' option (option ignored).\n"), 917 "-p"); 918 break; 919 } 920 if (YES == defaultAll) 921 { 922 defaultAll = NO; 923 i = 0; 924 while (NULL != EXTRACTOR_metatype_to_string (i)) 925 print[i++] = NO; 926 } 927 i = 0; 928 while (NULL != EXTRACTOR_metatype_to_string (i)) 929 { 930 if ( (0 == strcmp (optarg, 931 EXTRACTOR_metatype_to_string (i))) || 932 (0 == strcmp (optarg, 933 gettext (EXTRACTOR_metatype_to_string (i)))) ) 934 935 { 936 print[i] = YES; 937 break; 938 } 939 i++; 940 } 941 if (NULL == EXTRACTOR_metatype_to_string (i)) 942 { 943 fprintf (stderr, 944 "Unknown keyword type `%s', use option `%s' to get a list.\n", 945 optarg, 946 "-L"); 947 free (utf8_argv); 948 return -1; 949 } 950 break; 951 case 'v': 952 printf ("extract v%s\n", PACKAGE_VERSION); 953 free (utf8_argv); 954 return 0; 955 case 'V': 956 verbose++; 957 break; 958 case 'x': 959 i = 0; 960 while (NULL != EXTRACTOR_metatype_to_string (i)) 961 { 962 if ( (0 == strcmp (optarg, 963 EXTRACTOR_metatype_to_string (i))) || 964 (0 == strcmp (optarg, 965 gettext (EXTRACTOR_metatype_to_string (i)))) ) 966 { 967 print[i] = NO; 968 break; 969 } 970 i++; 971 } 972 if (NULL == EXTRACTOR_metatype_to_string (i)) 973 { 974 fprintf (stderr, 975 "Unknown keyword type `%s', use option `%s' to get a list.\n", 976 optarg, 977 "-L"); 978 free (utf8_argv); 979 return -1; 980 } 981 break; 982 default: 983 fprintf (stderr, 984 "%s", 985 _ ("Use --help to get a list of options.\n")); 986 free (utf8_argv); 987 return -1; 988 } /* end of parsing commandline */ 989 } /* while (1) */ 990 if (optind < 0) 991 { 992 fprintf (stderr, 993 "%s", "Unknown error parsing options\n"); 994 free (print); 995 free (utf8_argv); 996 return -1; 997 } 998 if (utf8_argc - optind < 1) 999 { 1000 fprintf (stderr, 1001 "%s", "Invoke with list of filenames to extract keywords form!\n"); 1002 free (print); 1003 free (utf8_argv); 1004 return -1; 1005 } 1006 1007 /* build list of libraries */ 1008 if (NO == nodefault) 1009 plugins = EXTRACTOR_plugin_add_defaults (in_process 1010 ? EXTRACTOR_OPTION_IN_PROCESS 1011 : EXTRACTOR_OPTION_DEFAULT_POLICY); 1012 else 1013 plugins = NULL; 1014 if (NULL != libraries) 1015 plugins = EXTRACTOR_plugin_add_config (plugins, 1016 libraries, 1017 in_process 1018 ? EXTRACTOR_OPTION_IN_PROCESS 1019 : EXTRACTOR_OPTION_DEFAULT_POLICY); 1020 if (NULL == processor) 1021 processor = &print_selected_keywords; 1022 if (NULL == utf8_argv[optind]) 1023 goto cleanup; 1024 /* extract keywords */ 1025 if (YES == bibtex) 1026 fprintf (stdout, 1027 "%s", 1028 _ ("% BiBTeX file\n")); 1029 for (i = optind; NULL != utf8_argv[i]; i++) 1030 { 1031 errno = 0; 1032 if (YES == grepfriendly) 1033 fprintf (stdout, 1034 "%s ", 1035 utf8_argv[i]); 1036 else if (NO == bibtex) 1037 fprintf (stdout, 1038 _ ("Keywords for file %s:\n"), 1039 utf8_argv[i]); 1040 else 1041 cleanup_bibtex (); 1042 if (NO == from_memory) 1043 EXTRACTOR_extract (plugins, 1044 utf8_argv[i], 1045 NULL, 0, 1046 processor, 1047 NULL); 1048 else 1049 { 1050 struct stat sb; 1051 unsigned char *data = NULL; 1052 int f = open (utf8_argv[i], 1053 O_RDONLY 1054 #if WINDOWS 1055 | O_BINARY 1056 #endif 1057 ); 1058 1059 if ( (-1 != f) && 1060 (0 == fstat (f, 1061 &sb)) && 1062 (MAP_FAILED != 1063 (data = mmap (NULL, 1064 (size_t) sb.st_size, 1065 PROT_READ, 1066 MAP_SHARED, 1067 f, 1068 0))) ) 1069 { 1070 EXTRACTOR_extract (plugins, 1071 NULL, 1072 data, sb.st_size, 1073 processor, 1074 NULL); 1075 } 1076 else 1077 { 1078 if (verbose > 0) 1079 fprintf (stderr, 1080 "%s: %s: %s\n", 1081 utf8_argv[0], 1082 utf8_argv[i], 1083 strerror (errno)); 1084 ret = 1; 1085 } 1086 if (MAP_FAILED != data) 1087 munmap (data, 1088 (size_t) sb.st_size); 1089 if (-1 != f) 1090 (void) close (f); 1091 } 1092 if (YES == grepfriendly) 1093 fprintf (stdout, 1094 "%s", "\n"); 1095 continue; 1096 } 1097 if (YES == grepfriendly) 1098 fprintf (stdout, 1099 "%s", 1100 "\n"); 1101 if (bibtex) 1102 finish_bibtex (utf8_argv[optind]); 1103 if (verbose > 0) 1104 fprintf (stdout, 1105 "%s", 1106 "\n"); 1107 cleanup: 1108 free (print); 1109 free (utf8_argv); 1110 EXTRACTOR_plugin_remove_all (plugins); 1111 plugins = NULL; 1112 cleanup_bibtex (); /* actually free's stuff */ 1113 return ret; 1114 } 1115 1116 1117 /* end of extract.c */