/rusxmms/rcctools

To get this branch, use:
bzr branch http://suren.me/webbzr/rusxmms/rcctools

« back to all changes in this revision

Viewing changes to rcc-recode.c

  • Committer: Suren A. Chilingaryan
  • Date: 2007-04-15 01:10:43 UTC
  • Revision ID: Arch-1:ds@dside.dyndns.org--darksoft-2004%rcctools--main--0.1--base-0
initial import

(automatically generated log message)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <unistd.h>
 
4
#include <string.h>
 
5
#include <locale.h>
 
6
 
 
7
#include <errno.h>
 
8
 
 
9
#include "config.h"
 
10
 
 
11
#ifdef HAVE_SYS_STAT_H
 
12
# include <sys/stat.h>
 
13
#endif /* HAVE_SYS_STAT_H */
 
14
#ifdef HAVE_SYS_FILE_H
 
15
# include <sys/file.h>
 
16
#endif /* HAVE_SYS_FILE_H */
 
17
#ifdef HAVE_SYS_TYPES_H
 
18
# include <sys/types.h>
 
19
#endif /* HAVE_SYS_TYPES_H */
 
20
#ifdef HAVE_DIRENT_H
 
21
# include <dirent.h>
 
22
#endif /* HAVE_DIRENT_H */
 
23
 
 
24
#ifdef HAVE_GETOPT_H
 
25
# include <getopt.h>
 
26
#endif /* HAVE_GETOPT_H */
 
27
 
 
28
#include <librcc.h>
 
29
 
 
30
#ifndef RCC_OPTION_TRANSLATE_SKIP_PARENT
 
31
# define RCC_OPTION_TRANSLATE_SKIP_PARENT RCC_OPTION_TRANSLATE_SKIP_PARRENT
 
32
#endif
 
33
 
 
34
typedef enum {
 
35
    MODE_STDIN = 0x1000,
 
36
    MODE_DIRECTORY,
 
37
    MODE_FILE,
 
38
    MODE_FILELIST
 
39
} Modes;
 
40
 
 
41
int mode = MODE_STDIN;
 
42
 
 
43
typedef enum {
 
44
    OPT_CONFIG = 'c',
 
45
    OPT_ENCODING_IN = 'e',
 
46
    OPT_FROM = 'f',
 
47
    OPT_HELP = 'h',
 
48
    OPT_LANGUAGE_IN = 'l',
 
49
    OPT_TO = 't',
 
50
    OPT_YES = 'y',
 
51
    OPT_ENCODING_OUT,
 
52
    OPT_LANGUAGE_OUT,
 
53
    OPT_TRANSLATION,
 
54
    OPT_CACHING,
 
55
    OPT_CACHE,
 
56
    OPT_AUTODETECT,
 
57
    OPT_OFFLINE,
 
58
    OPT_TIMEOUT,
 
59
    OPT_SUBDIRS,
 
60
} Options;
 
61
 
 
62
static struct option long_options[] = {
 
63
    {"config",                  required_argument, 0, OPT_CONFIG },
 
64
    {"from",                    required_argument, 0, OPT_FROM }, 
 
65
    {"to",                      required_argument, 0, OPT_TO },
 
66
    {"force-encoding",          required_argument, 0, OPT_ENCODING_IN },
 
67
    {"force-language",          required_argument, 0, OPT_LANGUAGE_IN },
 
68
    {"force-target-encoding",   required_argument, 0, OPT_ENCODING_OUT },
 
69
    {"force-target-language",   required_argument, 0, OPT_LANGUAGE_OUT },
 
70
    {"language-detection",      required_argument, 0, OPT_AUTODETECT },
 
71
    {"translation",             optional_argument, 0, OPT_TRANSLATION },
 
72
    {"caching",                 optional_argument, 0, OPT_CACHING },
 
73
    {"cache",                   required_argument, 0, OPT_CACHE },
 
74
    {"timeout",                 required_argument, 0, OPT_TIMEOUT },
 
75
    {"force",                   no_argument, 0, OPT_YES },
 
76
    {"allow-offline-processing",no_argument, 0, OPT_OFFLINE },
 
77
    {"disable-subdirs",         no_argument, 0, OPT_SUBDIRS },
 
78
    {"stdin",                   no_argument, &mode, MODE_STDIN },
 
79
    {"directory",               no_argument, &mode, MODE_DIRECTORY },
 
80
    {"file",                    no_argument, &mode, MODE_FILE },
 
81
    {"filelist",                no_argument, &mode, MODE_FILELIST },
 
82
    {"help",                    no_argument, 0, OPT_HELP },
 
83
    { 0, 0, 0, 0 }
 
84
};
 
85
 
 
86
void Usage(int argc, char *argv[]) {
 
87
    printf(
 
88
"Usage:\n"
 
89
" %s [options] [mode] [file|directory]\n"
 
90
"  Modes:\n"
 
91
"       --stdin         - Convert stdin to stdout\n"
 
92
"       --directory     - Convert file names in specified directory\n"
 
93
"       --file          - Convert specified file\n"
 
94
"       --filelist      - Convert all files writed on stdin\n"
 
95
"       --help          - Help message\n"
 
96
"\n"
 
97
"  Options:\n"
 
98
"       -c <config>     - Specify configuration name\n"
 
99
"       -f <class>      - Source class ('in' is default)\n"
 
100
"       -t <class>      - Output class ('out' is default)\n"
 
101
"       -e <enc>        - Force specified source encoding (autodetection)\n"
 
102
"       -l <lang>       - Force specified source language (from LC_CTYPE)\n"
 
103
"       --force-target-encoding=<enc>\n"
 
104
"                       - Convert to the specified encoding\n"
 
105
"       --force-target-language=<enc>\n"
 
106
"                       - Translate to the specified language\n"
 
107
"       --caching=[mode]\n"
 
108
"                       - Use recodings cache. Following modes are supported\n"
 
109
"                       off             - Turn off\n"
 
110
"                       use             - Use cached values (default)\n"
 
111
"                       add             - Add new recodings to cache\n"
 
112
"                       replace         - Replace encodings in cache\n"
 
113
"       --cache=<name>\n"
 
114
"                       - Use specified cache database instead of default one\n"
 
115
"       --translation=[mode]\n"
 
116
"                       - Enable translation. Following modes are supported:\n"
 
117
"                       full            - Full\n"
 
118
"                       skip_parent     - Skip translation to parent lang\n"
 
119
"                       skip_related    - Skip translation between related langs\n"
 
120
"                       english         - Translate to english (default)\n"
 
121
"                       transliterate   - Transliterate\n"
 
122
"       --language-detection=[mode]\n"
 
123
"                       - Lanuage autodetection. Following modes are supported:\n"
 
124
"                       off             - Current language is considered\n"
 
125
"                       on              - Use only configured langs (default)\n"
 
126
"                       all             - Try everything (slow)\n"
 
127
"       --timeout=<us>\n"
 
128
"                       - Specify recoding timeout in microseconds (1s default)\n"
 
129
"\n"
 
130
"       -y              - Do not ask any question\n"
 
131
"       --disable-subdirs\n"
 
132
"                       - Do not descend into the sub directories\n"
 
133
"\n"
 
134
" Language Relations:\n"
 
135
"  To prevent unneccesary translations the concept of related/parent languages is\n"
 
136
"  introduced. For each language you can specify a parent language.\n"
 
137
"  skip_parent   translation option will turn off translation to parent language\n"
 
138
"  skip_related  translation option will additionaly turn off translation from\n"
 
139
"  parent language.\n"
 
140
"\n"
 
141
"  For example, in the default configuration Russian is parent of Ukrainian, and\n"
 
142
"  English is parent of all other languages. With \"skip_parrent\" option the\n"
 
143
"  translation from Russian to Ukrainian would be turned off, but translation\n"
 
144
"  from Ukrainian to Russian would operate. With \"skip_related\" option the\n"
 
145
"  translation in both directions would be disabled\n"
 
146
"\n\n"
 
147
" Language Detection:\n"
 
148
"  Current version uses aspell dictionaries to autodetect language. Therefore,\n"
 
149
"  only languages with aspell available in the system aspell dictionaries are\n"
 
150
"  autodected. Beware, if your system contains a lot of installed languages,\n"
 
151
"  the autodection may take considerable amount of time.\n"
 
152
"\n\n",
 
153
argv[0]);
 
154
}
 
155
 
 
156
/*
 
157
    fs: is a standard class here, we do not need fs detecting here
 
158
*/
 
159
static rcc_class classes[] = {
 
160
    { "unicode", RCC_CLASS_TRANSLATE_CURRENT, "UTF-8", NULL, "Dummy", 0 },
 
161
    { "in", RCC_CLASS_STANDARD, NULL, NULL, "Input Encoding", 0 },
 
162
    { "out", RCC_CLASS_TRANSLATE_CURRENT, "LC_CTYPE", NULL, "Output Encoding", 0 },
 
163
    { "id3", RCC_CLASS_STANDARD, "in", NULL, "ID3 Encoding", 0 },
 
164
    { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0},
 
165
    { "pl", RCC_CLASS_STANDARD, "id3", NULL, "PlayList Title Encoding", 0},
 
166
    { "plfs", RCC_CLASS_STANDARD, "pl", NULL, "PlayList File Encoding", 0 },
 
167
    { "fs", RCC_CLASS_STANDARD, "LC_CTYPE", NULL, "FileSystem Encoding", 0 },
 
168
    { "arc", RCC_CLASS_STANDARD, "in", NULL, "Archives Encoding", 0 },
 
169
    { "oem", RCC_CLASS_STANDARD, "in", NULL, "Zip OEM Encoding", 0 },
 
170
    { "iso", RCC_CLASS_STANDARD, "in", NULL, "Zip ISO Encoding", 0 },
 
171
    { "ftp", RCC_CLASS_STANDARD, "in", NULL, "FTP Encoding", 0 },
 
172
    { "http", RCC_CLASS_STANDARD, "in", NULL, "HTTP Encoding", 0 },
 
173
    { "ssh", RCC_CLASS_STANDARD, "in", NULL, "SSH Encoding", 0 },
 
174
    { NULL }
 
175
};
 
176
 
 
177
rcc_class_id GetClass(const char *name) {
 
178
    int i;
 
179
    
 
180
    for (i = 1; classes[i].name; i++) {
 
181
        if ((!strcasecmp(name, classes[i].name))||(!strcasecmp(name, classes[i].fullname)))
 
182
            return i;
 
183
    }
 
184
    return (rcc_class_id)-1;
 
185
}
 
186
 
 
187
static char ask = 1;
 
188
static char process_subdirs = 1;
 
189
static rcc_language_id source_language_id, target_language_id;
 
190
static rcc_class_id source_class_id = 1, target_class_id = 2;
 
191
static char *efrom = NULL, *eto = NULL;
 
192
 
 
193
static int translate = RCC_OPTION_TRANSLATE_OFF;
 
194
 
 
195
 
 
196
char *Translate(const char *source);
 
197
int Stdin(const char *arg);
 
198
int Directory(const char *arg);
 
199
 
 
200
int main(int argc, char *argv[]) {
 
201
    rcc_language_id language_id, current_language_id, english_language_id;
 
202
    
 
203
    char c;
 
204
    
 
205
    char *arg = NULL;
 
206
    
 
207
    char *config_name = NULL;
 
208
    char *cache_name = NULL;
 
209
    
 
210
    char *from = "in";
 
211
    char *to = "out";
 
212
    
 
213
    unsigned char from_forced = 0;
 
214
    unsigned char to_forced = 0;
 
215
    
 
216
    char *lfrom = NULL;
 
217
    char *lto = NULL;
 
218
    
 
219
    int cache = RCC_OPTION_LEARNING_FLAG_USE;
 
220
    
 
221
    int ldetect = 0;
 
222
    int ldetect_all = 0;
 
223
    int ldetect_force = 0;
 
224
 
 
225
    unsigned long timeout = 0;
 
226
    char offline = 0;
 
227
    
 
228
    int option_index = 0;
 
229
    while ((c = getopt_long(argc, argv, "yhe:f:l:t:", long_options, &option_index)) != -1) {
 
230
        switch (c) {
 
231
            case 0:
 
232
            break;
 
233
            case OPT_HELP:
 
234
                Usage(argc, argv);
 
235
                exit(0);                
 
236
            break;
 
237
            case OPT_CONFIG:
 
238
                config_name = optarg;
 
239
            break;
 
240
            case OPT_CACHE:
 
241
                cache_name = optarg;
 
242
            case OPT_FROM:
 
243
                from_forced = 1;
 
244
                from = optarg;
 
245
            break;
 
246
            case OPT_TO:
 
247
                to_forced = 1;
 
248
                to = optarg;
 
249
            break;
 
250
            case OPT_ENCODING_IN:
 
251
                efrom = optarg;
 
252
            break;
 
253
            case OPT_ENCODING_OUT:
 
254
                eto = optarg;
 
255
            break;
 
256
            case OPT_LANGUAGE_IN:
 
257
                lfrom = optarg;
 
258
/*
 
259
                Selects main language, but for translation we can switch on
 
260
                autodetection. Should do it manualy.
 
261
*/              
 
262
                if (!ldetect_force) {
 
263
                    ldetect = 0;
 
264
                    ldetect_force = 1;
 
265
                }
 
266
 
 
267
            break;
 
268
            case OPT_LANGUAGE_OUT:
 
269
                lto = optarg;
 
270
            break;
 
271
            case OPT_TRANSLATION:
 
272
                if (!optarg)
 
273
                    translate = RCC_OPTION_TRANSLATE_TO_ENGLISH;
 
274
                else if (!strcasecmp(optarg, "full"))
 
275
                    translate = RCC_OPTION_TRANSLATE_FULL;
 
276
                else if (!strcasecmp(optarg, "skip_parent"))
 
277
                    translate = RCC_OPTION_TRANSLATE_SKIP_PARENT;
 
278
                else if (!strcasecmp(optarg, "skip_related"))
 
279
                    translate = RCC_OPTION_TRANSLATE_SKIP_RELATED;
 
280
                else if (!strcasecmp(optarg, "english"))
 
281
                    translate = RCC_OPTION_TRANSLATE_TO_ENGLISH;
 
282
                else if (!strcasecmp(optarg, "transliterate"))
 
283
                    translate = RCC_OPTION_TRANSLATE_TRANSLITERATE;
 
284
                else if (!strcasecmp(optarg, "off"))
 
285
                    translate = RCC_OPTION_TRANSLATE_OFF;
 
286
                else {
 
287
                    fprintf(stderr, "*** Unknown translation mode: %s\n\n", optarg);
 
288
                    Usage(argc, argv);
 
289
                    exit(0);
 
290
                }
 
291
                
 
292
                if (!ldetect_force) {
 
293
                    if (!strcasecmp(optarg, "off"))
 
294
                        ldetect = 0;
 
295
                    else 
 
296
                        ldetect = 1;
 
297
                }
 
298
            break;
 
299
            case OPT_CACHING:
 
300
                if (!optarg)
 
301
                    cache = RCC_OPTION_LEARNING_FLAG_USE;
 
302
                else if (!strcasecmp(optarg, "off"))
 
303
                    cache = 0;
 
304
                else if (!strcasecmp(optarg, "use"))
 
305
                    cache = RCC_OPTION_LEARNING_FLAG_USE;
 
306
                else if (!strcasecmp(optarg, "add"))
 
307
                    cache = RCC_OPTION_LEARNING_FLAG_USE|RCC_OPTION_LEARNING_FLAG_LEARN;
 
308
                else if (!strcasecmp(optarg, "replace"))
 
309
                    cache = RCC_OPTION_LEARNING_FLAG_LEARN;
 
310
                else {
 
311
                    fprintf(stderr, "*** Unknown caching mode: %s\n\n", optarg);
 
312
                    Usage(argc, argv);
 
313
                    exit(0);
 
314
                }
 
315
            break;
 
316
            case OPT_AUTODETECT:
 
317
                ldetect_force = 1;
 
318
 
 
319
                if (!optarg) ldetect = 1;
 
320
                else if (!strcasecmp(optarg, "off")) {
 
321
                    ldetect = 0;
 
322
                    ldetect_force = 1;
 
323
                } else if (!strcasecmp(optarg, "on")) {
 
324
                    ldetect = 1;
 
325
                    ldetect_all = 0;
 
326
                    ldetect_force = 1;
 
327
                } else if (!strcasecmp(optarg, "all")) {
 
328
                    ldetect = 1;
 
329
                    ldetect_all = 1;
 
330
                    ldetect_force = 1;
 
331
                }
 
332
            break;
 
333
            case OPT_TIMEOUT:
 
334
                timeout = atoi(optarg);
 
335
            break;
 
336
            case OPT_OFFLINE:
 
337
                offline = 1;
 
338
            break;
 
339
            case OPT_SUBDIRS:
 
340
                process_subdirs = 0;
 
341
            break;
 
342
            case OPT_YES:
 
343
                ask = 0;
 
344
            break;
 
345
            default:
 
346
                Usage(argc, argv);
 
347
                exit(0);
 
348
        }
 
349
    }
 
350
    
 
351
    if (optind < argc) {
 
352
        if ((optind + 1) < argc) {
 
353
            fprintf(stderr, "*** Invalid non-option arguments:\n");
 
354
            for (;optind < argc;optind++) {
 
355
                puts(argv[optind]);
 
356
            }
 
357
            fprintf(stderr, "\n\n");
 
358
            Usage(argc,argv);
 
359
            exit(0);
 
360
        }
 
361
        arg = argv[optind];
 
362
    }
 
363
 
 
364
    switch (mode) {
 
365
        case MODE_DIRECTORY:
 
366
            if (!from_forced) from = "fs";
 
367
            if (!to_forced) to = "fs";
 
368
        break;
 
369
        default:
 
370
            ;
 
371
    }
 
372
        
 
373
    setlocale(LC_ALL, "");
 
374
    
 
375
 
 
376
 
 
377
    rccInit();
 
378
    rccInitDefaultContext(NULL, 0, 0, classes, 0);
 
379
    rccInitDb4(NULL, cache_name, 0);
 
380
 
 
381
    if (timeout) rccSetOption(NULL, RCC_OPTION_TIMEOUT, timeout);
 
382
 
 
383
    if (config_name) rccLoad(NULL, config_name);
 
384
 
 
385
 
 
386
    rccSetOption(NULL, RCC_OPTION_LEARNING_MODE, cache);
 
387
 
 
388
    if (translate != RCC_OPTION_TRANSLATE_OFF) 
 
389
        rccSetOption(NULL, RCC_OPTION_TRANSLATE, translate);
 
390
 
 
391
    if (ldetect) {
 
392
        rccSetOption(NULL, RCC_OPTION_AUTODETECT_LANGUAGE, 1);
 
393
        if (ldetect_all) {
 
394
            rccSetOption(NULL, RCC_OPTION_CONFIGURED_LANGUAGES_ONLY, 0);
 
395
        }
 
396
    }
 
397
    
 
398
        // DS: More checks, sometimes we can skip that.
 
399
    if ((lfrom)||(lto)) {
 
400
//      if (lfrom) rccSetOption(NULL, RCC_OPTION_AUTODETECT_LANGUAGE, 1);
 
401
        rccSetOption(NULL, RCC_OPTION_CONFIGURED_LANGUAGES_ONLY, 0);
 
402
    }
 
403
 
 
404
    if (offline)
 
405
        rccSetOption(NULL, RCC_OPTION_OFFLINE, 1);
 
406
 
 
407
 
 
408
    if (from) {
 
409
        source_class_id = GetClass(from);
 
410
        if (source_class_id == (rcc_class_id)-1) {
 
411
            rccFree();
 
412
            fprintf(stderr, "*** Invalid source class (%s) specified\n", from);
 
413
            exit(1);
 
414
        }
 
415
    } 
 
416
    if (to) {
 
417
        target_class_id = GetClass(to);
 
418
        if (target_class_id == (rcc_class_id)-1) {
 
419
            rccFree();
 
420
            fprintf(stderr, "*** Invalid target class (%s) specified\n", to);
 
421
            exit(1);
 
422
        }
 
423
    } 
 
424
    
 
425
    current_language_id = rccGetCurrentLanguage(NULL);
 
426
    english_language_id = rccGetLanguageByName(NULL, "en");
 
427
 
 
428
    if (lfrom) {
 
429
        source_language_id = rccGetLanguageByName(NULL, lfrom);
 
430
        if (source_language_id == (rcc_language_id)-1) {
 
431
            rccFree();
 
432
            fprintf(stderr, "*** Invalid source language (%s) specified\n", lfrom);
 
433
            exit(1);
 
434
        }
 
435
    } else source_language_id = current_language_id;
 
436
    
 
437
    if (lto) {
 
438
        target_language_id = rccGetLanguageByName(NULL, lto);
 
439
        if (target_language_id == (rcc_language_id)-1) {
 
440
            rccFree();
 
441
            fprintf(stderr, "*** Invalid target language (%s) specified\n", lto);
 
442
            exit(1);
 
443
        }
 
444
    } else target_language_id = current_language_id;
 
445
    
 
446
    if (source_language_id == target_language_id) {
 
447
        language_id = source_language_id;
 
448
        
 
449
        if (language_id != current_language_id) {
 
450
            if ((rccSetLanguage(NULL, language_id))||(!rccGetCurrentLanguageName(NULL))) {
 
451
                rccFree();
 
452
                fprintf(stderr, "*** Unable to set the specified language (%s)\n", rccGetLanguageName(NULL, language_id));
 
453
                exit(1);
 
454
            }
 
455
        } else {
 
456
            // Automatic
 
457
            if (!rccGetCurrentLanguageName(NULL)) {
 
458
                if (current_language_id != english_language_id) {
 
459
                    language_id = english_language_id;
 
460
                    rccSetLanguage(NULL, english_language_id);
 
461
                }
 
462
                
 
463
                if (!rccGetCurrentLanguageName(NULL)) {
 
464
                    rccFree();
 
465
                    fprintf(stderr, "*** Default language (%s) is not configured\n", rccGetLanguageName(NULL, current_language_id));
 
466
                    exit(1);
 
467
                }
 
468
            }
 
469
        }
 
470
        
 
471
    } else {
 
472
        language_id = (rcc_language_id)-1;
 
473
        
 
474
            // Checking if languages are selectable
 
475
        if ((rccSetLanguage(NULL, source_language_id))||(!rccGetCurrentLanguageName(NULL))) {
 
476
            rccFree();
 
477
            fprintf(stderr, "*** Unable to set source language (%s)\n", rccGetLanguageName(NULL, source_language_id));
 
478
            exit(1);
 
479
        }
 
480
        if ((rccSetLanguage(NULL, target_language_id))||(!rccGetCurrentLanguageName(NULL))) {
 
481
            rccFree();
 
482
            fprintf(stderr, "*** Unable to set target language (%s)\n", rccGetLanguageName(NULL, target_language_id));
 
483
            exit(1);
 
484
        }
 
485
    }
 
486
    
 
487
    switch (mode) {
 
488
        case MODE_STDIN:
 
489
            Stdin(arg);
 
490
        break;
 
491
        case MODE_DIRECTORY:
 
492
            Directory(arg);
 
493
        break;
 
494
        case MODE_FILE:
 
495
            fprintf(stderr, "*** Mode (FILE) is not supported in current version\n");
 
496
        break;
 
497
        case MODE_FILELIST:
 
498
            fprintf(stderr, "*** Mode (FILELIST) is not supported in current version\n");
 
499
        break;
 
500
    }
 
501
 
 
502
    
 
503
    rccFree();
 
504
 
 
505
    return 0;
 
506
}
 
507
 
 
508
// DS. Dynamicaly raise string length?
 
509
int Stdin(const char *arg) {
 
510
    char *res;
 
511
    char buf[16384];
 
512
 
 
513
    while (fgets(buf,16384,stdin)) {
 
514
        res = Translate(buf);
 
515
        fprintf(stdout, res?res:buf);
 
516
        if (res) free(res);
 
517
    }
 
518
    
 
519
    return 0;
 
520
}
 
521
 
 
522
char *Fullname(const char *path, const char *name) {
 
523
    char *res;
 
524
    
 
525
    res = (char*)malloc(strlen(path) + strlen(name) + 2);
 
526
    if (res) {
 
527
        if (path[strlen(path)-1] == '/')
 
528
            sprintf(res, "%s%s",path,name);
 
529
        else
 
530
            sprintf(res, "%s/%s",path,name);
 
531
    }
 
532
    return res;
 
533
}
 
534
 
 
535
// DS: We do not follow symbolic links (add option?)
 
536
// DS: Skipping everything begining with point (system files)
 
537
int Directory(const char *arg) {
 
538
    int err;
 
539
    struct stat st;
 
540
    
 
541
    DIR *dir;
 
542
    struct dirent *entry;
 
543
    char *res;
 
544
    char answer;
 
545
    
 
546
    char stmp[255];
 
547
    char *fn, *nfn;
 
548
    
 
549
    if (!arg) arg = ".";
 
550
    
 
551
    printf("Processing directory: %s\n", arg);
 
552
    
 
553
    dir = opendir(arg);
 
554
    if (!dir) {
 
555
        fprintf(stderr, "*** Failed to process directory: %s\n", arg);
 
556
        return -1;
 
557
    }
 
558
    
 
559
    entry = readdir(dir);
 
560
    while (entry) {
 
561
        if (entry->d_name[0] == '.') {
 
562
            entry = readdir(dir);
 
563
            continue;
 
564
        }
 
565
        
 
566
        res = Translate(entry->d_name);
 
567
        if (res) {
 
568
            if (strcmp(res, entry->d_name)) {
 
569
                if (ask) {
 
570
                    printf("Rename \"%s\" to \"%s\" (y/[n]) ", entry->d_name, res);
 
571
                    scanf("%c", &answer);
 
572
                    if (answer != '\n') fgets(stmp, 255, stdin);
 
573
                    answer = ((answer=='y')||(answer=='Y'))?1:0;
 
574
                } else {
 
575
                    answer = 1;
 
576
                }
 
577
                
 
578
                if (answer) {
 
579
                    fn = Fullname(arg, entry->d_name);
 
580
                    nfn = Fullname(arg, res);
 
581
                    if ((fn)&&(nfn)) {
 
582
                        if (!lstat(nfn, &st)) {
 
583
                            if (!ask) {
 
584
                                printf("Trying rename \"%s\" to \"%s\"\n", entry->d_name, res);
 
585
                            }
 
586
                            
 
587
                            if (S_ISDIR(st.st_mode)) {
 
588
                                printf("*** Directory with that name exists, skipping\n");
 
589
                                answer = 0;
 
590
                            } else {
 
591
                                printf("*** File exists, overwrite (y/[n]) ");
 
592
                                scanf("%c", &answer);
 
593
                                if (answer != '\n') fgets(stmp, 255, stdin);
 
594
                                answer = ((answer=='y')||(answer=='Y'))?1:0;
 
595
                            }
 
596
                        }
 
597
                        if (answer) {
 
598
                            err = rename(fn, nfn);
 
599
                        }
 
600
                    } else err = ENOMEM;
 
601
                    
 
602
                    if (fn) free(fn);
 
603
                    if (nfn) free(nfn);
 
604
                    
 
605
                    if (err) {
 
606
                        printf("*** Renaming \"%s\" to \"%s\" is failed (errno: %u)\n", entry->d_name, res, errno);
 
607
                    } else if (!ask) {
 
608
                        printf("Rename completed: \"%s\" to \"%s\"\n", entry->d_name, res);
 
609
                    }
 
610
                }
 
611
            }
 
612
            free(res);
 
613
        }
 
614
        entry = readdir(dir);
 
615
    }
 
616
    closedir(dir);
 
617
    
 
618
    if (process_subdirs) {
 
619
        dir = opendir(arg);
 
620
        if (!dir) return 0;
 
621
        
 
622
        entry = readdir(dir);
 
623
        while (entry) {
 
624
            if (entry->d_name[0] == '.') {
 
625
                entry = readdir(dir);
 
626
                continue;
 
627
            }
 
628
 
 
629
            fn = Fullname(arg, entry->d_name);
 
630
            if (fn) {
 
631
                if ((!lstat(fn, &st))&&((S_ISDIR(st.st_mode)))) {
 
632
                    Directory(fn);
 
633
                }
 
634
                free(fn);
 
635
            }
 
636
            entry = readdir(dir);
 
637
        }
 
638
        closedir(dir);
 
639
    }
 
640
    
 
641
    
 
642
    return 0;
 
643
}
 
644
 
 
645
char *Translate(const char *source) {
 
646
    rcc_string rccstring;
 
647
    char *recoded, *stmp;
 
648
 
 
649
    if (strlen(source)<2) return NULL;
 
650
 
 
651
    if (source_language_id != target_language_id) {
 
652
        rccSetLanguage(NULL, source_language_id);
 
653
    }
 
654
 
 
655
    if (efrom) rccstring = rccFromCharset(NULL, efrom, source);
 
656
    else rccstring = rccFrom(NULL, source_class_id, source);
 
657
    
 
658
    if (!rccstring) return NULL;
 
659
 
 
660
    if (source_language_id != target_language_id)
 
661
        rccSetLanguage(NULL, target_language_id);
 
662
 
 
663
    if (eto) {
 
664
        if (translate = RCC_OPTION_TRANSLATE_OFF) {
 
665
            stmp = rccTo(NULL, target_class_id, rccstring);
 
666
            if (stmp) {
 
667
                recoded = rccRecodeCharsets(NULL, "UTF-8", eto, stmp);
 
668
                if (recoded)  free(stmp);
 
669
                else recoded = stmp;
 
670
            } else recoded = NULL;
 
671
            
 
672
        } else {
 
673
            recoded = rccToCharset(NULL, eto, rccstring);
 
674
        }
 
675
    } else recoded = rccTo(NULL, target_class_id, rccstring);
 
676
    
 
677
    free(rccstring);
 
678
    return recoded;        
 
679
}
 
680