home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume30 / tin / part07 / save.c next >
Encoding:
C/C++ Source or Header  |  1992-05-20  |  25.2 KB  |  1,181 lines

  1. /*
  2.  *  Project   : tin - a threaded Netnews reader
  3.  *  Module    : save.c
  4.  *  Author    : I.Lea & R.Skrenta
  5.  *  Created   : 01-04-91
  6.  *  Updated   : 09-05-92
  7.  *  Notes     :
  8.  *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  9.  *              You may  freely  copy or  redistribute  this software,
  10.  *              so  long as there is no profit made from its use, sale
  11.  *              trade or  reproduction.  You may not change this copy-
  12.  *              right notice, and it must be included in any copy made
  13.  */
  14.  
  15. #include    "tin.h"
  16.  
  17. #define    INITIAL        1
  18. #define MIDDLE        2
  19. #define OFF            3
  20. #define END            4
  21.  
  22. extern int cur_groupnum;
  23.  
  24. int create_subdir = TRUE;
  25. int save_num=0;
  26. int max_save;
  27.  
  28. struct save_t *save;
  29.  
  30.  
  31. /*
  32.  * types of archive programs
  33.  * 0=archiver, 1=extension, 2=extract option, 3=list option
  34.  */
  35.  
  36. struct archiver_t { 
  37.     char *name;
  38.     char *ext;
  39.     char *extract;
  40.     char *list;
  41. };
  42.  
  43. struct archiver_t archiver[] = {
  44.     { "",            "",            "",            "" },
  45.     { "",            "",            "",            "" },
  46.     { "",            "",            "",            "" },
  47.     { "zoo",        "zoo",        "-extract",    "-list" },
  48.     { (char *) 0,    (char *) 0,    (char *) 0,    (char *) 0 }
  49. };
  50.  
  51. extern char *glob_group;
  52. extern char note_h_path[LEN];    /* Path:    */
  53. extern char note_h_date[LEN];    /* Date:    */
  54. extern FILE    *note_fp;            /* the body of the current article */
  55. extern int index_point;
  56. extern int note_end;
  57. extern int note_page;
  58. extern long note_mark[MAX_PAGES];
  59.  
  60.  
  61. /*
  62.  *  Check for articles and say how many new/unread in each group.
  63.  *  or
  64.  *  Start if new/unread articles and return first group with new/unread.
  65.  *  or
  66.  *  Save any new articles to savedir and mark arts read and mail user
  67.  *  and inform how many arts in which groups were saved.
  68.  *  or
  69.  *  Mail any new articles to specified user and mark arts read and mail
  70.  *  user and inform how many arts in which groups were mailed.
  71.  */
  72.  
  73. int check_start_save_any_news (check_start_save)
  74.     int check_start_save;
  75. {
  76. #ifndef INDEX_DAEMON
  77.  
  78.     char buf[LEN], logfile[LEN], *p;
  79.     char group_path[LEN];
  80.     char savefile[LEN];
  81.     extern FILE *note_fp;
  82.     FILE *fp;
  83.     FILE *fp_log = (FILE *) 0;
  84.     int i, j, print_group;
  85.     int check_arts = 0;
  86.     int    log_opened = TRUE;
  87.     int print_first = TRUE;
  88.     int saved_arts = 0;
  89.     int saved_groups = 0;
  90.     int unread_news = FALSE;    
  91.     long epoch;
  92.  
  93.     switch (check_start_save) {
  94.         case CHECK_ANY_NEWS:
  95.             if (verbose) {
  96.                 wait_message (txt_checking_for_news);
  97.             }
  98.             break;
  99.         case START_ANY_NEWS:
  100.             wait_message (txt_checking_for_news);
  101.             break;
  102.         case MAIL_ANY_NEWS:
  103.         case SAVE_ANY_NEWS:
  104.             sprintf (logfile, "%s/log", rcdir);
  105.             if ((fp_log = fopen (logfile, "w")) == NULL) {
  106.                 perror_message (txt_cannot_open, logfile);
  107.                 fp_log = stdout;
  108.                 verbose = FALSE;
  109.                 log_opened = FALSE;
  110.             }
  111.             time (&epoch);
  112.             fprintf (fp_log, "To: %s\n", userid);
  113.             fprintf (fp_log, "Subject: NEWS LOG %s\n", ctime (&epoch));
  114.             break;
  115.     }
  116.     
  117.     for (i = 0; i < group_top; i++) {
  118.         strcpy (group_path, active[my_group[i]].name);
  119.         for (p = group_path; *p; p++) {
  120.             if (*p == '.') {
  121.                 *p = '/';
  122.             }
  123.         }
  124.         
  125.         index_group (active[my_group[i]].name, group_path);
  126.         read_newsrc_line (active[my_group[i]].name);
  127.         print_group = TRUE;
  128.         check_arts = 0;
  129.  
  130.         for (j = 0; j < top; j++) {
  131.             if (arts[j].unread == ART_UNREAD)  {
  132.                 switch (check_start_save) {
  133.                     case CHECK_ANY_NEWS:
  134.                         if (print_first && verbose) {
  135.                             fputc ('\n', stdout);
  136.                             print_first = FALSE;
  137.                         }
  138.                         check_arts++;
  139.                         break;
  140.                     case START_ANY_NEWS:
  141.                         return i;    /* return first group with unread news */ 
  142.                         /* NOTREACHED */
  143.                     case MAIL_ANY_NEWS:
  144.                     case SAVE_ANY_NEWS:
  145.                         if (print_group) {    
  146.                             sprintf (buf, "Saved %s...\n", active[my_group[i]].name);
  147.                             fprintf (fp_log, "%s", buf);
  148.                             if (verbose) {
  149.                                 wait_message (buf);
  150.                             }
  151.                             print_group = FALSE;
  152.                             saved_groups++;
  153.                             if (check_start_save == SAVE_ANY_NEWS) {
  154.                                 sprintf (buf, "%s/dummy", group_path);
  155.                                 create_path (buf);
  156.                             }
  157.                         }
  158.                         sprintf (buf, "[%5ld]  %s\n", arts[j].artnum, arts[j].subject);
  159.                         fprintf (fp_log, "%s", buf);
  160.                         if (verbose) {
  161.                             wait_message (buf);
  162.                         }
  163.                         saved_arts++;
  164.  
  165.                         if (check_start_save == MAIL_ANY_NEWS) {
  166.                             sprintf (savefile, "/tmp/tin.%d", process_id);
  167.                         } else {
  168.                             sprintf (savefile, "%s/%s/%ld", active[my_group[cur_groupnum]].attribute.savedir,
  169.                                      group_path, arts[j].artnum);
  170.                         }
  171.  
  172.                         if ((fp = fopen (savefile, "w")) == NULL) {
  173.                             fprintf (fp_log, txt_cannot_open, savefile);
  174.                             if (verbose) {
  175.                                 perror_message (txt_cannot_open, savefile);
  176.                             }
  177.                             continue;
  178.                         }
  179.                 
  180.                         if (check_start_save == MAIL_ANY_NEWS) {
  181.                             fprintf (fp, "To: %s\n", mail_news_user);
  182.                         }
  183.  
  184.                         note_page = art_open (arts[j].artnum, group_path);    
  185.                         fseek (note_fp, 0L, 0);
  186.                         copy_fp (note_fp, fp, "");
  187.                         art_close ();
  188.                         fclose (fp);
  189.  
  190.                         if (check_start_save == MAIL_ANY_NEWS) {
  191.                             sprintf (buf, "%s \"%s\" < %s", mailer,
  192.                                     mail_news_user, savefile);
  193.                             if (! invoke_cmd (buf)) {
  194.                                 error_message (txt_command_failed_s, buf);
  195.                             }
  196.                             unlink (savefile);
  197.                         }
  198.                         if (catchup) {
  199.                             arts[j].unread = ART_READ;
  200.                         }
  201.                         break;
  202.                 }
  203.             }
  204.         }
  205.         
  206.         if (check_start_save == MAIL_ANY_NEWS ||
  207.             check_start_save == SAVE_ANY_NEWS) {
  208.             if (catchup) {
  209.                 update_newsrc (active[my_group[i]].name, my_group[i], FALSE);
  210.             }
  211.         } else {
  212.             if (check_arts) {
  213.                 if (verbose) {
  214.                     sprintf (buf, "%4d unread articles in %s\n",
  215.                         check_arts, active[my_group[i]].name);
  216.                     wait_message (buf);     
  217.                 }
  218.                 unread_news = TRUE;    
  219.             }
  220.         }
  221.     }
  222.     switch (check_start_save) {
  223.         case CHECK_ANY_NEWS:
  224.             if (unread_news) {
  225.                 return 2;
  226.             } else {
  227.                 if (verbose) {
  228.                     wait_message (txt_there_is_no_news);
  229.                 }
  230.                 return 0;
  231.             }
  232.             /* NOTREACHED */ 
  233.         case START_ANY_NEWS:
  234.             wait_message (txt_there_is_no_news);
  235.             return -1;
  236.             /* NOTREACHED */ 
  237.         case MAIL_ANY_NEWS:
  238.         case SAVE_ANY_NEWS:
  239.             sprintf (buf, "\n%s %d article(s) from %d group(s)\n", 
  240.                 (check_start_save == MAIL_ANY_NEWS ? "Mailed" : "Saved"),
  241.                 saved_arts, saved_groups);
  242.             fprintf (fp_log, "%s", buf);
  243.             if (verbose) {
  244.                 wait_message (buf);
  245.             }
  246.             if (log_opened) {
  247.                 fclose (fp_log);
  248.                 if (verbose) {
  249.                     sprintf (buf, "Mailing log to %s\n",
  250.                         (check_start_save == MAIL_ANY_NEWS ? mail_news_user : userid));
  251.                     wait_message (buf);
  252.                 }
  253.                 sprintf (buf, "%s \"%s\" < %s", mailer,
  254.                     (check_start_save == MAIL_ANY_NEWS ? mail_news_user : userid),
  255.                     logfile);
  256.                 if (! invoke_cmd (buf)) {
  257.                     error_message (txt_command_failed_s, buf);
  258.                 }
  259.             }
  260.             break;
  261.     }
  262.  
  263. #endif /* INDEX_DAEMON */
  264.  
  265.     return 0;
  266. }
  267.  
  268.  
  269. int save_art_to_file (respnum, index, mailbox, filename)
  270.     int respnum;
  271.     int index;
  272.     int mailbox;
  273.     char *filename;
  274. {
  275. #ifndef INDEX_DAEMON
  276.  
  277.     char file[PATH_LEN];
  278.     char save_art_info[LEN];
  279.     FILE *fp;
  280.     int is_mailbox = FALSE;
  281.     int i = 0, ret_code = FALSE;
  282.     long epoch;
  283.     
  284.     if (strlen (filename)) {
  285.         my_strncpy (file, filename, sizeof (file));
  286.         is_mailbox = mailbox;
  287.         i = index;
  288.     } else if (save_archive_name && arts[respnum].archive) {
  289.         my_strncpy (file, arts[respnum].archive, sizeof (file));
  290.     }
  291.  
  292.     if (! append_to_existing_file (i)) {
  293.         save[i].saved = FALSE;
  294.         info_message (txt_art_not_saved);
  295.         sleep (1);
  296.         return (ret_code);
  297.     }
  298.  
  299.     if ((fp = fopen (save_filename (i), "a+")) == NULL) {
  300.         save[i].saved = FALSE;
  301.         info_message (txt_art_not_saved);
  302.         return (ret_code);
  303.     }
  304.  
  305.      time (&epoch);
  306.      fprintf (fp, "From %s %s", note_h_path, ctime (&epoch));
  307.  
  308.     if (fseek (note_fp, 0L, 0) == -1) {
  309.         perror_message ("fseek() error on [%s]", arts[respnum].subject);
  310.     }
  311.     copy_fp (note_fp, fp, "");
  312.     fputc ('\n', fp);
  313.     fclose (fp);
  314.     fseek (note_fp, note_mark[note_page], 0);
  315.  
  316.     save[i].saved = TRUE;
  317.  
  318.     if (filename == (char *) 0) {
  319.         if (is_mailbox) {
  320.             sprintf (save_art_info, txt_saved_to_mailbox, get_first_savefile ());
  321.         } else {
  322.             sprintf (save_art_info, txt_art_saved_to, get_first_savefile ());
  323.         }
  324.         info_message(save_art_info);
  325.     }
  326.  
  327. #endif /* INDEX_DAEMON */
  328.  
  329.     return TRUE;
  330. }
  331.  
  332.  
  333. int save_thread_to_file (is_mailbox, group_path)
  334.     int is_mailbox;
  335.     char *group_path;
  336. {
  337. #ifndef INDEX_DAEMON
  338.  
  339.     char file[PATH_LEN];
  340.     char save_thread_info[LEN];
  341.     char *first_savefile;
  342.     int count = 0;
  343.     int i, ret_code = FALSE;
  344.  
  345.     for (i=0 ; i < save_num ; i++) {
  346.         sprintf (msg, "%s%d", txt_saving, ++count);
  347.         wait_message (msg);
  348.  
  349.         if (is_mailbox) {
  350.             file[0] = 0;
  351.         }else {
  352.             sprintf (file, "%s.%02d", save[i].file, i+1);
  353.         }
  354.  
  355.         note_page = art_open (arts[save[i].index].artnum, group_path);
  356.         ret_code = save_art_to_file (save[i].index, i, is_mailbox, file);
  357.         art_close ();            
  358.     }
  359.     
  360.     first_savefile = get_first_savefile ();
  361.  
  362.     if (first_savefile == (char *) 0) {
  363.         info_message (txt_thread_not_saved);
  364.     } else {
  365.         if (is_mailbox) {
  366.             sprintf (save_thread_info, txt_saved_to_mailbox, first_savefile);
  367.         } else {
  368.             if (save_num == 1) {
  369.                 sprintf (save_thread_info, txt_art_saved_to, first_savefile);
  370.             } else {
  371.                 sprintf (save_thread_info, txt_thread_saved_to_many,
  372.                     first_savefile, get_last_savefile ());
  373.             }
  374.             if (first_savefile != (char *) 0) {
  375.                 free (first_savefile);
  376.                 first_savefile = (char *) 0;
  377.             }
  378.         }
  379.         info_message (save_thread_info);
  380.         sleep (2);
  381.     }
  382.  
  383. #endif /* INDEX_DAEMON */
  384.  
  385.     return TRUE;
  386. }
  387.  
  388.  
  389. int save_regex_arts (is_mailbox, group_path)
  390.     int is_mailbox;
  391.     char *group_path;
  392. {
  393. #ifndef INDEX_DAEMON
  394.  
  395.     char buf[PATH_LEN];
  396.     int i, ret_code = FALSE;     
  397.     
  398.     for (i=0 ; i < save_num ; i++) {
  399.         sprintf(msg, "%s%d", txt_saving, i+1);
  400.         wait_message (msg);
  401.  
  402.         if (is_mailbox) {
  403.             buf[0] = 0;
  404.         }else {
  405.             sprintf (buf, "%s.%02d", save[i].file, i+1);
  406.         }
  407.  
  408.         note_page = art_open (arts[save[i].index].artnum, group_path);
  409.         ret_code = save_art_to_file (save[i].index, i, is_mailbox, buf);
  410.         art_close ();            
  411.     }
  412.  
  413.     if (! save_num) {    
  414.         info_message (txt_no_match);
  415.     } else {
  416.         if (is_mailbox) {
  417.             sprintf (buf, txt_saved_to_mailbox, get_first_savefile ());
  418.         } else {
  419.             sprintf (buf,txt_saved_pattern_to,
  420.                 get_first_savefile (), get_last_savefile ());
  421.         }
  422.         info_message (buf);
  423.     }
  424.  
  425.     return (ret_code);
  426.  
  427. #else
  428.  
  429.     return (FALSE);
  430.     
  431. #endif /* INDEX_DAEMON */
  432. }
  433.  
  434.  
  435. int append_to_existing_file (i)
  436.     int i;
  437. {
  438. #ifndef INDEX_DAEMON
  439.  
  440.     char buf[LEN];
  441.     char *file;
  442.     struct stat st;
  443.  
  444.     if (! save[i].is_mailbox) {
  445.         file = save_filename (i);
  446.         if (stat(file, &st) != -1) {    
  447.             sprintf (buf, txt_append_to_file, file); 
  448.             if (! prompt_yn (LINES, buf, 'n')) {
  449.                 if (file != (char *) 0) {
  450.                     free (file);
  451.                     file = (char *) 0;
  452.                 }
  453.                 return FALSE;
  454.             }
  455.         }
  456.         if (file != (char *) 0) {
  457.             free (file);
  458.             file = (char *) 0;
  459.         }
  460.     }
  461.  
  462. #endif /* INDEX_DAEMON */
  463.     
  464.     return TRUE;
  465. }
  466.  
  467.  
  468. int create_path (path)
  469.     char *path;
  470. {
  471. #ifndef INDEX_DAEMON
  472.  
  473.     char buf[PATH_LEN];
  474.     char group[PATH_LEN];
  475.     char *env = (char *) 0;
  476.     int i, j, len = 0;
  477.     struct stat st;
  478.     
  479.     /*
  480.      * save in mailbox format to ~/Mail/<group.name>
  481.      */
  482.     if (path[0] == '=') {
  483.         return TRUE;
  484.     }
  485.  
  486.     /*
  487.      * if ~/file expand (ie. /usr/homedir/file)
  488.      */
  489.     switch (path[0]) {
  490.         case '~':
  491.             my_strncpy (buf, path+1, sizeof (buf));
  492.             sprintf (path, "%s%s", homedir, buf);
  493.             break;
  494.         case '+':
  495.             my_strncpy (buf, path+1, sizeof (buf));
  496. #ifdef USE_LONG_FILENAMES 
  497.             my_strncpy (group, glob_group, sizeof (group));
  498. #else
  499.             my_strncpy (group, glob_group, 14);
  500. #endif
  501.             /*
  502.              *  convert 1st letter to uppercase
  503.              */
  504.             if (group[0] >= 'a' && group[0] <= 'z') {
  505.                 group[0] = group[0] - 32;
  506.             }
  507.             sprintf (path, "%s/%s/%s", 
  508.                 active[my_group[cur_groupnum]].attribute.savedir,
  509.                 group, buf);
  510.             break;
  511.         case '$':
  512.             for (i = 0 ; isalnum (path[i+1]) ; i++) {
  513.                 buf[i] = path[i+1];
  514.             }
  515.             buf[i] = '\0';
  516.             if (buf[0] == '\0' || (env = (char *) getenv (buf)) == NULL ||
  517.                 (len = strlen (env)) == 0) {
  518.             }
  519.             sprintf (buf, "%s%s%s", env, (path[i+1] != '/' &&
  520.                 env[len-1] != '/') ? "/" : "", &path[i+1]);
  521.             my_strncpy (path, buf, PATH_LEN);
  522.             break;
  523.         case '/':
  524.             break;
  525.         case '.':
  526.             return FALSE;
  527.             /* NOTREACHED */
  528.         default:
  529.             sprintf (buf, "%s/%s", 
  530.                 active[my_group[cur_groupnum]].attribute.savedir, path);
  531.             my_strncpy (path, buf, PATH_LEN);
  532.             break;
  533.     }
  534.  
  535.     /*
  536.      *  create any directories, otherwise check
  537.      *  errno and give appropiate error message
  538.      */
  539.     len = (int) strlen (path);
  540.     
  541.     for (i=0, j=0 ; i < len ; i++, j++) {
  542.         buf[j] = path[i];
  543.         if (i+1 < len && path[i+1] == '/') {
  544.             buf[j+1] = '\0';
  545.             if (stat (buf, &st) == -1) {
  546.                 if (mkdir (buf, 0755) == -1) {
  547.                     perror_message ("Cannot create %s", buf);
  548.                     return FALSE;
  549.                 }
  550.             }
  551.         }
  552.     }
  553.  
  554. #endif /* INDEX_DAEMON */
  555.     
  556.     return FALSE;
  557. }
  558.  
  559.  
  560. int create_sub_dir (i)
  561.     int i;
  562. {
  563. #ifndef INDEX_DAEMON
  564.  
  565.     char dir[LEN];
  566.     struct stat st;
  567.  
  568.     if (! save[i].is_mailbox && save[i].archive) {
  569.         sprintf (dir, "%s/%s", save[i].dir, save[i].archive);
  570.         if (stat (dir, &st) == -1) {
  571.             mkdir (dir, 0755);
  572.             return TRUE;
  573.         }
  574.         if ((st.st_mode & S_IFMT) == S_IFDIR) {
  575.             return TRUE;
  576.         } else {
  577.             return FALSE;
  578.         }
  579.     }
  580.  
  581. #endif /* INDEX_DAEMON */
  582.     
  583.     return FALSE;
  584. }
  585.  
  586. /*
  587.  *  add files to be saved to save array
  588.  */
  589.  
  590. void add_to_save_list (index, article, is_mailbox, path)
  591.     int index;
  592.     struct article_t *article;
  593.     int is_mailbox;
  594.     char *path;
  595. {
  596. #ifndef INDEX_DAEMON
  597.  
  598.     char dir[PATH_LEN];
  599.     char file[PATH_LEN];
  600.     int i;
  601.     
  602.     dir[0] = '\0';
  603.     file[0] = '\0';
  604.  
  605.     if (save_num == max_save-1) {
  606.         expand_save ();
  607.     }
  608.  
  609.     save[save_num].index   = index;
  610.     save[save_num].saved   = FALSE;
  611.     save[save_num].is_mailbox = is_mailbox;
  612.     save[save_num].dir     = (char *) 0;
  613.     save[save_num].file    = (char *) 0;
  614.     save[save_num].archive = (char *) 0;
  615.     save[save_num].part    = (char *) 0;
  616.     save[save_num].patch   = (char *) 0;
  617.  
  618.     save[save_num].subject = str_dup (article->subject);
  619.     if (article->archive) {
  620.         save[save_num].archive = str_dup (article->archive);
  621.     }
  622.     if (article->part) {
  623.         save[save_num].part = str_dup (article->part);
  624.     }
  625.     if (article->patch) {
  626.         save[save_num].patch = str_dup (article->patch);
  627.     }
  628.  
  629.     if (is_mailbox) {
  630.         if ((int) strlen (path) > 1) {
  631.             if (path[0] == '=') {
  632.                 my_strncpy (file, path+1, sizeof (file));
  633.             } else {
  634.                 my_strncpy (file, path, sizeof (file));
  635.             }
  636.         } else {
  637.             my_strncpy (file, glob_group, sizeof (file));
  638.         }
  639.         save[save_num].dir = str_dup (active[my_group[cur_groupnum]].attribute.maildir);
  640.         save[save_num].file = str_dup (file);
  641.     } else {
  642.         if (path[0]) {
  643.             for (i=strlen (path) ; i ; i--) {
  644.                 if (path[i] == '/') {
  645.                     strncpy (dir, path, i);
  646.                     dir[i] = '\0';
  647.                     strcpy (file, path+i+1);
  648.                     break;
  649.                 }
  650.             }
  651.         }
  652.         
  653.         if (dir[0]) {
  654.             save[save_num].dir = str_dup (dir);
  655.         } else {
  656.             save[save_num].dir = str_dup (active[my_group[cur_groupnum]].attribute.savedir);
  657.         }
  658.  
  659.         if (file[0]) {
  660.             save[save_num].file = str_dup (file);
  661.         } else {
  662.             if (path[0]) {
  663.                 save[save_num].file = str_dup (path);
  664.             } else {
  665.                 save[save_num].file = str_dup (save[save_num].archive);
  666.             }
  667.         }
  668.     }
  669.     save_num++;
  670.  
  671. #endif /* INDEX_DAEMON */
  672. }
  673.  
  674. /*
  675.  *  print save array of files to be saved
  676.  */
  677.  
  678. void sort_save_list ()
  679. {
  680.     qsort ((char *) save, save_num, sizeof (struct save_t), save_comp);
  681. }
  682.  
  683. /*
  684.  *  string comparison routine for the qsort()
  685.  *  ie. qsort(array, 5, 32, save_comp);
  686.  */
  687.  
  688. int save_comp (p1, p2)
  689.     char *p1;
  690.     char *p2;
  691. {
  692.     struct save_t *s1 = (struct save_t *) p1;
  693.     struct save_t *s2 = (struct save_t *) p2;
  694.  
  695.     /*
  696.      * Sort on Archive-name: part & patch otherwise Subject: 
  697.      */
  698.     if (s1->archive != (char *) 0) {
  699.         if (s1->part != (char *) 0) {
  700.             if (strcmp (s1->part, s2->part) < 0) {
  701.                 return -1;
  702.             }
  703.             if (strcmp (s1->part, s2->part) > 0) {
  704.                 return 1;
  705.             }
  706.         } else {
  707.             if (strcmp (s1->patch, s2->patch) < 0) {
  708.                 return -1;
  709.             }
  710.             if (strcmp (s1->patch, s2->patch) > 0) {
  711.                 return 1;
  712.             }
  713.         }    
  714.     } else {
  715.         if (strcmp (s1->subject, s2->subject) < 0) {
  716.             return -1;
  717.         }
  718.         if (strcmp (s1->subject, s2->subject) > 0) {
  719.             return 1;
  720.         }
  721.     }
  722.     
  723.     return 0;
  724. }
  725.  
  726.  
  727. char *save_filename (i)
  728.     int i;
  729. {
  730.     char *filename;
  731.  
  732.     filename = (char *) my_malloc (PATH_LEN);
  733.  
  734.     if (save[i].is_mailbox) {
  735.         sprintf (filename, "%s/%s", save[i].dir, save[i].file);
  736.         return (filename);
  737.     }
  738.     
  739.     if (! save_archive_name || (! save[i].part && ! save[i].patch)) {
  740.         if (save_num == 1) {
  741.             sprintf (filename, "%s/%s", save[i].dir, save[i].file);
  742.         } else {
  743.             sprintf (filename, "%s/%s.%02d", save[i].dir, save[i].file, i+1);
  744.         }
  745.     } else {
  746.         if (save[i].part) {
  747.             if (create_sub_dir (i)) {
  748.                 sprintf (filename, "%s/%s/%s.%s%s", save[i].dir, save[i].archive, save[i].archive, LONG_PATH_PART, save[i].part);
  749.             } else {
  750.                 sprintf (filename, "%s/%s.%s%s", save[i].dir, save[i].archive, LONG_PATH_PART, save[i].part);
  751.             }
  752.         } else {
  753.             if (save[i].patch) {
  754.                 if (create_sub_dir (i)) {
  755.                     sprintf (filename, "%s/%s/%s.%s%s", save[i].dir, save[i].archive, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  756.                 } else {
  757.                     sprintf (filename, "%s/%s.%s%s", save[i].dir, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  758.                 }
  759.             } else {
  760.                   sprintf (filename, "%s/%s", save[i].dir, save[i].file);
  761.             }
  762.         }
  763.     }
  764.  
  765.     return (filename);
  766. }
  767.  
  768.  
  769. char *get_first_savefile ()
  770. {
  771.     char *file;
  772.     int i;
  773.  
  774.     for (i=0 ; i < save_num ; i++) {
  775.         if (save[i].saved) {
  776.             file = (char *) my_malloc (PATH_LEN);
  777.             if (save[i].is_mailbox) {
  778.                 sprintf (file, "%s/%s", save[i].dir, save[i].file);
  779.                 return (file);
  780.             } else {
  781.                 if (save[i].archive && save_archive_name) {
  782.                     if (save[i].part) {
  783.                         if (create_subdir) {
  784.                             sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PART, save[i].part);
  785.                         } else {
  786.                             sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PART, save[i].part);
  787.                         }
  788.                     } else {
  789.                         if (create_subdir) {
  790.                             sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  791.                         } else {
  792.                             sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PATCH, save[i].patch);
  793.                         }
  794.                     }
  795.                 } else {
  796.                     if (save_num == 1) {
  797.                         sprintf (file, "%s", save[i].file);
  798.                     } else {
  799.                         sprintf (file, "%s.%02d", save[i].file, i+1);
  800.                     }
  801.                 }
  802.                 return (file);
  803.             }
  804.         }
  805.     }
  806.     return ((char *) 0);
  807. }
  808.  
  809.  
  810. char *get_last_savefile ()
  811. {
  812.     char *file;
  813.     int i;
  814.     
  815.     for (i=save_num-1 ; i >= 0 ; i--) {
  816.         if (save[i].saved) {
  817.             file = (char *) my_malloc (PATH_LEN);
  818.             if (save[i].is_mailbox) {
  819.                 sprintf (file, "%s/%s", save[i].dir, save[i].file);
  820.                 return (file);
  821.             } else {
  822.                 if (save[i].archive && save_archive_name) {
  823.                     if (save[i].part) {
  824.                         if (create_subdir) {
  825.                             sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PART, save[i].part);
  826.                         } else {
  827.                             sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PART, save[i].part);
  828.                         }
  829.                     } else {
  830.                         if (create_subdir) {
  831.                             sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  832.                         } else {
  833.                             sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PATCH, save[i].patch);
  834.                         }
  835.                     }
  836.                 } else {
  837.                     if (save_num == 1) {
  838.                         sprintf (file, "%s", save[i].file);
  839.                     } else {
  840.                         sprintf (file, "%s.%02d", save[i].file, i+1);
  841.                     }
  842.                 }
  843.                 return (file);
  844.             }
  845.         }
  846.     }
  847.     return ((char *) 0);
  848. }
  849.  
  850.  
  851. int post_process_files (proc_type_ch)
  852.     char proc_type_ch;
  853. {
  854.     if (save_num) {
  855.         wait_message (txt_post_processing);
  856.  
  857.         switch (proc_type_ch) {
  858.             case 's':
  859.                 post_process_sh ();
  860.                 break;
  861.                 
  862.             case 'u':
  863.                 post_process_uud (POST_PROC_UUDECODE);
  864.                 break;
  865.  
  866.             case 'U':
  867.                 if (post_proc_type == POST_PROC_UUD_EXT_ZOO) {
  868.                     post_process_uud (POST_PROC_UUD_EXT_ZOO);
  869.                 } else {
  870.                     post_process_uud (POST_PROC_UUD_LST_ZOO);
  871.                 }
  872.                 break;
  873.         }
  874.  
  875.         info_message (txt_post_processing_finished);
  876.         sleep (1);
  877.         return TRUE;
  878.     }
  879.     return FALSE;
  880. }
  881.  
  882.  
  883. void post_process_uud (pp)
  884.     int pp;
  885. {
  886. #ifndef INDEX_DAEMON
  887.  
  888.     char s[LEN], t[LEN], u[LEN];
  889.     char buf[LEN], *file;
  890.     char file_out[PATH_LEN];
  891.     char file_out_dir[PATH_LEN];
  892.     FILE *fp_in, *fp_out;
  893.     int i, state = INITIAL;
  894.     int file_size = 0;
  895.     struct stat st;
  896.     
  897.     t[0] = '\0';
  898.     u[0] = '\0';
  899.  
  900.     my_strncpy (file_out_dir, save_filename (0), 
  901.         sizeof (file_out_dir));
  902.     for (i=strlen(file_out_dir) ; i > 0 ; i--) {
  903.         if (file_out_dir[i] == '/') {
  904.             file_out_dir[i] = '\0';
  905.             break;
  906.         }
  907.     }
  908.  
  909.     sprintf (file_out, "%s/tin.%05d", file_out_dir, process_id);
  910.     
  911.     if ((fp_out = fopen (file_out, "a+")) == NULL) {
  912.         perror_message (txt_cannot_open, file_out);
  913.     }
  914.  
  915.  
  916.     for (i=0 ; i < save_num ; i++) {
  917.         my_strncpy (buf, save_filename (i), sizeof (buf));
  918.  
  919.         if ((fp_in = fopen (buf, "r")) != NULL) {
  920.             if (fgets (s, sizeof s, fp_in) == NULL) {
  921.                 fclose (fp_in);
  922.                 continue;
  923.             }
  924.             while (state != END) { 
  925.                 switch (state) {
  926.                     case INITIAL:
  927.                         if (! strncmp ("begin", s, 5)) {
  928.                             state = MIDDLE;
  929.                             fprintf (fp_out, "%s", s);
  930.                         }
  931.                         break;
  932.  
  933.                     case MIDDLE:
  934.                         if (s[0] == 'M') {
  935.                             fprintf (fp_out, "%s", s);
  936.                         } else if (strncmp("end", s, 3)) {
  937.                             state = OFF;
  938.                         } else { /* end */
  939.                             state = END;
  940.                             if (u[0] != 'M') {
  941.                                 fprintf (fp_out, "%s", u);
  942.                             }
  943.                             if (t[0] != 'M') {
  944.                                 fprintf (fp_out, "%s", t);
  945.                             }
  946.                             fprintf (fp_out, "%s\n", s);
  947.                         }
  948.                         break;
  949.  
  950.                     case OFF:
  951.                         if ((s[0] == 'M') && (t[0] == 'M') && (u[0] == 'M')) {
  952.                             fprintf (fp_out, "%s", u);
  953.                             fprintf (fp_out, "%s", t);
  954.                             fprintf (fp_out, "%s", s);
  955.                             state = MIDDLE;
  956.                         } else if (! strncmp ("end", s, 3)) {
  957.                             state = END;
  958.                             if (u[0] != 'M') {
  959.                                 fprintf (fp_out, "%s", u);
  960.                             }
  961.                             if (t[0] != 'M') {
  962.                                 fprintf (fp_out, "%s", t);
  963.                             }
  964.                             fprintf (fp_out, "%s\n", s);
  965.                         }
  966.                         break;
  967.  
  968.                     case END:
  969.                         break;
  970.  
  971.                     default:
  972.                         fprintf (stderr, "\r\nerror: ASSERT - default state\n");
  973.                         fclose (fp_in);
  974.                         fclose (fp_out);
  975.                         unlink (file_out);
  976.                         return;
  977.                 }
  978.                 strcpy (u,t);
  979.                 strcpy (t,s);
  980.                 /*
  981.                  *  read next line & if error goto next file in save array
  982.                  */
  983.                 if (fgets (s, sizeof s, fp_in) == NULL) {
  984.                     break;
  985.                 }
  986.             }
  987.             fclose (fp_in);
  988.         }
  989.     }
  990.     fclose (fp_out);
  991.  
  992.     /*
  993.      *  uudecode file
  994.      */
  995.     wait_message (txt_uudecoding);
  996.     
  997.     sprintf (buf, "cd %s; uudecode %s", file_out_dir, file_out); 
  998.     if (invoke_cmd (buf)) {
  999.         /*
  1000.          *  sum file
  1001.          */
  1002.         if ((file = get_archive_file (file_out_dir, "*")) != NULL) { 
  1003.             sprintf (buf, "%s %s", DEFAULT_SUM, file); 
  1004.             printf (txt_checksum_of_file, file); 
  1005.             fflush (stdout);
  1006.             if ((fp_in = (FILE *) popen (buf, "r")) == NULL) {
  1007.                 printf ("Cannot execute %s\r\n", buf); 
  1008.                 fflush (stdout);
  1009.             } else {
  1010.                 if (stat (file, &st) != -1) {
  1011.                     file_size = (int) st.st_size;
  1012.                 }
  1013.                 if (fgets (buf, sizeof buf, fp_in) != NULL) {
  1014.                     buf[strlen (buf)-1] = '\0';
  1015.                 }
  1016.                 fclose (fp_in);
  1017.                 printf ("%s  %8d bytes\r\n", buf, file_size); 
  1018.                 fflush (stdout);
  1019.             }
  1020.             if (file != (char *) 0) {
  1021.                 free (file);
  1022.                 file = (char *) 0;
  1023.             }
  1024.         }
  1025.     }
  1026.  
  1027.     if (pp > POST_PROC_UUDECODE) {
  1028.         sprintf (buf, "*.%s", archiver[pp].ext); 
  1029.         if ((file = get_archive_file (file_out_dir, buf)) != NULL) {
  1030.             if (pp == POST_PROC_UUD_EXT_ZOO) {
  1031.                 sprintf (buf, "cd %s; %s %s %s", file_out_dir,
  1032.                     archiver[pp].name, archiver[pp].extract, file);
  1033.                 printf (txt_listing_archive, file); 
  1034.             } else {
  1035.                 sprintf (buf, "cd %s; %s %s %s", file_out_dir,
  1036.                     archiver[pp].name, archiver[pp].list, file);
  1037.                 printf (txt_extracting_archive, file);
  1038.             }
  1039.             fflush (stdout);
  1040.             if (file != (char *) 0) {
  1041.                 free (file);
  1042.                 file = (char *) 0;
  1043.             }
  1044.             if (! invoke_cmd (buf)) {
  1045.                 error_message (txt_post_processing_failed, "");
  1046.             }
  1047.         }
  1048.     }
  1049.     delete_processed_files ();
  1050.  
  1051.     unlink (file_out);
  1052.  
  1053. #endif /* INDEX_DAEMON */
  1054. }
  1055.  
  1056. /*
  1057.  *  Unpack /bin/sh archives
  1058.  */
  1059.  
  1060. void post_process_sh ()
  1061. {
  1062. #ifndef INDEX_DAEMON
  1063.  
  1064.     char buf[LEN];
  1065.     char file_in[PATH_LEN];
  1066.     char file_out[PATH_LEN];
  1067.     char file_out_dir[PATH_LEN];
  1068.     char *ptr1, *ptr2;
  1069.     char sh_pattern_1[16];
  1070.     char sh_pattern_2[16];
  1071.     FILE *fp_in, *fp_out;
  1072.     int found_header;
  1073.     int i, j;
  1074.     int patlen1, patlen2;
  1075.  
  1076.     strcpy (sh_pattern_1, "#! /bin/sh");
  1077.     strcpy (sh_pattern_2, "#!/bin/sh");
  1078.  
  1079.     my_strncpy (file_out_dir, save_filename (0), sizeof (file_out_dir));
  1080.     for (i=strlen(file_out_dir) ; i > 0 ; i--) {
  1081.         if (file_out_dir[i] == '/') {
  1082.             file_out_dir[i] = '\0';
  1083.             break;
  1084.         }
  1085.     }
  1086.  
  1087.     sprintf (file_out, "%s/tin.%05d", file_out_dir, process_id);
  1088.  
  1089.     for (j=0 ; j < save_num ; j++) {
  1090.         my_strncpy (file_in, save_filename (j), sizeof (file_in));
  1091.  
  1092.         printf (txt_extracting_shar, file_in);
  1093.         fflush (stdout);
  1094.  
  1095.         found_header = FALSE;
  1096.         
  1097.         if ((fp_out = fopen (file_out, "w")) != NULL) {
  1098.             if ((fp_in = fopen (file_in, "r")) != NULL) {
  1099.                 ptr1 = sh_pattern_1;
  1100.                 ptr2 = sh_pattern_2;
  1101.                 patlen1 = strlen (sh_pattern_1);
  1102.                 patlen2 = strlen (sh_pattern_2);
  1103.                 while (! feof (fp_in)) {
  1104.                     if (fgets (buf, sizeof buf, fp_in)) {
  1105.                         /*
  1106.                          *  find #!/bin/sh or #! /bin/sh pattern
  1107.                          */
  1108.                         if (!found_header) {
  1109.                             if (str_str (buf, ptr1, patlen1) != 0 ||
  1110.                                 str_str (buf, ptr2, patlen2) != 0) {
  1111.                                 found_header = TRUE;
  1112.                             }
  1113.                         }
  1114.                     
  1115.                         /*
  1116.                          *  Write to temp file
  1117.                          */
  1118.                         if (found_header) {
  1119.                             fputs (buf, fp_out);
  1120.                         }
  1121.                     }
  1122.                 }
  1123.                 fclose (fp_in);
  1124.             }
  1125.             fclose (fp_out);
  1126.  
  1127.             sprintf (buf, "cd %s; sh %s", file_out_dir, file_out); 
  1128.             fputs ("\r\n", stdout);
  1129.             fflush (stdout);
  1130.             Raw (FALSE);
  1131.             invoke_cmd (buf);
  1132.             Raw (TRUE);
  1133.             unlink (file_out);
  1134.         }
  1135.     }
  1136.     delete_processed_files ();
  1137.  
  1138. #endif /* INDEX_DAEMON */
  1139. }
  1140.  
  1141.  
  1142. char *get_archive_file (dir, ext)
  1143.     char *dir;
  1144.     char *ext;
  1145. {
  1146.     char buf[LEN];
  1147.     char *file = (char *) 0;
  1148.     FILE *fp;
  1149.     
  1150.     sprintf (buf, "ls -t %s/%s", dir, ext);
  1151.  
  1152.     if ((fp = (FILE *) popen (buf, "r")) == NULL) {
  1153.         return (char *) 0;
  1154.     }
  1155.  
  1156.     if (fgets (buf, sizeof buf, fp) != NULL) {
  1157.         file = str_dup (buf);
  1158.         file[strlen (file)-1] = '\0';
  1159.     }
  1160.     
  1161.     fclose (fp);
  1162.  
  1163.     return (file);
  1164. }
  1165.  
  1166.  
  1167. void delete_processed_files ()
  1168. {
  1169.     int i;
  1170.  
  1171.     wait_message ("\r\n");
  1172.     
  1173.     if (prompt_yn (LINES, txt_delete_processed_files, 'y')) {
  1174.         wait_message (txt_deleting);
  1175.  
  1176.         for (i=0 ; i < save_num ; i++) {
  1177.             unlink (save_filename (i));
  1178.         }
  1179.     }
  1180. }
  1181.