1 /*
2  * $Id: rearj.c,v 1.11 2005/06/21 19:53:14 andrew_belov Exp $
3  * ---------------------------------------------------------------------------
4  * This is the main file of the REARJ utility.
5  *
6  */
7 
8 #include <stdio.h>
9 #include <signal.h>
10 #include <time.h>
11 
12 #include "arj.h"
13 
14 #if COMPILER==BCC
15 #include <dir.h>
16 #elif COMPILER==MSC
17 #include <direct.h>
18 #endif
19 
20 #if TARGET==UNIX
21 #include <unistd.h>
22 #endif
23 
24 DEBUGHDR(__FILE__)                      /* Debug information block */
25 
26 /* Limits for "*.*"-alike processing */
27 #ifdef TILED
28  #define LARGE_FLIST_SIZE      20000
29  #define EXCL_FLIST_SIZE       10000
30 #else
31  #define LARGE_FLIST_SIZE FILELIST_CAPACITY
32  #define EXCL_FLIST_SIZE FILELIST_CAPACITY
33 #endif
34 
35 #define MAX_SUFFIXES              25    /* Number of supported suffixes */
36 #if TARGET!=UNIX
37 #define MAX_SUFFIX                 3    /* Consider increasing... */
38 #else
39 #define MAX_SUFFIX                32
40 #endif
41 #define MAX_ARGS                 100    /* Maximum # of command-line args */
42 
43 #if TARGET==UNIX
44  #define REARJ_SWITCHAR          "-"
45 #else
46  #define REARJ_SWITCHAR          "/"
47 #endif
48 
49 /* Time output sequence */
50 
51 #define timeseq (int)log_ts.ti_hour, (int)log_ts.ti_min, (int)log_ts.ti_sec
52 
53 /* Configuration entry structure */
54 
55 struct archiver_entry
56 {
57  char *suffix;
58  char *pack_cmd;
59  char *unpack_cmd;
60  int hidden_supported;                  /* Consider making them chars */
61  int subdirs_supported;
62  /* The following is an ASR fix for REARJ v 2.42.05 (.tar.gz) */
63  int manual_deletion;                   /* Can't delete errorneous archives */
64 };
65 
66 /* Local variables */
67 
68 static int logging_enabled;             /* 1 if actions are to be logged */
69 static struct time log_ts;              /* Current time (for logging) */
70 static int total_suffixes;              /* Number of suffixes in REARJ.CFG */
71 static struct archiver_entry archivers[MAX_SUFFIXES];
72 static int target_type;                 /* Target archive type */
73 static FILE *logstream;                 /* Log file */
74 static int ctrlc_busy;                  /* 1 if Ctrl+C can't be processed */
75 static int cnv_diskette_archives;       /* Convert diskette archives (-f) */
76 static int internal_archives_only;      /* Process only internal archive
77                                            files (-e) */
78 static int update_with_backups;         /* Allow updates of archives with
79                                            backup (-u) */
80 static int conversion_query;            /* Query for conversion (-q) */
81 static int skip_size_check;             /* Do not check total size and count */
82 static int run_preunpack_cmd;           /* Run a cmd. before unpacking */
83 static int run_precount_cmd;            /* 1 if a command must be run before
84                                            counting files */
85 static int run_extract_cmd;             /* Run a command when all files have
86                                            been extracted */
87 static int testing_mode;                /* /Y testing mode */
88 static char *backup_extension;          /* "BAK" (without a preceding dot) */
89 static char dot[]=".";                  /* Widely-used symbol */
90 static char work_dir[CCHMAXPATH];       /* Working directory */
91 static char name_fetch[CCHMAXPATH];     /* For parsing list files */
92 static int default_suffix;              /* For non-standard extensions */
93 static char *tmp_dir;
94 static char *preunpack_cmd_text;
95 static char *precount_cmd_text;
96 static char *extract_cmd_text;
97 static struct timestamp ts_newer;
98 static struct timestamp ts_older;
99 static int limit;
100 static int cleanup_initiated;
101 static int ctrlc_initiated;
102 static int skip_packing;
103 static int skip_rearj_sw;
104 static int skip_larger_output;
105 static int skip_timestamping;
106 static int pick_older;                  /* Pick older archives (/m) */
107 static int pick_newer;                  /* Pick newer archives (/n) */
108 static int exclusion_assigned;          /* Never used but implemented (/x) */
109 static int convert_nested_archives;
110 static char *acc_nested_suffixes;       /* Filter for nested archives */
111 static int delete_original_archives;
112 static unsigned long total_old_fsize, total_new_fsize;
113 static int skip_lfn;
114 static int chk_integrity;
115 static char *suffix_override;
116 static char *log_name;
117 static char *target_suffix;
118 static char *testing_marker;            /* Text to write (/Y****) */
119 static char *timestr_older;
120 static char *timestr_newer;
121 static FILE *liststream;
122 static struct date x_date;
123 static int work_directory_assigned;
124 static int skip_count;
125 static int clear_tmp_dir;               /* 1 if files in tmp. dir must be
126                                            removed upon shutdown */
127 static char *arg_ptr[MAX_ARGS];         /* Argument table */
128 static char u_strform[]="%S";
129 static char single_spc[]=" ";
130 static int n_args;
131 static int tmpdir_malloced;
132 static char rearj_sw[]="REARJ_SW";
133 
134 /* Filenames/extensions */
135 
136 static char backup_ext[]="bak";
137 static char cfg_name[]="rearj.cfg";
138 static char rearj_log[]="rearj.log";
139 
140 /* Pauses the execution and displays an error */
141 
pause_error(FMSG * msg)142 void pause_error(FMSG *msg)
143 {
144  arj_delay(5);
145  msg_cprintf(H_ERR, msg);
146  exit(REARJ_ERL_WARNING);
147 }
148 
149 /* Resets the attributes of all files in the current directory */
150 
reset_attrs()151 static void reset_attrs()
152 {
153  char tmp_name[CCHMAXPATH];
154  struct flist_root tmp_flist;
155  FILE_COUNT i;
156 
157  strcpy(tmp_name, all_wildcard);
158  flist_init(&tmp_flist, LARGE_FLIST_SIZE, 0, 0);
159  wild_list(&tmp_flist, tmp_name, FETCH_DIRS, 1, 1, NULL);
160  for(i=0; i<tmp_flist.files; i++)
161  {
162   retrieve_entry(tmp_name, &tmp_flist, i);
163   flush_kbd();
164   if(file_chmod(tmp_name, 1, 0)==-1)
165    error(M_CANT_CLEAR_ATTRS, tmp_name);
166  }
167  flist_cleanup_proc(&tmp_flist);
168 }
169 
170 /* Returns total size of the files located in the current directory */
171 
count_total_size()172 static unsigned long count_total_size()
173 {
174  char tmp_name[CCHMAXPATH];
175  struct flist_root tmp_flist;
176  FILE_COUNT i;
177  unsigned long rc;
178 
179  rc=0L;
180  strcpy(tmp_name, all_wildcard);
181  flist_init(&tmp_flist, LARGE_FLIST_SIZE, 0, 0);
182  wild_list(&tmp_flist, tmp_name, FETCH_DIRS, 1, 1, NULL);
183  for(i=0; i<tmp_flist.files; i++)
184  {
185   retrieve_entry(tmp_name, &tmp_flist, i);
186   flush_kbd();
187   rc+=(unsigned long)file_getfsize(tmp_name);
188  }
189  flist_cleanup_proc(&tmp_flist);
190  return(rc);
191 }
192 
193 /* Copies one file to another with mandatory comparison */
194 
file_copy_v(char * src,char * dest)195 static int file_copy_v(char *src, char *dest)
196 {
197  FILE *istream, *ostream;
198  char buf[CACHE_SIZE], dbuf[CACHE_SIZE];
199  int bytes_read;
200 
201  istream=file_open(src, m_rb);
202  if(istream==NULL)
203   return(-1);
204  ostream=file_open(dest, m_wb);
205  if(ostream==NULL)
206  {
207   fclose(istream);
208   return(-1);
209  }
210  flush_kbd();
211  do
212  {
213   flush_kbd();
214   if((bytes_read=fread(buf, 1, sizeof(buf), istream))==0)
215    break;
216  } while(fwrite(buf, 1, bytes_read, ostream)==bytes_read);
217  if(fclose(istream))
218  {
219   fclose(ostream);
220   return(-1);
221  }
222  if(fclose(ostream))
223   return(-1);
224  istream=file_open(src, m_rb);
225  if(istream==NULL)
226   return(-1);
227  ostream=file_open(dest, m_rb);
228  if(ostream==NULL)
229  {
230   fclose(istream);
231   return(-1);
232  }
233  flush_kbd();
234  while(1)
235  {
236   if((bytes_read=fread(buf, 1, CACHE_SIZE, istream))==0)
237    break;
238   if(fread(dbuf, 1, CACHE_SIZE, ostream)!=bytes_read)
239    break;
240   if(memcmp(buf, dbuf, bytes_read))
241    break;
242   flush_kbd();
243  }
244  fclose(ostream);
245  fclose(istream);
246  return((bytes_read>0)?-1:0);
247 }
248 
249 /* Returns total number of the files located in the current directory */
250 
count_files()251 static FILE_COUNT count_files()
252 {
253  char tmp_name[CCHMAXPATH];
254  struct flist_root tmp_flist;
255  FILE_COUNT rc;
256 
257  strcpy(tmp_name, all_wildcard);
258  flist_init(&tmp_flist, LARGE_FLIST_SIZE, 0, 0);
259  wild_list(&tmp_flist, tmp_name, FETCH_DIRS, 1, 1, NULL);
260  rc=tmp_flist.files;
261  flist_cleanup_proc(&tmp_flist);
262  return(rc);
263 }
264 
265 /* Recursively removes files and subdirectories */
266 
recursive_unlink(char * name)267 static void recursive_unlink(char *name)
268 {
269  struct new_ffblk new_ffblk;
270  char tmp_name[CCHMAXPATH];
271  char subdir_wildcard[20];
272  int attr_mask;
273  int result;
274 
275  attr_mask=STD_FI_ATTRS;
276  result=lfn_findfirst(name, &new_ffblk, attr_mask);
277  while(result==0)
278  {
279   if(new_ffblk.ff_attrib&STD_DIR_ATTR)
280   {
281    if(strcmp(new_ffblk.ff_name, cur_dir_spec)&&strcmp(new_ffblk.ff_name, up_dir_spec))
282    {
283     split_name(name, tmp_name, subdir_wildcard);
284     if(strlen(new_ffblk.ff_name)+strlen(tmp_name)+strlen(subdir_wildcard)+2>=CCHMAXPATH)
285      error(M_MAXDIR_EXCEEDED, tmp_name);
286     strcat(tmp_name, new_ffblk.ff_name);
287     strcat(tmp_name, pathsep_str);
288     strcat(tmp_name, subdir_wildcard);
289     case_path(tmp_name);
290     recursive_unlink(tmp_name);
291     /* Remove the directory itself */
292     split_name(name, tmp_name, NULL);
293     strcat(tmp_name, new_ffblk.ff_name);
294     flush_kbd();
295     file_chmod(tmp_name, 1, 0);
296     if(file_rmdir(tmp_name))
297      error(M_CANT_RMDIR, tmp_name);
298    }
299   }
300   else
301   {
302    split_name(name, tmp_name, NULL);
303    strcat(tmp_name, new_ffblk.ff_name);
304    case_path(tmp_name);
305    flush_kbd();
306    file_chmod(tmp_name, 1, 0);
307    if(file_unlink(tmp_name))
308     error(M_CANT_UNLINK, tmp_name);
309   }
310   result=lfn_findnext(&new_ffblk);
311  }
312  lfn_findclose(&new_ffblk);
313 }
314 
315 /* Releases the working directory -- ASR fix 14/11/2000 */
316 
release_dir(char * dir)317 static void release_dir(char *dir)
318 {
319  char tmp_name[4];
320 
321  #ifdef HAVE_DRIVES
322   if(dir[0]!='\0'&&dir[1]==':')
323   {
324    memcpy(tmp_name, dir, 2);
325    strcpy(tmp_name+2, pathsep_str);
326   }
327   else
328    strcpy(tmp_name, pathsep_str);
329  #else
330   strcpy(tmp_name, pathsep_str);
331  #endif
332  file_chdir(tmp_name);
333 }
334 
335 /* Removes all files on the specified drive/path */
336 
unlink_all(char * path)337 static void unlink_all(char *path)
338 {
339  char tmp_path[CCHMAXPATH];
340  char c;
341 
342  strcpy(tmp_path, path);
343  case_path(tmp_path);
344  c=tmp_path[strlen(tmp_path)-1];
345  #ifdef HAVE_DRIVES
346   strcat(tmp_path, (c==PATHSEP_DEFAULT||c==':')?all_wildcard:root_wildcard);
347  #else
348   strcat(tmp_path, (c==PATHSEP_DEFAULT)?all_wildcard:root_wildcard);
349  #endif
350  if(no_file_activity)
351   msg_cprintf(H_HL|H_NFMT, M_DELETING, tmp_path);
352  recursive_unlink(tmp_path);
353 }
354 
355 /* Writes a "SKIPPED" log entry */
356 
log_as_skipped(char * name,int reason)357 static void log_as_skipped(char *name, int reason)
358 {
359  if(logging_enabled)
360  {
361   arj_gettime(&log_ts);
362   if(fprintf(logstream, M_LOGENTRY_SKIP, timeseq, archivers[target_type].suffix, reason, name)<=0)
363    error(M_CANT_WRITE_LOG);
364  }
365 }
366 
367 /* Checks if any subdirectories are present in the current directory */
368 
check_for_dirs()369 static int check_for_dirs()
370 {
371  char tmp_name[CCHMAXPATH];
372  struct new_ffblk new_ffblk;
373  int attr_mask;
374  int result;
375 
376  strcpy(tmp_name, all_wildcard);
377  attr_mask=STD_FI_ATTRS;
378  result=lfn_findfirst(tmp_name, &new_ffblk, attr_mask);
379  while(result==0)
380  {
381   if(new_ffblk.ff_attrib&STD_DIR_ATTR&&strcmp(new_ffblk.ff_name, cur_dir_spec)&&strcmp(new_ffblk.ff_name, up_dir_spec))
382   {
383    lfn_findclose(&new_ffblk);
384    return(1);
385   }
386   result=lfn_findnext(&new_ffblk);
387  }
388  lfn_findclose(&new_ffblk);
389  return(0);
390 }
391 
392 /* Checks if any files and/or subdirectories are present in the current
393    directory */
394 
check_for_entries()395 static int check_for_entries()
396 {
397  char tmp_name[CCHMAXPATH];
398  struct new_ffblk new_ffblk;
399  int attr_mask;
400  int result;
401 
402  strcpy(tmp_name, all_wildcard);
403  attr_mask=STD_FI_ATTRS;
404  result=lfn_findfirst(tmp_name, &new_ffblk, attr_mask);
405  while(result==0)
406  {
407   if(!(new_ffblk.ff_attrib&STD_DIR_ATTR))
408   {
409    lfn_findclose(&new_ffblk);
410    return(1);
411   }
412   else if(strcmp(new_ffblk.ff_name, cur_dir_spec)&&strcmp(new_ffblk.ff_name, up_dir_spec))
413   {
414    lfn_findclose(&new_ffblk);
415    return(1);
416   }
417   result=lfn_findnext(&new_ffblk);
418  }
419  lfn_findclose(&new_ffblk);
420  return(0);
421 }
422 
423 /* Returns a fully-qualified filename */
424 
truename(char * dest,char * name)425 static int truename(char *dest, char *name)
426 {
427  char tmp_name[CCHMAXPATH], cur_dir[CCHMAXPATH];
428  int tmp_entry;
429 #ifdef HAVE_DRIVES
430  int dsk;
431 #endif
432 
433  tmp_entry=split_name(name, dest, tmp_name);
434  /* Verify if it's a root directory path or file path */
435  if(
436 #ifdef HAVE_DRIVES
437     (dest[1]!=':'||dest[2]!='\0')&&
438     (dest[1]!=':'||dest[2]!=PATHSEP_DEFAULT||dest[3]!='\0')&&
439 #endif
440     (dest[0]!=PATHSEP_DEFAULT||dest[1]!='\0')&&
441     (tmp_entry>0))
442   dest[tmp_entry-1]='\0';
443 #ifdef HAVE_DRIVES
444  dsk=getdisk();
445  if(dest[1]==':')
446   setdisk(toupper(dest[0])-'A');
447 #endif
448  if(file_getcwd(cur_dir)==NULL)
449  {
450   msg_cprintf(0, M_GETCWD_FAILED);
451   return(1);
452  }
453  if(
454 #ifdef HAVE_DRIVES
455    (dest[1]!=':'||dest[2]!='\0')&&
456 #endif
457     dest[0]!='\0')
458  {
459   if(file_chdir(dest))
460   {
461    msg_cprintf(H_HL|H_NFMT, M_PATH_NOT_FOUND, dest);
462 termination:
463    if(file_chdir(cur_dir))
464     error(M_CANT_CHDIR, cur_dir);
465 #ifdef HAVE_DRIVES
466    setdisk(dsk);
467 #endif
468    return(1);
469   }
470  }
471  if(file_getcwd(dest)==NULL)
472  {
473   msg_cprintf(0, M_GETCWD_FAILED);
474   goto termination;
475  }
476  if(tmp_name[0]!='\0'&&dest[strlen(dest)-1]!=PATHSEP_DEFAULT)
477   strcat(dest, pathsep_str);
478  strcat(dest, tmp_name);
479  if(file_chdir(cur_dir))
480   error(M_CANT_CHDIR, cur_dir);
481 #ifdef HAVE_DRIVES
482  setdisk(dsk);
483 #endif
484  return(0);
485 }
486 
487 /* Runs an external command */
488 
exec_cmd(char * cmd)489 static int exec_cmd(char *cmd)
490 {
491  int rc;
492 
493  if(no_file_activity)
494   return(1);
495  flush_kbd();
496  ctrlc_busy=1;
497  rc=system_cmd(cmd);
498  ctrlc_busy=0;
499  flush_kbd();
500  return(rc);
501 }
502 
503 /* Runs an external executable */
504 
exec_exe(char * cmd)505 static int exec_exe(char *cmd)
506 {
507  int rc;
508 
509  if(no_file_activity)
510   return(1);
511  flush_kbd();
512  ctrlc_busy=1;
513  rc=exec_pgm(cmd);
514  ctrlc_busy=0;
515  flush_kbd();
516  return(rc);
517 }
518 
519 /* Archive conversion procedure */
520 
convert_archive(char * name)521 static int convert_archive(char *name)
522 {
523  long old_fsize, new_fsize;
524  int exec_rc=0;
525  char full_name[CCHMAXPATH], target_name[CCHMAXPATH];
526  char bak_name[CCHMAXPATH];
527  char cnv_name[CCHMAXPATH];             /* Converted file in the work dir. */
528  char filespec[40];
529  int entry;
530  char *dot_pos;
531  int repack;
532  char *tmp_name;
533  int i;
534  int src_type;
535  struct timestamp old_ftime;
536  char cmd_buffer[400];
537  FILE_COUNT old_count=0, new_count;
538  char *nst_suf_wildcard;
539  unsigned long old_size=0, new_size;
540  long gain;
541  #if TARGET==UNIX
542   int match, fspec_len, pattern_len;
543  #else
544   char extension[64];
545  #endif
546 
547  if(truename(full_name, name))
548  {
549   msg_cprintf(H_HL|H_NFMT, M_SKIP_CANT_FIND, name);
550   return(REARJ_ERL_WARNING);
551  }
552  entry=split_name(full_name, NULL, filespec);
553  #if TARGET==UNIX
554   fspec_len=strlen(filespec);
555  #endif
556  dot_pos=strrchr(filespec, '.');
557  if(dot_pos==NULL)
558  {
559   #if TARGET!=UNIX
560    extension[0]='\0';
561   #endif
562   strcpy(target_name, full_name);
563   strcat(target_name, dot);
564   strcat(target_name, archivers[target_type].suffix);
565   strcpy(bak_name, full_name);
566  }
567  else
568  {
569   #if TARGET!=UNIX
570    *dot_pos++='\0';
571    strcpy(extension, dot_pos);
572   #endif
573   strncpy(target_name, full_name, entry);
574   target_name[entry]='\0';
575   strcpy(bak_name, target_name);
576   #if TARGET!=UNIX
577    strcat(target_name, filespec);
578    strcat(target_name, dot);
579    strcat(target_name, archivers[target_type].suffix);
580   #endif
581   strcat(bak_name, filespec);
582  }
583  strcat(bak_name, dot);
584  strcat(bak_name, backup_extension);
585  strcpy(cnv_name, work_dir);
586  strcat(cnv_name, pathsep_str);
587  strcat(cnv_name, filespec);
588  strcat(cnv_name, dot);
589  strcat(cnv_name, archivers[target_type].suffix);
590  repack=!strcmp_os(target_name, full_name);
591  tmp_name=cnv_diskette_archives?cnv_name:target_name;
592  src_type=-1;
593  for(i=0; i<total_suffixes; i++)
594  {
595   #if TARGET==UNIX
596    match=0;
597    if(dot_pos==NULL)
598    {
599     if(archivers[i].suffix[0]=='\0')
600      match=1;
601    }
602    else
603    {
604     pattern_len=strlen(archivers[i].suffix);
605     if(fspec_len>pattern_len&&
606        filespec[fspec_len-pattern_len-1]=='.'&&
607        !strcmp_os(filespec+fspec_len-pattern_len, archivers[i].suffix))
608     {
609      match=1;
610      strcat(target_name, filespec);
611      target_name[strlen(target_name)-pattern_len]='\0';
612      strcat(target_name, archivers[target_type].suffix);
613     }
614    }
615    if(match)
616     src_type=i;
617   #else
618    if(!strcmp_os(extension, archivers[i].suffix))
619     src_type=i;
620   #endif
621  }
622  if(src_type==-1)
623   src_type=default_suffix;
624  if(src_type==-1)
625  {
626   msg_cprintf(H_HL|H_NFMT, M_SKIP_UNKNOWN_TYPE, full_name);
627   return(REARJ_ERL_UNCONFIGURED);
628  }
629  old_fsize=file_getfsize(full_name);
630  if((!overwrite_existing&&!repack&&file_exists(target_name))||
631     (cnv_diskette_archives&&!overwrite_existing&&file_exists(cnv_name)))
632  {
633   msg_cprintf(H_HL|H_NFMT, M_SKIP_TGT_EXISTS, full_name);
634   return(REARJ_ERL_TGT_EXISTS);
635  }
636  if(!update_with_backups&&repack)
637  {
638   msg_cprintf(H_HL|H_NFMT, M_SKIP_REPACK, full_name);
639   return(REARJ_ERL_UPD_SKIPPED);
640  }
641  msg_cprintf(H_HL|H_NFMT, M_CONVERTING_ARCHIVE, full_name, archivers[src_type].suffix, archivers[target_type].suffix);
642  if(conversion_query)
643  {
644   msg_cprintf(0, M_QUERY_CONVERT);
645   if(!query_action())
646   {
647    msg_cprintf(H_HL|H_NFMT, M_SKIPPING, full_name);
648    return(REARJ_ERL_UPD_SKIPPED);
649   }
650  }
651  if(overwrite_existing&&!repack&&file_exists(target_name)&&!no_file_activity)
652   if(file_unlink(target_name))
653    error(M_CANT_UNLINK, target_name);
654  if(cnv_diskette_archives&&overwrite_existing&&file_exists(cnv_name)&&!no_file_activity)
655   if(file_unlink(cnv_name))
656    error(M_CANT_UNLINK, cnv_name);
657  ts_store(&old_ftime, OS, file_getftime(full_name));
658  unlink_all(tmp_dir);
659  if(file_chdir(tmp_dir))
660   error(M_CANT_CHDIR, tmp_dir);
661  if(run_preunpack_cmd)
662  {
663   sprintf(cmd_buffer, "%s %s", preunpack_cmd_text, full_name);
664   msg_cprintf(H_HL|H_NFMT, M_EXECUTING_PRE, cmd_buffer);
665   exec_cmd(cmd_buffer);
666  }
667  sprintf(cmd_buffer, archivers[src_type].unpack_cmd, full_name);
668  msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
669  exec_rc=exec_exe(cmd_buffer);
670  if(exec_rc!=0)
671  {
672   if(exec_rc==-1)
673    msg_cprintf(H_HL|H_NFMT, M_SKIP_EXE_MISSING, full_name);
674   else
675    msg_cprintf(H_HL|H_NFMT, M_SKIP_UNPACK_ERR, full_name, exec_rc);
676   return(REARJ_ERL_UNPACK);
677  }
678  if(!archivers[target_type].subdirs_supported&&check_for_dirs())
679  {
680   msg_cprintf(H_HL|H_NFMT, M_SKIP_UNSUPP_DIR, full_name);
681   return(REARJ_ERL_DIRECTORIES);
682  }
683  if(!check_for_entries())
684  {
685   msg_cprintf(H_HL|H_NFMT, M_SKIP_NO_FILES, full_name);
686   return(REARJ_ERL_UNPACK);
687  }
688  if(run_precount_cmd)
689  {
690   sprintf(cmd_buffer, "%s %s", precount_cmd_text, full_name);
691   msg_cprintf(H_HL|H_NFMT, M_EXECUTING_CNT, cmd_buffer);
692   exec_cmd(cmd_buffer);
693  }
694  if(!skip_size_check)
695   old_count=count_files();
696  if(run_extract_cmd)
697  {
698   msg_cprintf(H_HL|H_NFMT, M_EXECUTING_EXTR, extract_cmd_text);
699   exec_rc=exec_exe(extract_cmd_text);
700   if(exec_rc!=0)
701   {
702    if(exec_rc==-1)
703     msg_cprintf(H_HL|H_NFMT, M_SKIP_V_EXE_MISSING, full_name);
704    else
705     msg_cprintf(H_HL|H_NFMT, M_SKIP_V_ERR, full_name, exec_rc);
706    return(REARJ_ERL_VIRUS);
707   }
708  }
709  if(convert_nested_archives)
710  {
711   nst_suf_wildcard=(acc_nested_suffixes!=NULL)?acc_nested_suffixes:archivers[src_type].suffix;
712   /* ASR FIX 30/12/1999: only 6 additional (%s) params in original REARJ v 2.42 */
713   sprintf(cmd_buffer,
714           "%s *.%s " REARJ_SWITCHAR "t%s " REARJ_SWITCHAR "d " REARJ_SWITCHAR "r " REARJ_SWITCHAR "a%s " REARJ_SWITCHAR "e%s%s%s%s%s%s%s",
715           exe_name,
716           nst_suf_wildcard,
717           archivers[target_type].suffix,
718           nst_suf_wildcard,
719           skip_size_check?" " REARJ_SWITCHAR "s":nullstr,
720           no_file_activity?" " REARJ_SWITCHAR "z":nullstr,
721           update_with_backups?" " REARJ_SWITCHAR "u":nullstr,
722           overwrite_existing?" " REARJ_SWITCHAR "o":nullstr,
723           run_extract_cmd?" " REARJ_SWITCHAR "v":nullstr,
724           skip_rearj_sw?" " REARJ_SWITCHAR "+":nullstr,
725           skip_packing?" " REARJ_SWITCHAR "g":nullstr);
726   msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
727   exec_rc=exec_exe(cmd_buffer);
728   if(exec_rc!=0)
729   {
730    if(exec_rc==-1)
731     msg_cprintf(H_HL|H_NFMT, M_SKIP_REARJ_MISSING, full_name);
732    else
733     msg_cprintf(H_HL|H_NFMT, M_SKIP_REARJ_FAILED, full_name, exec_rc);
734    return(REARJ_ERL_INTERNAL);
735   }
736  }
737  if(skip_packing)
738  {
739   if(logging_enabled)
740   {
741    arj_gettime(&log_ts);
742    if(fprintf(logstream, M_LOGENTRY_CONV, timeseq, archivers[target_type].suffix, old_fsize, 0L, 0L, full_name)<=0)
743     error(M_CANT_WRITE_LOG);
744   }
745   return(0);
746  }
747  if(!skip_size_check)
748   old_size=count_total_size();
749  if(!archivers[target_type].hidden_supported)
750   reset_attrs();
751  if(update_with_backups&&repack)
752  {
753   if(file_exists(bak_name)&&!no_file_activity)
754    if(file_unlink(bak_name))
755     error(M_CANT_UNLINK, bak_name);
756   if(!no_file_activity)
757    if(rename_with_check(full_name, bak_name))
758    {
759     msg_cprintf(H_HL|H_NFMT, M_SKIP_CANT_RENAME, full_name, bak_name);
760     return(REARJ_ERL_RENAME);
761    }
762   if(!no_file_activity)
763    msg_cprintf(H_HL|H_NFMT, M_BACKED_UP, full_name, bak_name);
764  }
765  sprintf(cmd_buffer, archivers[target_type].pack_cmd, tmp_name);
766  msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
767  exec_rc=exec_exe(cmd_buffer);
768  if(exec_rc!=0)
769  {
770   if(update_with_backups&&repack)
771   {
772    if(file_exists(full_name)&&!no_file_activity)
773     if(file_unlink(full_name))
774      error(M_CANT_UNLINK, full_name);
775    if(!no_file_activity)
776     if(rename_with_check(bak_name, full_name))
777      error(M_CANTRENAME, bak_name, full_name);
778   }
779   if(exec_rc==-1)
780    msg_cprintf(H_HL|H_NFMT, M_SKIP_P_EXE_MISSING, full_name);
781   else
782   {
783    /* ASR fix for 2.42.05 -- unlink empty .tar.gz archives */
784    if(archivers[target_type].manual_deletion)
785     unlink(tmp_name);
786    msg_cprintf(H_HL|H_NFMT, M_SKIP_PACK_ERR, full_name, exec_rc);
787   }
788   return(REARJ_ERL_PACK);
789  }
790  if(file_chdir(work_dir))
791   error(M_CANT_CHDIR, work_dir);
792  if(!file_exists(tmp_name))
793  {
794   if(update_with_backups&&repack)
795   {
796    if(file_exists(full_name)&&!no_file_activity)
797     if(file_unlink(full_name))
798      error(M_CANT_UNLINK, full_name);
799    if(!no_file_activity)
800     if(rename_with_check(bak_name, full_name))
801      error(M_CANTRENAME, bak_name, full_name);
802   }
803   msg_cprintf(H_HL|H_NFMT, M_SKIP_NOT_PACKED, full_name);
804   return(REARJ_ERL_PACK);
805  }
806  new_fsize=file_getfsize(tmp_name);
807  if(skip_larger_output&&old_fsize<new_fsize)
808  {
809   msg_cprintf(H_HL|H_NFMT, M_SKIP_LARGER, full_name);
810   if(!no_file_activity)
811    if(file_unlink(tmp_name))
812     error(M_CANT_UNLINK, tmp_name);
813   if(update_with_backups||!repack||no_file_activity)
814    return(REARJ_ERL_OVERGROW);
815   else
816   {
817    if(rename_with_check(bak_name, full_name))
818     return(REARJ_ERL_OVERGROW);
819    else
820     error(M_CANTRENAME, bak_name, full_name);
821   }
822  }
823  if(!skip_size_check)
824  {
825   msg_cprintf(H_HL|H_NFMT, M_VERIFYING_SIZE, old_count, old_size);
826   unlink_all(tmp_dir);
827   if(file_chdir(tmp_dir))
828    error(M_CANT_CHDIR, tmp_dir);
829   sprintf(cmd_buffer, archivers[target_type].unpack_cmd, tmp_name);
830   msg_cprintf(H_HL|H_NFMT, M_EXECUTING, cmd_buffer);
831   exec_exe(cmd_buffer);
832   new_count=count_files();
833   new_size=count_total_size();
834   msg_cprintf(H_HL|H_NFMT, M_FOUND_SIZE, new_count, new_size);
835   if(old_count!=new_count)
836   {
837    msg_cprintf(H_HL|H_NFMT, M_SKIP_COUNT_MISMATCH, full_name);
838    if(!no_file_activity)
839     if(file_unlink(tmp_name))
840      error(M_CANT_UNLINK, tmp_name);
841    if(update_with_backups&&repack&&!no_file_activity)
842     if(rename_with_check(bak_name, full_name))
843      error(M_CANTRENAME, bak_name, full_name);
844    return(REARJ_ERL_COUNT);
845   }
846   if(old_size!=new_size)
847   {
848    msg_cprintf(H_HL|H_NFMT, M_SKIP_SIZE_MISMATCH, full_name);
849    if(!no_file_activity)
850     if(file_unlink(tmp_name))
851      error(M_CANT_UNLINK, tmp_name);
852    if(update_with_backups&&repack&&!no_file_activity)
853     if(rename_with_check(bak_name, full_name))
854      error(M_CANTRENAME, bak_name, full_name);
855    return(REARJ_ERL_SIZE);
856   }
857   msg_cprintf(H_HL, M_SIZE_VERIFIED);
858   if(file_chdir(work_dir))
859    error(M_CANT_CHDIR, work_dir);
860  }
861  if(cnv_diskette_archives)
862  {
863   if(file_getfree(full_name)+old_fsize<new_fsize)
864   {
865    msg_cprintf(H_HL|H_NFMT, M_SKIP_DISK_FULL, full_name);
866    if(!no_file_activity)
867     if(file_unlink(tmp_name))
868      error(M_CANT_UNLINK, tmp_name);
869    if(update_with_backups&&repack&&!no_file_activity)
870     if(rename_with_check(bak_name, full_name))
871      error(M_CANTRENAME, bak_name, full_name);
872    return(REARJ_ERL_DISK_FULL);
873   }
874  }
875  if(delete_original_archives)
876  {
877   if(!repack)
878   {
879    msg_cprintf(H_HL|H_NFMT, M_DELETING_2, full_name);
880    if(!no_file_activity)
881     if(file_unlink(full_name))
882      error(M_CANT_UNLINK, full_name);
883   }
884   else if(cnv_diskette_archives&&update_with_backups)
885   {
886    msg_cprintf(H_HL|H_NFMT, M_DELETING_2, bak_name);
887    if(!no_file_activity)
888     if(file_unlink(bak_name))
889      error(M_CANT_UNLINK, bak_name);
890   }
891  }
892  if(cnv_diskette_archives)
893  {
894   if(!no_file_activity)
895   {
896    if(file_copy_v(cnv_name, target_name))
897     error(M_CANT_COPY, cnv_name, target_name);
898   }
899   if(!no_file_activity)
900    if(file_unlink(cnv_name))
901     error(M_CANT_UNLINK, cnv_name);
902  }
903  if(delete_original_archives&&!cnv_diskette_archives&&update_with_backups&&repack)
904  {
905   msg_cprintf(H_HL|H_NFMT, M_DELETING_2, bak_name);
906   if(!no_file_activity)
907    if(file_unlink(bak_name))
908     error(M_CANT_UNLINK, bak_name);
909  }
910  if(!skip_timestamping)
911   file_setftime(target_name, ts_native(&old_ftime, OS));
912  if(testing_mode&&!delete_original_archives)
913  {
914   if(update_with_backups&&repack)
915   {
916    if(file_exists(full_name))
917     if(file_unlink(full_name))
918      error(M_CANT_UNLINK, full_name);
919    msg_cprintf(H_HL|H_NFMT, M_RENAMING, bak_name, full_name);
920    if(!no_file_activity)
921    {
922     if(rename_with_check(bak_name, full_name))
923      error(M_CANTRENAME, bak_name, full_name);
924    }
925   }
926   else if(!repack)
927   {
928    msg_cprintf(H_HL|H_NFMT, M_DELETING_2, target_name);
929    if(!no_file_activity)
930     if(file_unlink(target_name))
931      error(M_CANT_UNLINK, target_name);
932   }
933  }
934  gain=(long)(old_fsize-new_fsize);
935  msg_cprintf(H_HL|H_NFMT, M_OLD_SIZE, old_fsize);
936  msg_cprintf(H_HL|H_NFMT, M_NEW_SIZE, new_fsize);
937  msg_cprintf(H_HL|H_NFMT, M_SAVINGS_SIZE, gain);
938  printf("\n");
939  total_old_fsize+=old_fsize;
940  total_new_fsize+=new_fsize;
941  total_files++;
942  if(logging_enabled)
943  {
944   arj_gettime(&log_ts);
945   if(fprintf(logstream, M_LOGENTRY_CONV, timeseq, archivers[target_type].suffix, old_fsize, new_fsize, gain, full_name)<=0)
946    error(M_CANT_WRITE_LOG);
947  }
948  return(0);
949 }
950 
951 /* Adds a new file to the exclusion filelist */
952 
submit_exclusion(char * name)953 static void submit_exclusion(char *name)
954 {
955  char tmp_name[CCHMAXPATH];
956  FILE *stream;
957 
958  if(name[0]=='!')
959  {
960   name++;
961   if(name[0]=='\0')
962    error(M_LISTFILE_MISSING);
963   if((stream=file_open(name, m_r))==NULL)
964    error(M_CANTOPEN, stream);
965   while(fgets(tmp_name, sizeof(tmp_name), stream)!=NULL)
966   {
967    tokenize_lf(tmp_name);
968    alltrim(tmp_name);
969    if(tmp_name[0]!='\0')
970    {
971     if(wild_list(&flist_exclusion, tmp_name, 0, 0, 0, NULL))
972      break;
973    }
974   }
975   fclose(stream);
976  }
977  else
978   wild_list(&flist_exclusion, name, 0, 0, 0, NULL);
979 }
980 
981 /* Sets up REARJ */
982 
analyze_rearj_sw(char * arg)983 static void analyze_rearj_sw(char *arg)
984 {
985  char sw;
986  char *swptr;
987 
988  swptr=arg+1;
989  sw=toupper(*swptr);
990  swptr++;
991  if(sw=='D'&&*swptr=='\0')
992   delete_original_archives=1;
993  else if(sw=='E'&&*swptr=='\0')
994   internal_archives_only=1;
995  else if(sw=='F'&&*swptr=='\0')
996   cnv_diskette_archives=1;
997  else if(sw=='H'&&*swptr=='\0')
998   help_issued=1;
999  else if(sw=='O'&&*swptr=='\0')
1000   overwrite_existing=1;
1001  else if(sw=='P'&&*swptr=='\0')
1002   skip_lfn=1;
1003  else if(sw=='Q'&&*swptr=='\0')
1004   conversion_query=1;
1005  else if(sw=='R'&&*swptr=='\0')
1006   recurse_subdirs=1;
1007  else if(sw=='S'&&*swptr=='\0')
1008   skip_size_check=1;
1009  else if(sw=='V'&&*swptr=='\0')
1010   run_extract_cmd=1;
1011  else if(sw=='Z'&&*swptr=='\0')
1012   no_file_activity=1;
1013  else if(sw=='A')
1014  {
1015   if(*swptr!='\0')
1016   {
1017    case_path(swptr);
1018    acc_nested_suffixes=swptr;
1019   }
1020   convert_nested_archives=1;
1021  }
1022  else if(sw=='B'&&*swptr!='\0')
1023  {
1024   run_preunpack_cmd=1;
1025   preunpack_cmd_text=swptr;
1026  }
1027  else if(sw=='C'&&*swptr!='\0')
1028  {
1029   run_precount_cmd=1;
1030   precount_cmd_text=swptr;
1031  }
1032  else if(sw=='I')
1033  {
1034   if(*swptr!='\0')
1035   {
1036    case_path(swptr);
1037    exe_name=swptr;
1038   }
1039   chk_integrity=1;
1040  }
1041  else if(sw=='F'&&*swptr!='\0')
1042  {
1043   default_suffix=-1;
1044   case_path(swptr);
1045   suffix_override=swptr;
1046  }
1047  else if(sw=='L')
1048  {
1049   if(*swptr!='\0')
1050   {
1051    case_path(swptr);
1052    log_name=swptr;
1053   }
1054   logging_enabled=1;
1055  }
1056  else if(sw=='T'&&*swptr!='\0')
1057  {
1058   target_type=-1;
1059   case_path(swptr);
1060   target_suffix=swptr;
1061  }
1062  else if(sw=='U')
1063  {
1064   if(*swptr!='\0')
1065   {
1066    case_path(swptr);
1067    backup_extension=swptr;
1068   }
1069   update_with_backups=1;
1070  }
1071  else if(sw=='W'&&*swptr!='\0')
1072  {
1073   case_path(swptr);
1074   tmp_dir=swptr;
1075   work_directory_assigned=1;
1076  }
1077  else if(sw=='X'&&*swptr!='\0')
1078   submit_exclusion(swptr);
1079  else if(sw=='G'&&*swptr=='\0')
1080   skip_packing=1;
1081  else if(sw=='J'&&*swptr=='\0')
1082   skip_larger_output=1;
1083  else if(sw=='K'&&*swptr=='\0')
1084   skip_timestamping=1;
1085  else if(sw=='+'&&*swptr=='\0')
1086   skip_rearj_sw=1;
1087  else if(sw=='M')
1088  {
1089   pick_older=1;
1090   timestr_older=swptr;
1091  }
1092  else if(sw=='N')
1093  {
1094   pick_newer=1;
1095   timestr_newer=swptr;
1096  }
1097  else if(sw=='Y')
1098  {
1099   testing_mode=1;
1100   testing_marker=swptr;
1101  }
1102  else
1103   error(M_INVALID_SWITCH, arg);
1104 }
1105 
1106 /* Parses REARJ.CFG */
1107 
parse_rearj_cfg()1108 static void parse_rearj_cfg()
1109 {
1110  #if COMPILER==BCC
1111   char *cfg_path;
1112  #else
1113   char cfg_path[CCHMAXPATH];
1114  #endif
1115  char tmp_line[200];
1116  FILE *stream;
1117  int i, fakesuffix;
1118 
1119  #if TARGET!=UNIX
1120   #if COMPILER==BCC
1121    if((cfg_path=searchpath(cfg_name))==NULL)
1122     error(M_CANT_FIND_CONFIG, cfg_name);
1123   #else
1124    _searchenv(cfg_name, "PATH", cfg_path);
1125    if(cfg_path[0]=='\0')
1126     error(M_CANT_FIND_CONFIG, cfg_name);
1127   #endif
1128  #else
1129   /* Attempt search in home directory first, then in /usr/local/etc. */
1130   sprintf(cfg_path, "%s/.%s", getenv("HOME"), cfg_name);
1131   if((stream=file_open(cfg_path, m_r))!=NULL)
1132    fclose(stream);
1133   else
1134    sprintf(cfg_path, "/usr/local/etc/%s", cfg_name);
1135  #endif
1136  if((stream=file_open(cfg_path, m_r))==NULL)
1137   error(M_CANTOPEN, cfg_path);
1138  msg_cprintf(H_HL|H_NFMT, M_USING_CONFIG, cfg_path);
1139  if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1140   total_suffixes=0;
1141  else
1142  {
1143   rewind(stream);
1144   for(i=0; i<MAX_SUFFIXES; i++)
1145   {
1146    /* ASR fix for 2.43, 24/01/2003 - the option strings may be placed before
1147       ANY extension command. */
1148    do
1149    {
1150     /* Extension */
1151     do
1152     {
1153      if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1154       goto no_more_exts;
1155      archivers[i].hidden_supported=0;
1156      archivers[i].subdirs_supported=0;
1157      archivers[i].manual_deletion=0;     /* ASR fix */
1158      tokenize_lf(tmp_line);
1159      alltrim(tmp_line);
1160     } while (tmp_line[0]=='\0');
1161     fakesuffix=1;
1162 #ifdef COLOR_OUTPUT
1163     if(!strnicmp(tmp_line, "COLORS ", 7))
1164     {
1165      if(parse_colors(tmp_line+7))
1166       error(M_INVALID_PARAM_STR, tmp_line);
1167     }
1168     else
1169 #endif
1170     if(!strnicmp(tmp_line, "VIRUS ", 6))
1171     {
1172      if((extr_cmd_text=strdup(tmp_line+6))==NULL)
1173       error(M_OUT_OF_MEMORY);
1174      if(strchr(extr_cmd_text, PATHSEP_DEFAULT)==NULL)
1175      {
1176       msg_cprintf(0, M_NO_ANTIVIRUS_PATH);
1177       msg_cprintf(0, M_IGNORED_FOR_COMP);
1178       arj_delay(4);
1179      }
1180     }
1181     else
1182      fakesuffix=0;
1183    } while(fakesuffix);
1184    if(strlen(tmp_line)>MAX_SUFFIX)
1185     error(M_INVALID_SUFFIX, tmp_line);
1186    if((archivers[i].suffix=strdup(tmp_line))==NULL)
1187     error(M_OUT_OF_MEMORY);
1188    /* Pack command */
1189    if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1190     error(M_MISSING_PACK_CMD, archivers[i].suffix);
1191    tokenize_lf(tmp_line);
1192    alltrim(tmp_line);
1193    if(strlen(tmp_line)==0)
1194     error(M_INVALID_PACK_CMD, tmp_line);
1195    if(strstr(tmp_line, strform)==NULL&&strstr(tmp_line, u_strform)==NULL)
1196     error(M_NO_PACK_STRFORM, tmp_line);
1197    if((archivers[i].pack_cmd=strdup(tmp_line))==NULL)
1198     error(M_OUT_OF_MEMORY);
1199    /* Unpack command */
1200    if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1201     error(M_MISSING_UNPACK_CMD, archivers[i].suffix);
1202    tokenize_lf(tmp_line);
1203    alltrim(tmp_line);
1204    if(strlen(tmp_line)==0)
1205     error(M_INVALID_UNPACK_CMD, tmp_line);
1206    if(strstr(tmp_line, strform)==NULL&&strstr(tmp_line, u_strform)==NULL)
1207     error(M_NO_UNPACK_STRFORM, tmp_line);
1208    if((archivers[i].unpack_cmd=strdup(tmp_line))==NULL)
1209     error(M_OUT_OF_MEMORY);
1210    /* Option record */
1211    if(fgets(tmp_line, sizeof(tmp_line), stream)==NULL)
1212     error(M_MISSING_OPTIONS, archivers[i].suffix);
1213    tokenize_lf(tmp_line);
1214    alltrim(tmp_line);
1215    if(strpbrk(tmp_line, "Aa")!=NULL)
1216     archivers[i].hidden_supported=1;
1217    if(strpbrk(tmp_line, "Dd")!=NULL)
1218     archivers[i].subdirs_supported=1;
1219    /* ASR fix for v 2.42.05 (.tar.gz): */
1220    if(strpbrk(tmp_line, "Tt")!=NULL)
1221     archivers[i].manual_deletion=1;
1222   }
1223 no_more_exts:
1224   total_suffixes=i;
1225  }
1226  fclose(stream);
1227 }
1228 
1229 /* atexit routine */
1230 
final_cleanup(void)1231 static void final_cleanup(void)
1232 {
1233  if(!cleanup_initiated)
1234  {
1235   cleanup_initiated=1;
1236   if(tmpdir_malloced)
1237    release_dir(tmp_dir);                /* ASR fix 14/11/2000 */
1238   if(work_dir[0]!='\0')
1239    file_chdir(work_dir);
1240   if(tmp_dir!=NULL)
1241   {
1242    if(clear_tmp_dir)
1243     unlink_all(tmp_dir);
1244    if(!work_directory_assigned)
1245     file_rmdir(tmp_dir);
1246    if(tmpdir_malloced)
1247    {
1248     free(tmp_dir);                      /* malloc'ed */
1249     tmpdir_malloced=0;
1250    }
1251   }
1252  }
1253 #ifdef COLOR_OUTPUT
1254  scrn_reset();
1255 #endif
1256 }
1257 
1258 /* Ctrl+C handler */
1259 
ctrlc_handler(SIGHDLPARAMS)1260 static void ctrlc_handler(SIGHDLPARAMS)
1261 {
1262  /* Check if we are able to honor the request. If we aren't, raise the
1263     signal again and make a speedy getaway. */
1264  if(ctrlc_busy)
1265   raise(SIGINT);
1266  else
1267  {
1268   ctrlc_initiated=1;
1269   signal(SIGINT, NULL);                 /* Restore default Ctrl+C handler */
1270   msg_cprintf(H_SIG, M_BREAK_SIGNALED);
1271   exit(REARJ_ERL_WARNING);
1272  }
1273 }
1274 
1275 /* Main routine */
1276 
main(int argc,char ** argv)1277 int main(int argc, char **argv)
1278 {
1279  int cnv_rc, exit_code;
1280  static char rearj_exe[CCHMAXPATH];
1281  int switchar;
1282  int arg;
1283  char *aptr=NULL;
1284  unsigned int i;
1285  FILE_COUNT cur_file;
1286  char tmp_name[CCHMAXPATH], src_name[CCHMAXPATH];
1287  char *fullpath;
1288  long total_gain;
1289  char *env_ptr, *env_dup, *env_tail;
1290  struct timestamp timestamp;
1291  time_t start_time, end_time;
1292  unsigned long time_diff;
1293 
1294 #ifdef COLOR_OUTPUT
1295  no_colors=redirected=!is_tty(stdout);
1296 #endif
1297  msg_cprintf(0, M_REARJ_BANNER);
1298  #ifdef USE_TZSET
1299   tzset();
1300  #endif
1301  build_crc32_table();
1302  ctrlc_busy=0;
1303  lfn_supported=LFN_NOT_SUPPORTED;
1304  convert_nested_archives=0;
1305  run_precount_cmd=0;
1306  run_preunpack_cmd=0;
1307  recurse_subdirs=0;
1308  help_issued=0;
1309  no_file_activity=0;
1310  delete_original_archives=0;
1311  skip_larger_output=0;
1312  cnv_diskette_archives=0;
1313  run_extract_cmd=0;
1314  skip_rearj_sw=0;
1315  logging_enabled=0;
1316  internal_archives_only=0;
1317  pick_older=0;
1318  pick_newer=0;
1319  conversion_query=0;
1320  chk_integrity=0;
1321  overwrite_existing=0;
1322  skip_lfn=0;
1323  skip_packing=0;
1324  skip_timestamping=0;
1325  skip_size_check=0;
1326  work_directory_assigned=0;
1327  testing_mode=0;
1328  update_with_backups=0;
1329  clear_tmp_dir=0;
1330  skip_count=0;
1331  target_type=0;
1332  total_old_fsize=total_new_fsize=0L;
1333  total_files=0;
1334  ts_store(&ts_older, OS_SPECIAL, 0L);
1335  ts_newer=ts_older;
1336  ctrlc_initiated=0;
1337  is_registered=0;
1338  exit_code=REARJ_ERL_SUCCESS;
1339  log_name=rearj_log;
1340  default_suffix=-1;
1341  backup_extension=backup_ext;
1342  #ifndef SKIP_GET_EXE_NAME
1343   get_exe_name(rearj_exe);
1344  #else
1345   get_exe_name(rearj_exe, argv[0]);
1346  #endif
1347  exe_name=rearj_exe;
1348  target_suffix=NULL;
1349  suffix_override=NULL;
1350  extract_cmd_text=NULL;
1351  precount_cmd_text=NULL;
1352  preunpack_cmd_text=NULL;
1353  tmp_dir=NULL;
1354  testing_marker=NULL;
1355  acc_nested_suffixes=NULL;
1356  work_dir[0]='\0';
1357  timestr_older=timestr_newer=nullstr;
1358  flist_init(&flist_exclusion, EXCL_FLIST_SIZE, 0, 0);
1359  atexit(final_cleanup);
1360  parse_reg_key();
1361  detect_lfns();
1362  is_registered=reg_validation(regdata+REG_KEY1_SHIFT, regdata+REG_KEY2_SHIFT, regdata+REG_NAME_SHIFT, regdata+REG_HDR_SHIFT);
1363  if(!is_registered&&!msg_strcmp((FMSG *)regdata+REG_KEY2_SHIFT, M_REG_TYPE))
1364   msg_cprintf(0, M_REGISTERED_TO, regdata+REG_NAME_SHIFT);
1365  limit=20;
1366  total_suffixes=0;
1367  if(signal(SIGINT, ctrlc_handler)==SIG_ERR)
1368   error(M_SIGNAL_FAILED);
1369  limit=0;
1370  if(regdata[REG_NAME_SHIFT]=='\0')
1371   is_registered=1;
1372  if(!reg_validation(single_spc, single_spc, single_spc, regdata+REG_HDR_SHIFT))
1373   is_registered=2;
1374  n_args=0;
1375  switchar=get_sw_char();
1376  for(arg=1; arg<argc; arg++)
1377  {
1378   aptr=argv[arg];
1379   if(aptr[0]==switchar&&aptr[1]=='+'&&aptr[2]=='\0')
1380    skip_rearj_sw=0;
1381  }
1382  if((env_ptr=getenv(rearj_sw))!=NULL)
1383  {
1384   env_dup=strdup(env_ptr);
1385   msg_cprintf(H_HL|H_NFMT, M_USING_REARJ_SW, env_dup);
1386   for(env_ptr=env_dup; *env_ptr!='\0'; env_ptr++)
1387    if(*env_ptr==' ')
1388     *env_ptr='\0';                       /* Tokenize by spaces */
1389   env_tail=env_ptr;
1390   env_ptr=env_dup;
1391   while(env_ptr<env_tail)
1392   {
1393    while(*env_ptr=='\0')
1394     env_ptr++;
1395    if(env_ptr<env_tail)
1396    {
1397     if(switchar=='-')
1398      name_to_hdr(env_ptr);
1399     if(*env_ptr==switchar)
1400      analyze_rearj_sw(aptr);
1401     while(*env_ptr!='\0'&&env_ptr<env_tail)
1402      env_ptr++;
1403    }
1404   }
1405  }
1406  for(arg=1; arg<argc; arg++)
1407  {
1408   aptr=argv[arg];
1409   if(switchar=='-')
1410    name_to_hdr(aptr);
1411   if(aptr[0]==switchar)
1412    analyze_rearj_sw(aptr);
1413   else
1414   {
1415    if(n_args>=MAX_ARGS)
1416     error(M_ARGTABLE_OVERFLOW);
1417    arg_ptr[n_args++]=aptr;
1418   }
1419  }
1420  if(skip_lfn)
1421   lfn_supported=LFN_NOT_SUPPORTED;
1422  if(chk_integrity)
1423   exit(check_integrity(rearj_exe));
1424  if(help_issued||n_args==0)
1425  {
1426   msg_cprintf(0, strform, M_REARJ_COMMANDS);
1427   msg_cprintf(0, strform, M_REARJ_RCODES);
1428   exit(REARJ_ERL_SUCCESS);
1429  }
1430  if(delete_original_archives&&testing_mode)
1431   error(M_YD_CMD_CONFLICT);
1432  if(testing_mode&&testing_marker!=NULL&&!logging_enabled)
1433   error(M_LY_CMD);
1434  parse_rearj_cfg();
1435  if(run_extract_cmd&&extract_cmd_text==NULL)
1436   error(M_NO_V_CMD, cfg_name);
1437  if(suffix_override!=NULL)
1438  {
1439   default_suffix=-1;
1440   for(i=0; i<total_suffixes; i++)
1441   {
1442    if(!strcmp_os(suffix_override, archivers[i].suffix))
1443     default_suffix=i;
1444   }
1445   if(default_suffix<0)
1446    error(M_INVALID_F_SUFFIX, suffix_override);
1447  }
1448  if(target_suffix!=NULL)
1449  {
1450   target_type=-1;
1451   for(i=limit; i<total_suffixes; i++)
1452   {
1453    if(!strcmp_os(target_suffix, archivers[i].suffix))
1454     target_type=i;
1455   }
1456   if(target_type<0)
1457    error(M_INVALID_T_SUFFIX, target_suffix);
1458  }
1459  if(pick_older||pick_newer)
1460  {
1461   if(timestr_older[0]!='\0')
1462    convert_strtime(&ts_older, timestr_older);
1463   if(timestr_newer[0]!='\0')
1464    convert_strtime(&ts_newer, timestr_newer);
1465   if(timestr_older[0]=='\0'||timestr_newer[0]=='\0')
1466   {
1467    arj_getdate(&x_date);
1468    make_timestamp(&timestamp, x_date.da_year, x_date.da_mon, x_date.da_day,
1469                   0, 0, 0);
1470    if(timestr_newer[0]=='\0')
1471     ts_newer=timestamp;
1472    if(timestr_older[0]=='\0')
1473     ts_older=timestamp;
1474   }
1475  }
1476  if(file_getcwd(work_dir)==NULL)
1477   error(M_GETCWD_FAILED);
1478  if(no_file_activity)
1479   msg_cprintf(0, M_SIMULATION_MODE);
1480  flist_init(&flist_main, LARGE_FLIST_SIZE, n_args>1, 1);
1481  for(i=limit; i<n_args; i++)
1482  {
1483   flush_kbd();
1484   if(arg_ptr[i][0]=='!')
1485   {
1486    if(arg_ptr[i][1]=='\0')
1487     error(M_NO_LISTFILE);
1488    if((liststream=file_open(arg_ptr[i]+1, m_r))==NULL)
1489     error(M_CANTOPEN, arg_ptr[i]+1);
1490    while(fgets(name_fetch, CCHMAXPATH, liststream)!=NULL)
1491    {
1492     tokenize_lf(name_fetch);
1493     alltrim(name_fetch);
1494     if(name_fetch[0]!='\0')
1495     {
1496      strcpy(tmp_name, name_fetch);
1497      if(wild_list(&flist_main, tmp_name, 0, 1, recurse_subdirs, NULL))
1498       break;
1499     }
1500    }
1501    fclose(liststream);
1502   }
1503   else
1504   {
1505    strcpy(tmp_name, arg_ptr[i]);
1506    if(wild_list(&flist_main, tmp_name, 0, 1, recurse_subdirs, NULL))
1507     break;
1508   }
1509  }
1510  if(flist_main.files==0)
1511  {
1512   msg_cprintf(0, internal_archives_only?M_NO_FILES_INT:M_NO_FILES);
1513   exit(internal_archives_only?REARJ_ERL_SUCCESS:REARJ_ERL_WARNING);
1514  }
1515  time(&start_time);
1516  if(logging_enabled)
1517  {
1518   if((logstream=file_open(log_name, m_a))==NULL)
1519    error(M_CANTOPEN, log_name);
1520   arj_gettime(&log_ts);
1521   if(testing_marker!=NULL)
1522    if(fprintf(logstream, M_LOGENTRY_MARKER, timeseq, archivers[target_type].suffix, testing_marker)<=0)
1523     error(M_CANT_WRITE_LOG);
1524   if(fprintf(logstream, M_LOGENTRY_HEADER, timeseq, archivers[target_type].suffix)<=0)
1525    error(M_CANT_WRITE_LOG);
1526  }
1527  if(cnv_diskette_archives&&count_files()>0)
1528   msg_cprintf(0, M_CWD_MUST_BE_EMPTY);
1529  if(tmp_dir==NULL)
1530  {
1531   /* BUGBUG: this comes from a NetBSD patch. Originally a check for NO_MKDTEMP
1532      was suggested, but where are we expected to define it under DOS? --
1533      ASR fix 25/01/2004 */
1534 #ifdef HAVE_MKDTEMP
1535   tmp_dir=mkdtemp("/tmp/arj.XXXXXX"); /* BUGBUG: hardcoded location? */
1536 #else
1537   tmp_dir=tmpnam(NULL);
1538   if(file_mkdir(tmp_dir))
1539    error(M_CANT_MKDIR, tmp_dir);
1540 #endif
1541  }
1542  else
1543  {
1544   if(file_chdir(tmp_dir))
1545    error(M_CANT_CHDIR, tmp_dir);
1546   if(count_files()>0)
1547    error(M_WORK_DIR_NOT_EMPTY, tmp_dir);
1548   if(file_chdir(work_dir))
1549    error(M_CANT_CHDIR, work_dir);
1550  }
1551  if((fullpath=(char *)malloc(CCHMAXPATH))==NULL)
1552   error(M_OUT_OF_MEMORY);
1553  if(truename(fullpath, tmp_dir))
1554   error(M_CANT_GET_FULL_PATH);
1555  tmp_dir=fullpath;
1556  clear_tmp_dir=1;
1557  tmpdir_malloced=1;                     /* Introduced by ASR */
1558  for(cur_file=0; cur_file<flist_main.files; cur_file++)
1559  {
1560   flush_kbd();
1561   if(fetch_keystrokes())
1562   {
1563    msg_cprintf(H_PROMPT, M_OK_TO_QUIT);
1564    if(query_action())
1565    {
1566     msg_cprintf(H_OPER, M_QUITTING);
1567     exit(REARJ_ERL_WARNING);
1568    }
1569   }
1570   retrieve_entry(src_name, &flist_main, cur_file);
1571   ts_store(&timestamp, OS, file_getftime(src_name));
1572   if((!pick_newer||!ts_valid(ts_newer)||ts_cmp(&timestamp, &ts_newer)>=0)&&
1573      (!pick_older||!ts_valid(ts_older)||ts_cmp(&timestamp, &ts_older)<0))
1574   {
1575    cnv_rc=convert_archive(src_name);
1576    if(cnv_rc!=REARJ_ERL_SUCCESS)
1577    {
1578     skip_count++;
1579     log_as_skipped(src_name, cnv_rc);
1580     if(exit_code==REARJ_ERL_SUCCESS&&(!internal_archives_only||cnv_rc!=REARJ_ERL_UNCONFIGURED))
1581      exit_code=cnv_rc;
1582    }
1583    release_dir(tmp_dir);                /* ASR fix 14/11/2000 */
1584    if(file_chdir(work_dir))
1585     error(M_CANT_CHDIR, work_dir);
1586    unlink_all(tmp_dir);
1587    if(file_rmdir(tmp_dir))
1588     msg_cprintf(H_ERR, M_CANT_RMDIR, tmp_dir);
1589    if(file_mkdir(tmp_dir))
1590     error(M_CANT_MKDIR, tmp_dir);
1591   }
1592  }
1593  if(!work_directory_assigned)
1594  {
1595   if(file_rmdir(tmp_dir))
1596    msg_cprintf(H_ERR, M_CANT_RMDIR, tmp_dir);
1597  }
1598  if(tmpdir_malloced)
1599  {
1600   free(tmp_dir);
1601   tmpdir_malloced=0;
1602  }
1603  tmp_dir=NULL;
1604  time(&end_time);
1605  time_diff=sub_time(end_time, start_time);
1606  total_gain=(long)(total_old_fsize-total_new_fsize);
1607  msg_cprintf(H_HL|H_NFMT, M_TOTAL_SECONDS, time_diff);
1608  msg_cprintf(H_HL|H_NFMT, M_TOTAL_CONVERTED, total_files);
1609  msg_cprintf(H_HL|H_NFMT, M_TOTAL_SKIPPED, skip_count);
1610  msg_cprintf(H_HL|H_NFMT, M_OLD_SIZE, total_old_fsize);
1611  msg_cprintf(H_HL|H_NFMT, M_NEW_SIZE, total_new_fsize);
1612  msg_cprintf(H_HL|H_NFMT, M_SAVINGS_SIZE, total_gain);
1613  if(logging_enabled)
1614  {
1615   arj_gettime(&log_ts);
1616   if(fprintf(logstream, M_LOGENTRY_FOOTER, timeseq, archivers[target_type].suffix, total_old_fsize, total_new_fsize, total_gain, time_diff)<=0)
1617    error(M_CANT_WRITE_LOG);
1618   fclose(logstream);
1619  }
1620  flist_cleanup_proc(&flist_main);
1621  flist_cleanup_proc(&flist_exclusion);
1622  return((skip_count>0)?exit_code:REARJ_ERL_SUCCESS);
1623 }
1624