Home | History | Annotate | Download | only in src
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 #include <config.h>
     29 #endif
     30 
     31 #include <unistd.h>
     32 #include <getopt.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <locale.h>
     36 #include <libgen.h>
     37 #include <sys/types.h>
     38 #include <sys/wait.h>
     39 #include <sys/stat.h>
     40 #include <unistd.h>
     41 #include <signal.h>
     42 
     43 #include <glib.h>
     44 #include <glib/gi18n.h>
     45 #include <gconf/gconf-client.h>
     46 #include <gnome.h>
     47 #include <glade/glade.h>
     48 #include <bonobo/bonobo-object.h>
     49 #include <bonobo-activation/bonobo-activation.h>
     50 
     51 #include "fsexam-application-server.h"
     52 #include "GNOME_Fsexam.h"
     53 
     54 #include "file-filter.h"
     55 #include "fsexam.h"
     56 #include "fsexam-debug.h"
     57 #include "encoding.h"
     58 #include "fsexam-log.h"
     59 #include "fsexam-dryrun.h"
     60 #include "fsexam-history.h"
     61 #include "fsexam-pref.h"
     62 #include "fsexam-setting.h"
     63 #include "file-validate.h"
     64 #include "fsexam-ui.h"
     65 #include "fsexam-helper.h"
     66 #include "fsexam-convname.h"
     67 #include "fsexam-convcontent.h"
     68 #include "fsexam-specialfile.h"
     69 #include "fsexam-encoding-dialog.h"
     70 
     71 gboolean    cli_mode = FALSE;  /* global var, CLI or GUI */
     72 gboolean    force_quit = FALSE;
     73 gboolean    stop_search = FALSE;
     74 
     75 static FSEXAM_setting *setting = NULL;
     76 static GnomeProgram   *program = NULL;
     77 static BonoboObject   *fsexam_app_server = NULL;
     78 
     79 /* Remember command line options */
     80 static gboolean        prepend_encoding = FALSE;
     81 static gboolean        append_encoding = FALSE;
     82 static gboolean        save_encoding = FALSE;
     83 static gboolean        restore = FALSE;
     84 
     85 static gchar           *special = NULL;
     86 static gchar           *encoding_list = NULL;
     87 static gchar           *dryrun_file = NULL;
     88 static GList           *files = NULL;
     89 
     90 static void             signal_handler (int);
     91 static void             show_usage (void);
     92 static void             show_version (void);
     93 static void             decode_options (gint argc, gchar **argv,
     94                                         FSEXAM_pref *pref);
     95 static gint             CLI_processing (gint argc, gchar **argv);
     96 static gint             GUI_processing (gint argc, gchar **argv);
     97 static gint             all_in_one (gint argc, gchar **argv);
     98 static gboolean         create_config_dir (const gchar *dir);
     99 static GList *          read_files_from_stdin (GList *files);
    100 static FSEXAM_setting * fsexam_init (gint argc, gchar **argv, gboolean cli_mode);
    101 
    102 
    103 #define OPT_STRING "+abd:E:e:Ff:g:HklL:npPRrSstwV?"
    104 static struct option long_options[] =
    105 {
    106     {"auto-detect",             no_argument,            NULL,   'a'},
    107     {"batch",                   no_argument,            NULL,   'b'},
    108     {"force-convert",           no_argument,            NULL,   'F'},
    109     {"hidden",                  no_argument,            NULL,   'H'},
    110     {"no-check-symlink-content",no_argument,            NULL,   'k'},
    111     {"list-encoding",           no_argument,            NULL,   'l'},
    112     {"dry-run",                 no_argument,            NULL,   'n'},
    113     {"append-encoding-list",    no_argument,            NULL,   'p'},
    114     {"prepend-encoding-list",   no_argument,            NULL,   'P'},
    115     {"recursive",               no_argument,            NULL,   'R'},
    116     {"remove",                  no_argument,            NULL,   'r'},
    117     {"save-encoding-list",      no_argument,            NULL,   'S'},
    118     {"restore",                 no_argument,            NULL,   's'},
    119     {"conv-content",            no_argument,            NULL,   't'},
    120     {"follow",                  no_argument,            NULL,   'w'},
    121     {"version",                 no_argument,            NULL,   'V'},
    122     {"help",                    no_argument,            NULL,   '?'},
    123     {"dry-run-result-file",     required_argument,      NULL,   'd'},
    124     {"set-history-length",      required_argument,      NULL,   'g'},
    125     {NULL,                      0,                      NULL,    0},
    126 };
    127 
    128 
    129 gint
    130 main(gint argc, gchar **argv)
    131 {
    132     gint  ret = FEEXIT_SUCCESS;
    133 
    134     setlocale (LC_ALL, "");
    135 
    136     bindtextdomain (GETTEXT_PACKAGE, FSEXAM_LOCALEDIR);
    137     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    138     textdomain (GETTEXT_PACKAGE);
    139 
    140     if (strcmp (basename (argv[0]), FSEXAM_CLI_NAME) == 0)
    141         cli_mode = TRUE;
    142 
    143     ret = all_in_one (argc, argv);
    144 
    145     return ret;
    146 }
    147 
    148 static void
    149 signal_handler (int sig)
    150 {
    151     switch (sig) {
    152         case SIGQUIT:
    153         case SIGINT:
    154             break;
    155 
    156         case SIGALRM:
    157             g_print (_("Another fsexam is running, will quit soon\n"));
    158             break;
    159     }
    160 
    161     fsexam_cleanup_all ();
    162 
    163     exit (EXIT_SUCCESS);
    164 }
    165 
    166 void
    167 fsexam_cleanup_all ()
    168 {
    169     if (cli_mode) {
    170         fsexam_setting_destroy (setting);
    171         fsexam_list_free (files);
    172     }else if (view != NULL) {
    173         if (view->pid > 0) {    /* kill subprocess if running */
    174             kill (view->pid, SIGKILL);
    175             wait (NULL);
    176         }
    177 
    178         fsexam_pref_save_to_gconf (view->setting->pref,
    179                                    view->setting->pref->gconf_client,
    180                                    FALSE);
    181 
    182         fsexam_view_destroy (view);
    183         view = NULL;
    184     }
    185 
    186     if (G_IS_OBJECT (fsexam_app_server))
    187 	    bonobo_object_unref (fsexam_app_server);
    188 
    189     return;
    190 }
    191 
    192 static void
    193 handle_multiple_instance ()
    194 {
    195     CORBA_Environment env;
    196     GNOME_Fsexam_Application server;
    197 
    198     alarm (5);
    199 
    200     CORBA_exception_init (&env);
    201 
    202     server = bonobo_activation_activate_from_id (
    203             "OAFIID:GNOME_Fsexam_Application",
    204             0,
    205             NULL,
    206             &env);
    207 
    208     if (server == NULL) {
    209         gdk_notify_startup_complete ();
    210         return;
    211     }
    212 
    213     GNOME_Fsexam_Application_grabFocus (server, &env);
    214     g_print (_("Another fsexam is running, will quit soon\n"));
    215 
    216     bonobo_object_release_unref (server, &env);
    217     CORBA_exception_free (&env);
    218 
    219     gdk_notify_startup_complete ();
    220 
    221     return;
    222 }
    223 
    224 static void
    225 decode_options (gint argc, gchar **argv, FSEXAM_pref *pref)
    226 {
    227     gint     	optchar;
    228     const gchar	*find_expr = NULL;
    229 
    230     while ((optchar = getopt_long (
    231                     argc, argv, OPT_STRING, long_options, NULL)) != -1){
    232         switch (optchar){
    233             case 'a':
    234                     pref->auto_detect = TRUE;
    235                     break;
    236 
    237             case 'b':
    238                     pref->auto_conversion = TRUE;
    239                     break;
    240 
    241             case 'd':
    242                     dryrun_file = optarg;
    243                     break;
    244 
    245             case 'E':
    246                     special = optarg;
    247                     break;
    248 
    249             case 'e':
    250                     encoding_list = optarg;
    251                     break;
    252 
    253             case 'F':
    254                     pref->force = TRUE;
    255                     break;
    256 
    257             case 'f':
    258                     find_expr = optarg;
    259                     break;
    260 
    261             case 'g':
    262                     pref->hist_len = atoi (optarg);
    263 
    264             case 'H':
    265                     pref->hidden = TRUE;
    266                     break;
    267 
    268             case 'k':
    269                     pref->no_check_symlink_content = TRUE;
    270                     break;
    271 
    272             case 'l':
    273                     show_avail_encoding ();    /* show supported encoding */
    274                     exit (FEEXIT_SUCCESS);
    275 
    276             case 'L':
    277                     pref->use_log = TRUE;
    278                     pref->log_file = g_strdup (optarg);
    279                     break;
    280 
    281             case 'n':
    282                     pref->dry_run = TRUE;
    283                     break;
    284 
    285             case 'P':
    286                     append_encoding = TRUE;
    287                     break;
    288 
    289             case 'p':
    290                     prepend_encoding = TRUE;
    291                     break;
    292 
    293             case 'R':
    294                     pref->recursive = TRUE;
    295                     break;
    296 
    297             case 'r':
    298                     pref->remote = TRUE;
    299                     break;
    300 
    301             case 'S':
    302                     save_encoding = TRUE;
    303                     break;
    304 
    305             case 's':
    306                     restore = TRUE;
    307                     break;
    308 
    309             case 't':
    310                     pref->conv_content = TRUE;
    311                     break;
    312 
    313             case 'w':
    314                     pref->follow = TRUE;
    315                     break;
    316 
    317             case 'V':
    318                     show_version ();   /* show version info and exit */
    319                     exit (FEEXIT_SUCCESS);
    320 
    321             case '?':
    322                     show_usage ();
    323                     exit (FEEXIT_SUCCESS);
    324 
    325             default:
    326                     fprintf (stderr,
    327                          _("Run 'fsexam --help' for usage information.\n"));
    328                     exit (FEEXIT_FAILURE);
    329         }
    330     }
    331 
    332     if (pref->hist_len < 30) {
    333         g_print (_("Warning: The given history length is too short, will reset to default value %d\n"), HISTORY_LENGTH);
    334         pref->hist_len = HISTORY_LENGTH;
    335     }
    336 
    337     /* file list */
    338     if (find_expr != NULL) {        /* find(1) will suppress other operands */
    339         files = filter_cmd_run (find_expr);
    340     }else if (cli_mode) {           /* CLI operands */
    341         if  (optind < argc){
    342             for (; optind < argc; optind ++){
    343                 if ((*argv[optind] == '-') && (*(argv[optind] + 1) == '\0')){
    344                     files = read_files_from_stdin (files);
    345                     break;
    346                 }
    347 
    348                 files = g_list_prepend (files, g_strdup (argv[optind]));
    349             }
    350         }else{
    351             if ((dryrun_file == NULL) ||
    352                     ((dryrun_file != NULL) && pref->dry_run)) {
    353                 files = read_files_from_stdin (files);
    354             }
    355         }
    356     }else {                         /* GUI operands */
    357         if (optind < argc){
    358             for (; optind < argc; optind ++){
    359                 files = g_list_append (files, g_strdup (argv[optind]));
    360                 //files = g_list_prepend (files, g_strdup (argv[optind]));
    361             }
    362         }
    363     }
    364 
    365     return;
    366 }
    367 
    368 /* Read file list from stdin */
    369 static GList *
    370 read_files_from_stdin (GList *files)
    371 {
    372     gchar *p = NULL;
    373     gchar path[PATH_MAX];
    374 
    375     fprintf (stdout, _("Please enter the file name:\n"));
    376 
    377     while ((fgets (path, PATH_MAX, stdin)) != NULL){
    378         p = g_strstrip (path);
    379 
    380         if ('\0' != *p){
    381             files = g_list_prepend (files, g_strdup (p));
    382         }
    383     }
    384 
    385     return files;
    386 }
    387 
    388 static gint
    389 CLI_processing (gint argc, gchar **argv)
    390 {
    391     gint            ret = FEEXIT_SUCCESS;
    392     CORBA_Object factory;
    393 
    394     program = gnome_program_init ("fsexam", VERSION,
    395                         LIBGNOMEUI_MODULE, argc, argv,
    396                         GNOME_PARAM_HUMAN_READABLE_NAME,
    397                         _("File Encoding Examiner"),
    398                         GNOME_PROGRAM_STANDARD_PROPERTIES,
    399                         GNOME_PARAM_APP_DATADIR, DATADIR,
    400                         NULL);
    401 
    402     if (! bonobo_activation_is_initialized ()) {
    403         bonobo_activation_init (argc, argv);
    404     }
    405 
    406     factory = bonobo_activation_activate_from_id (
    407             "OAFIID:GNOME_Fsexam_Factory",
    408             Bonobo_ACTIVATION_FLAG_EXISTING_ONLY,
    409             NULL, NULL);
    410 
    411     if (factory != NULL) {
    412         handle_multiple_instance ();
    413         return EXIT_SUCCESS;
    414     }
    415 
    416     fsexam_app_server = fsexam_application_server_new (NULL);
    417 
    418     if (!setting->pref->dry_run && (dryrun_file != NULL)){
    419         /* Scenario based conversion */
    420         setting->dryrun_info = fsexam_dryrun_file_new (dryrun_file, TRUE);
    421         ret = fsexam_convert_scenario (setting);
    422     }else if (restore){
    423         /* Restore file name or file content */
    424         if (setting->pref->conv_content) {
    425             ret = fsexam_restore (setting, files, RestoreConvContent);
    426         }else{
    427             ret = fsexam_restore (setting, files, RestoreConvName);
    428         }
    429     }else{
    430         /* Convert file name or file content */
    431         if ((NULL == setting->pref->encode_list) &&
    432                 !(setting->pref->auto_detect)) {
    433             g_print (_("Error: No given encoding and disabled"
    434                         " auto detection.\n"));
    435             ret = FEEXIT_FAILURE;
    436             goto free;
    437         }
    438 
    439         if (NULL != dryrun_file) {
    440             setting->dryrun_info = fsexam_dryrun_file_new (dryrun_file, FALSE);
    441 
    442             if (setting->dryrun_info == NULL) {
    443                 fprintf (stderr, _("Can't open dryrun file %s\n"),
    444                          dryrun_file);
    445                 ret = FEEXIT_FAILURE;
    446                 goto free;
    447             }
    448 
    449             fsexam_dryrun_write_convtype (setting->dryrun_info,
    450                         setting->pref->conv_content ? ConvContent : ConvName);
    451         }
    452 
    453         if (setting->pref->conv_content) {
    454             ret = fsexam_convert_content_batch (setting, files);
    455         }else{
    456             ret = fsexam_convert_filename_batch (setting, files);
    457         }
    458     }
    459 
    460 free:
    461     fsexam_cleanup_all ();
    462 
    463     return ret;
    464 }
    465 
    466 static gint
    467 GUI_processing (gint argc, gchar **argv)
    468 {
    469     GnomeClient     *client = NULL;
    470     CORBA_Object    factory;
    471 
    472     program = gnome_program_init ("fsexam", VERSION,
    473                         LIBGNOMEUI_MODULE, argc, argv,
    474                         GNOME_PARAM_HUMAN_READABLE_NAME,
    475                         _("File Encoding Examiner"),
    476                         GNOME_PROGRAM_STANDARD_PROPERTIES,
    477                         GNOME_PARAM_APP_DATADIR, DATADIR,
    478                         NULL);
    479 
    480     client = gnome_master_client ();
    481     g_signal_connect (G_OBJECT (client), "die",
    482                       G_CALLBACK (exit),
    483                       NULL);
    484 
    485     if (! bonobo_activation_is_initialized ()) {
    486         bonobo_activation_init (argc, argv);
    487     }
    488 
    489     factory = bonobo_activation_activate_from_id (
    490             "OAFIID:GNOME_Fsexam_Factory",
    491             Bonobo_ACTIVATION_FLAG_EXISTING_ONLY,
    492             NULL, NULL);
    493 
    494     if (factory != NULL) {
    495         handle_multiple_instance ();
    496         return EXIT_SUCCESS;
    497     }
    498 
    499     fsexam_app_server = fsexam_application_server_new (
    500             gdk_screen_get_default ());
    501 
    502     view =  fsexam_view_new ();
    503     view->setting = setting;
    504 
    505     /* set the initial state of gui */
    506     fsexam_gui_set_initial_state ();
    507 
    508     /* set dryrun buffer */
    509     fsexam_dryrun_buffer_set_buffer (
    510             FSEXAM_DRYRUN_BUFFER (setting->dryrun_info),
    511             gtk_text_view_get_buffer (GTK_TEXT_VIEW (
    512                     g_object_get_data (G_OBJECT (view->mainwin),
    513                         "textview_dryrun"))));
    514 
    515 
    516     if (files == NULL) {
    517         fsexam_construct_ui (".");
    518     }else if (g_list_length (files) == 1) {
    519         fsexam_construct_ui (files->data);
    520     }else{
    521         fsexam_construct_ui (".");
    522         fsexam_search_treeview_append_list (files);
    523     }
    524 
    525     fsexam_list_free (files);
    526 
    527     gtk_main ();
    528 
    529     return FEEXIT_SUCCESS;
    530 }
    531 
    532 /*
    533  * Create "$HOME/.fsexam"
    534  */
    535 static gboolean
    536 create_config_dir (const gchar *dir)
    537 {
    538     struct stat statbuf;
    539 
    540     if (NULL == dir) {
    541         g_print (_("The configuration directory is NULL\n"));
    542         return FALSE;
    543     }
    544 
    545     if (stat (dir, &statbuf) == -1) {
    546         gint status = mkdir (dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    547         if (status == -1) {
    548             g_print (_("Can't create configuration directory %s for fsexam\n"), dir);
    549             return FALSE;
    550         }else{
    551             return TRUE;
    552         }
    553     }
    554 
    555     if (S_ISDIR (statbuf.st_mode)) {
    556         return TRUE;
    557     }
    558 
    559     g_print (_("file %s exist and is not one directory, please rename it.\n"), dir);
    560 
    561     return FALSE;
    562 }
    563 
    564 static FSEXAM_setting *
    565 fsexam_init (gint argc, gchar **argv, gboolean cli_mode)
    566 {
    567     FSEXAM_setting *setting = NULL;
    568     gchar          *fsexam_repo = NULL;
    569     gchar          *hist_file = NULL;
    570 
    571     fsexam_repo = g_build_filename (g_get_home_dir (), FSEXAM_HIDDEN, NULL);
    572 
    573     if (! create_config_dir (fsexam_repo)) {
    574         g_free (fsexam_repo);
    575         return NULL;
    576     }
    577 
    578     hist_file = g_build_filename (fsexam_repo, HISTORY_FILE, NULL);
    579 
    580     /* Init FSEXAM_setting */
    581     setting = fsexam_setting_init (cli_mode);
    582 
    583     decode_options (argc, argv, setting->pref);
    584 
    585     fsexam_pref_set_encoding_list(setting->pref,
    586                                   encoding_list,
    587                                   append_encoding,
    588                                   prepend_encoding,
    589                                   save_encoding);
    590 
    591     /* Special file handling */
    592     if ((special != NULL)
    593             && ((strcmp (special, "COMPRESS") == 0)
    594                 || strcmp (special, "ALL") == 0)) {
    595         setting->pref->special = SPECIAL_COMPRESS;
    596     }
    597 
    598     /* log */
    599     if (setting->pref->use_log) {
    600         if (setting->log_info != NULL) {
    601             fsexam_log_close (setting->log_info);
    602         }
    603 
    604         setting->log_info = fsexam_log_open (setting->pref->log_file);
    605         /*
    606          * Need use abs path for log_file, otherwise will lost path informaiton
    607          * after saved into gconf database
    608          */
    609         if (*setting->pref->log_file != '/') {
    610             char *tmp = get_abs_path (setting->pref->log_file);
    611             g_free (setting->pref->log_file);
    612             setting->pref->log_file = tmp;
    613         }
    614     }
    615 
    616     /* initiate remote path list */
    617     setting->remote_path = get_remote_paths ();
    618     setting->hist_info = fsexam_history_open (hist_file,
    619             setting->pref->hist_len);
    620 
    621     /* Init function pointer */
    622     if (cli_mode) {
    623         setting->get_index = get_index_default;
    624         setting->update_gui = NULL;
    625         setting->display_msg = display_msg_default;
    626         setting->display_stats = fsexam_setting_display_stats;
    627     }else{
    628         setting->get_index = fsexam_gui_get_index;
    629         setting->update_gui = fsexam_gui_update;
    630         setting->display_msg = fsexam_gui_display_msg;
    631         setting->display_stats = fsexam_gui_display_stats;
    632     }
    633 
    634     if (fsexam_debug () & FSEXAM_DBG_OPTION){
    635         fsexam_setting_print (setting);
    636         g_list_foreach (files, list_print, "\t");
    637     }
    638     if (fsexam_debug () & FSEXAM_DBG_ENCODING) {
    639         g_list_foreach (setting->pref->encode_list, print_encoding, NULL);
    640     }
    641 
    642     g_free (hist_file);
    643     g_free (fsexam_repo);
    644 
    645     return setting;
    646 }
    647 
    648 static gint
    649 all_in_one (gint argc, gchar *argv[])
    650 {
    651     gint           ret;
    652 
    653     if ((signal (SIGINT, signal_handler) == SIG_ERR)
    654             || (signal (SIGQUIT, signal_handler) == SIG_ERR)
    655             || (signal (SIGALRM, signal_handler) == SIG_ERR)) {
    656         perror ("Can't set signal handler.");
    657         return EXIT_FAILURE;
    658     }
    659 
    660     g_type_init ();
    661     setting = fsexam_init (argc, argv, cli_mode);
    662     if (NULL == setting) {
    663         return EXIT_FAILURE;
    664     }
    665 
    666     if (cli_mode)
    667         ret = CLI_processing (argc, argv);
    668     else
    669         ret = GUI_processing (argc, argv);
    670 
    671     return ret;
    672 }
    673 
    674 static void
    675 show_usage ()
    676 {
    677     printf (_("Usage:\n"));
    678     printf (_("    fsexam [OPTION] ... [file]\n"));
    679 
    680     printf (_("\nSupported options:\n"));
    681 
    682     printf (_("    -a, --auto-detect      Enable encoding auto detection\n"));
    683     if (cli_mode)
    684         printf (_("    -d dry-run-result      Specify the dryrun result file\n"));
    685     printf (_("    -E module-name         Enable special file handling\n"));
    686     printf (_("    -e encoding-list       Specify additional encoding list\n"));
    687     printf (_("    -F, --force-convert    Forceful conversion mode\n"));
    688     printf (_("    -f 'expression'        Specify file filter criteria\n"));
    689     if (cli_mode)
    690         printf (_("    -g history-length      Set the history length.\n"));
    691     printf (_("    -H, --hidden           Turn on hidden file handling\n"));
    692     printf (_("    -b, --batch            Non-interactive mode\n"));
    693     printf (_("    -l, list-encoding      List all supported encoding\n"));
    694     printf (_("    -k, --no-check-symlink-content\n"));
    695     printf (_("                           Don't check the consistency between\n"
    696               "                           symbolic link and its target name\n"));
    697     printf (_("    -L logfile             Specify log file\n"));
    698     if (cli_mode)
    699         printf (_("    -n, --dry-run          Dryrun mode\n"));
    700     printf (_("    -P, --append-encoding-list\n"));
    701     printf (_("                           Append encoding list specified by\n"
    702               "                           '-e' to predefined encoding list\n"));
    703     printf (_("    -p, --prepend-encoding-list\n"));
    704     printf (_("                           Prepend encoding list specified by\n"
    705               "                           '-e' to predefined encoding list\n"));
    706     printf (_("    -R, --recursive        Recursive mode\n"));
    707     printf (_("    -r, --remote           Turn on nfs files handling\n"));
    708     printf (_("    -S, --save-encoding-list\n"));
    709     printf (_("                           Save encoding list specified by\n"
    710               "                           '-e' permanently\n"));
    711     printf (_("    -s, --restore          Restore the original name or\n"
    712               "                           content for given files\n"));
    713     printf (_("    -t, --conv-content     Convert file content rather than\n"
    714               "                           file name\n"));
    715     printf (_("    -w, --follow           Follow symbolic link\n"));
    716     printf (_("    -V, --version          Print the version information\n"));
    717     printf (_("    -?, --help             Print this usage information for fsexam\n"));
    718 
    719     return;
    720 }
    721 
    722 static void
    723 show_version ()
    724 {
    725     printf ("%s %s\n",
    726             cli_mode ? FSEXAM_CLI_NAME : FSEXAM_GUI_NAME,
    727             VERSION);
    728 
    729     return;
    730 }
    731