home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / nn.tar / nn-6.5.1 / save.c < prev    next >
C/C++ Source or Header  |  1995-04-29  |  19KB  |  788 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Save (or print) articles
  5.  */
  6.  
  7. #include <signal.h>
  8. #include <errno.h>
  9. #include "config.h"
  10. #include "keymap.h"
  11. #include "nn_term.h"
  12. #include "news.h"
  13.  
  14. /* save.c */
  15.  
  16. static char *ckdir_path __APROTO((char *name));
  17. static mkdirs_in_path __APROTO((char *name, char *start));
  18.  
  19. export char *default_save_file = "+$F";
  20. export char *folder_save_file = NULL;
  21. export int suggest_save_file = 1;
  22. export char *unshar_header_file = "Unshar.Headers";
  23. export int  use_mail_folders = 0;
  24. export int  use_path_in_from = 0;
  25. export int  use_mmdf_folders = 0;
  26. export int  save_report = 1;
  27. export int  quick_save = 0;
  28. export int  conf_append = 0;
  29. export int  conf_create = 1;
  30. export int  folder_format_check = 1;
  31.  
  32. export char *saved_header_escape = "~";
  33.  
  34. export char *print_header_lines = "FDGS";
  35. export char *save_header_lines = "FDNS";
  36. static char *short_header_lines;
  37.  
  38. export char *save_counter_format = "%d";    /* format of save counter */
  39. export int  save_counter_offset = 0;
  40.  
  41. export char printer[FILENAME] = DEFAULT_PRINTER;
  42. export int edit_print_command = 1;
  43.  
  44. export char patch_command[FILENAME] = "patch -p0";
  45. export int edit_patch_command = 1;
  46.  
  47. export char unshar_command[FILENAME] = SHELL;
  48. export int edit_unshar_command = 0;
  49.  
  50. extern int file_completion();
  51.  
  52. import char *temp_file;
  53. import int  shell_restrictions;
  54. import char delayed_msg[];
  55.  
  56. import int current_folder_type;
  57.  
  58. import int rot13_active;
  59.  
  60. extern char *ctime();
  61.  
  62. static int save_mode;
  63. static char *unshar_cmd;
  64.  
  65. #define    HEADER_HANDLING    0x0f    /* what should we do with the header */
  66.  
  67. #define NO_HEADER    0    /* save without a header */
  68. #define SHORT_HEADER    1    /* save with partial header */
  69. #define    FULL_HEADER    2    /* save with full header */
  70. #define    SHORT_HEADER_DG    3    /* save with partial header (digest) */
  71.  
  72. export int print_header_type = SHORT_HEADER;
  73.  
  74. #define    SEPARATE_FILES    0x0100    /* save as separate files */
  75. #define UNIQUE_FILES    0x0200    /* save in unique files */
  76. #define    FILE_IS_NEW    0x0400    /* this is a new file */
  77. #define APPEND_ARTNUM    0x0800    /* append article number to file name */
  78. #define    IS_PIPE        0x1000    /* output is on pipe */
  79. #define    DO_UNSHAR    0x2000    /* unshar article (or patch) */
  80. #define    DO_PATCH    0x4000    /* patch article */
  81. #define    DO_DECODE    0x8000    /* uudecode article */
  82.  
  83. /* open modes for open_news_article for the various HEADER_HANDLINGs */
  84.  
  85. static int open_mode[] = {
  86.     SKIP_HEADER,
  87.     FILL_NEWS_HEADER | SKIP_HEADER | GET_ALL_FIELDS,
  88.     0,
  89.     FILL_NEWS_HEADER | FILL_DIGEST_HEADER | SKIP_HEADER | GET_ALL_FIELDS
  90. };
  91.  
  92. static FILE *save_file;            /* output stream for saved files */
  93. static char *save_name;            /* save file name */
  94.  
  95. static int uniq_counter;        /* separate files counter */
  96. static char uniq_format[FILENAME];     /* sprintf format for '*' expansion */
  97.  
  98. static char last_dir[FILENAME] = "";
  99.  
  100. /*
  101.  * return pointer to first path name component, that does not exist
  102.  */
  103.  
  104. static char *ckdir_path(name)
  105. char *name;
  106. {
  107.     char *slash;
  108.     char *component;
  109.  
  110.     component = name;
  111.  
  112.     while ((slash = strchr(component, '/'))) {
  113.     if (slash == component) {
  114.         /*  ...//...  */
  115.         component++;
  116.         continue;
  117.     }
  118.     *slash = NUL;
  119.     if (file_exist(name, "drx")) {
  120.         *slash++ = '/';
  121.         component = slash;
  122.         continue;
  123.     }
  124.     if (file_exist(name, (char *)NULL)) {
  125.         *slash = '/';
  126.         return NULL;
  127.     }
  128.     *slash = '/';
  129.     break;
  130.     }
  131.     return component;
  132. }
  133.  
  134. /*
  135.  * create directories in path name, starting from start
  136.  */
  137.  
  138. static int
  139. mkdirs_in_path(name, start)
  140. char *name, *start;
  141. {
  142.     char *slash;
  143.     char *component;
  144.  
  145.     component = start;
  146.  
  147.     while ((slash = strchr(component, '/'))) {
  148.     if (slash == component) {
  149.         /*  ...//...  */
  150.         component++;
  151.         continue;
  152.     }
  153.     *slash = NUL;
  154.     if (mkdir(name, 0755)) {
  155.         msg("Cannot make %s/", name);
  156.         *slash = '/';
  157.         return 0;
  158.     }
  159.     *slash++ = '/';
  160.     component = slash;
  161.     }
  162.     return 1;
  163. }
  164.  
  165. void
  166. set_folder_type(name)
  167. char *name;
  168. {        
  169.     FILE *f;
  170.  
  171.     current_folder_type = -1;
  172.     if (!folder_format_check) return;
  173.  
  174.     if ((f = open_file(name, OPEN_READ)) != NULL) {
  175.     get_folder_type(f);
  176.     fclose(f);
  177.     }
  178. }
  179.  
  180. char *init_save(command, mode_textp)
  181. char command;
  182. char **mode_textp;
  183. {
  184.     char *mode_text;
  185.     static char last_input[FILENAME] = "";
  186.     static char name_buf[512];    /* buffer for file name & command expansion */
  187.     char *start, *last, *np;
  188.  
  189.     uniq_counter = 0;
  190.     short_header_lines = save_header_lines;
  191.  
  192.     switch (command) {
  193.  
  194.      case K_SAVE_FULL_HEADER:
  195.     save_mode = FULL_HEADER;
  196.     mode_text = "Save";
  197.     goto cont_save;
  198.  
  199.      case K_SAVE_SHORT_HEADER:
  200.     save_mode = SHORT_HEADER;
  201.     mode_text = "Output";
  202.     goto cont_save;
  203.  
  204.      case K_SAVE_NO_HEADER:
  205.     save_mode = NO_HEADER;
  206.     mode_text = "Write";
  207.  
  208.      cont_save:
  209.     if (quick_save && (current_group->group_flag & G_FOLDER) == 0) {
  210.         if (current_group->save_file)
  211.         save_name = current_group->save_file;
  212.         else
  213.         save_name = default_save_file;
  214.         strcpy(last_input, save_name);
  215.         save_name = last_input;
  216.     } else {
  217.         prompt("\1%s on\1 (+~|) ", mode_text);
  218.  
  219.         save_name = current_group->save_file;
  220.         if (save_name == NULL && suggest_save_file)
  221.         save_name = (current_group->group_flag & G_FOLDER) ?
  222.             folder_save_file : default_save_file;
  223.         if (save_name != NULL) {
  224.         if (!expand_file_name(name_buf, save_name, 2)) return NULL;
  225.         save_name = name_buf;
  226.         }
  227.  
  228.         save_name = get_s(last_input, save_name, NONE, file_completion);
  229.         if (save_name == NULL || *save_name == NUL) return NULL;
  230.  
  231.         if (save_name[1] == NUL && save_name[0] == '+')
  232.         save_name = (current_group->group_flag & G_FOLDER) ?
  233.             folder_save_file : default_save_file;
  234.         else
  235.         if (current_group->save_file == NULL ||
  236.             strcmp(save_name, current_group->save_file))
  237.             strcpy(last_input, save_name);
  238.         if (save_name == NULL || *save_name == NUL) return NULL;
  239.     }
  240.  
  241.     if (*save_name == '|') {
  242.         if (shell_restrictions) {
  243.         msg("Restricted operation - pipes not allowed");
  244.         return NULL;
  245.         }
  246.         mode_text = "Pipe";
  247.         save_name++;
  248.         save_mode |= IS_PIPE;
  249.         if (*save_name == '|') {
  250.         save_mode |= SEPARATE_FILES;
  251.         save_name++;
  252.         }
  253.     }
  254.  
  255.     if (!expand_file_name(name_buf, save_name, (save_mode & IS_PIPE) ? 11 : 3))
  256.         return NULL;
  257.     save_name = name_buf;
  258.  
  259.     if ((save_mode & IS_PIPE) == 0) {
  260.         np = strrchr(save_name, '*');
  261.         if (np != NULL) {
  262.         *np = NUL;
  263.         sprintf(uniq_format, "%s%s%s",
  264.             save_name, save_counter_format, np + 1);
  265.         *np = '*';
  266.         save_mode |= SEPARATE_FILES | UNIQUE_FILES;
  267.         } else {
  268.         np = strrchr(save_name, '$');
  269.         if (np != NULL && np[1] == 'N') {
  270.             if (current_group->group_flag & G_FOLDER) {
  271.             msg("$N is not defined in a folder");
  272.             return NULL;
  273.             }
  274.             *np = NUL;
  275.             sprintf(uniq_format, "%s%%ld%s", save_name, np + 2);
  276.             *np = '$';
  277.             save_mode |= SEPARATE_FILES | APPEND_ARTNUM;
  278.         }
  279.         }
  280.     }
  281.     break;
  282.  
  283.      case K_UUDECODE:
  284.     save_mode = NO_HEADER | DO_UNSHAR | DO_DECODE;
  285.     mode_text = "Decode";
  286.     goto unshar1;
  287.  
  288.      case K_PATCH:
  289.     save_mode = NO_HEADER | SEPARATE_FILES | DO_UNSHAR | DO_PATCH;
  290.     mode_text = "Patch";
  291.     if (!shell_restrictions && edit_patch_command) {
  292.         prompt("\1Patch command:\1 ");
  293.         save_name = get_s(NONE, patch_command, NONE, NULL_FCT);
  294.         if (save_name == NULL || *save_name == NUL) return NULL;
  295.         strcpy(patch_command, save_name);
  296.     }
  297.     unshar_cmd = patch_command;
  298.     goto unshar1;
  299.  
  300.      case K_UNSHAR:
  301.     save_mode = NO_HEADER | SEPARATE_FILES | DO_UNSHAR;
  302.     mode_text = "Unshar";
  303.     if (!shell_restrictions && edit_unshar_command) {
  304.         prompt("\1Unshar command:\1 ");
  305.         save_name = get_s(NONE, unshar_command, NONE, NULL_FCT);
  306.         if (save_name == NULL || *save_name == NUL) return NULL;
  307.         strcpy(unshar_command, save_name);
  308.     }
  309.     unshar_cmd = unshar_command;
  310.  
  311.      unshar1:
  312.     prompt("\1%s Directory:\1 ", mode_text);
  313.     save_name = current_group->save_file;
  314.     if (save_name != NULL) {
  315.         if (!expand_file_name(name_buf, save_name, 10)) return NULL;
  316.         save_name = name_buf;
  317.     }
  318.  
  319.     save_name = get_s(last_dir, save_name, NONE, file_completion);
  320.     if (save_name == NULL || *save_name == NUL) return NULL;
  321.     strcpy(last_dir, save_name);
  322.     if (!expand_file_name(name_buf, save_name, 1))
  323.         return NULL;
  324.     save_name = name_buf;
  325.     break;
  326.  
  327.      case K_PRINT:
  328.     if (print_header_type < NO_HEADER || print_header_type > FULL_HEADER) {
  329.         msg("Invalid 'print-header-type' value %d", print_header_type);
  330.         print_header_type = NO_HEADER;
  331.     }
  332.  
  333.     short_header_lines = print_header_lines;
  334.     save_mode = print_header_type | IS_PIPE;
  335.     
  336.     if (!shell_restrictions && edit_print_command) {
  337.         prompt("\1Print command:\1 ");
  338.         save_name = get_s(NONE, printer, NONE, NULL_FCT);
  339.         if (save_name == NULL || *save_name == NUL) return NULL;
  340.         strcpy(printer, save_name);
  341.     }
  342.     if (!expand_file_name(name_buf, printer, 1))
  343.         return NULL;
  344.     save_name = name_buf;
  345.     mode_text = "Print";
  346.     break;
  347.  
  348.      default:
  349.     msg("Illegal save command: %d", command);
  350.     return NULL;
  351.     }
  352.  
  353.     if (save_name == NULL) return NULL;
  354.  
  355.     if (!(save_mode & IS_PIPE)) {
  356.     if (file_exist(save_name, (save_mode & DO_UNSHAR) ? "wd" : "wf")) {
  357.         if (save_mode & DO_UNSHAR) {
  358.         int len = strlen(save_name);
  359.         if (save_name[len - 1] != '/')
  360.             strcpy(save_name + len, "/");
  361.         } else
  362.         if (conf_append) {
  363.             tprintf("\rAppend to: %s ? ", save_name);
  364.             clrline();
  365.             if (!yes(0)) return NULL;
  366.         }
  367.     } else {
  368.         if (errno != ENOENT) {
  369.         msg("Cannot access %s", save_name);
  370.         return NULL;
  371.         }
  372.  
  373.         if (save_mode & DO_UNSHAR) {
  374.         int len = strlen(save_name);
  375.         if (save_name[len - 1] != '/')
  376.             strcpy(save_name + len, "/");
  377.         }
  378.  
  379.         start = ckdir_path(save_name);
  380.         if (start == NULL) {
  381.         msg("No permission");
  382.         return NULL;
  383.         }
  384.  
  385.         last = strrchr(start, '/');
  386.         /* last != NULL => non-existing directories */
  387.  
  388.         if (conf_create && (!(save_mode & SEPARATE_FILES) || last)) {
  389.         tprintf("\rCreate ");
  390.         for (np = save_name; *np; np++) {
  391.             if (np == start) tputc('\"');
  392.             tputc(*np);
  393.             if ((save_mode & SEPARATE_FILES) && np == last) break;
  394.         }
  395.         tprintf("\" ?");
  396.         clrline();
  397.         if (yes(last != NULL) <= 0) return NULL;
  398.         }
  399.  
  400.         if (last && !mkdirs_in_path(save_name, start))
  401.         return NULL;
  402.     }
  403.     }
  404.  
  405.     if (mode_textp) *mode_textp = mode_text;
  406.  
  407.     save_mode |= FILE_IS_NEW;    /* so save() will open it */
  408.  
  409.     if (save_mode & DO_DECODE) {
  410.     uud_start(save_name);
  411.     save_mode &= ~DO_UNSHAR;
  412.     }
  413.  
  414.     return save_name;
  415. }
  416.  
  417.  
  418. int
  419. save(ah)
  420. article_header *ah;
  421. {
  422.     register FILE *art;
  423.     register c, lcount = 0, mode;
  424.     news_header_buffer hdrbuf;
  425.     news_header_buffer dghdrbuf;
  426.     int was_raw = 0, set_visual = 0;
  427.     char copybuf[FILENAME * 4], uniqbuf[FILENAME];
  428.     flag_type nn_st_flag = A_ST_FILED;
  429.     int with_header;
  430.  
  431.     if (ah->a_group) init_group(ah->a_group);
  432.  
  433.     mode = save_mode & HEADER_HANDLING;
  434.     if (mode == SHORT_HEADER && ah->flag & A_DIGEST)
  435.     mode = SHORT_HEADER_DG;
  436.  
  437.     c = open_mode[mode];
  438.     if (use_mail_folders && use_path_in_from && (c & FILL_NEWS_HEADER) == 0)
  439.     c |= FILL_NEWS_HEADER | GET_ALL_FIELDS;
  440.  
  441.     art = open_news_article(ah, c, hdrbuf, dghdrbuf);
  442.     if (art == NULL) {
  443.     msg("Cannot read %s", group_path_name);
  444.     return 0;
  445.     }
  446.  
  447.     if (save_mode & DO_DECODE) {
  448.     save_file = NULL;
  449.     c = uudecode(ah, art);
  450.     fclose(art);
  451.     return (c < 0) ? 0 : 1;
  452.     }
  453.  
  454.     if (save_mode & UNIQUE_FILES) {
  455.     uniqbuf[0] = NUL;
  456.     do {
  457.         strcpy(copybuf, uniqbuf);
  458.         uniq_counter++;
  459.         sprintf(uniqbuf, uniq_format, uniq_counter + save_counter_offset);
  460.         if (strcmp(uniqbuf, copybuf) == 0) {
  461.         msg("save-counter \"%s\" does not generate unique file names",
  462.             save_counter_format);
  463.         goto fatal;
  464.         }
  465.     } while (file_exist(uniqbuf, (char *)NULL));
  466.     save_name = uniqbuf;
  467.     save_mode |= FILE_IS_NEW;
  468.     } else
  469.     if (save_mode & APPEND_ARTNUM) {
  470.         sprintf(uniqbuf, uniq_format, (long)(ah->a_number));
  471.         save_name = uniqbuf;
  472.     }
  473.  
  474.     if (save_mode & FILE_IS_NEW) {
  475.     if (save_mode & (IS_PIPE | DO_UNSHAR)) {
  476.         set_visual = 1;
  477.         was_raw = visual_off();
  478.     }
  479.  
  480.     if (save_mode & IS_PIPE) {
  481.         if ((save_file = popen(save_name, "w")) == NULL) {
  482.         msg("Cannot pipe to %s", save_name);
  483.         goto fatal;
  484.         }
  485.     } else
  486.     if (save_mode & DO_UNSHAR) {
  487.         if ((save_mode & DO_PATCH) == 0) {
  488.         if (!unshar_position(art))
  489.             goto fatal;
  490.         if (unshar_header_file)
  491.             store_header(ah, art, save_name, unshar_header_file);
  492.         }
  493.  
  494.         new_temp_file();
  495.         sprintf(copybuf,
  496.             "cd %s && { %s 2>&1 ; } | tee %s ; cat %s >> %s.Result ; rm %s",
  497.             save_name != NULL ? save_name : ".", unshar_cmd,
  498.             temp_file, temp_file,
  499.             (save_mode & DO_PATCH) ? "Patch" : "Unshar",
  500.             temp_file);
  501.  
  502.         save_file = popen(copybuf, "w");
  503.         if (save_file == NULL) {
  504.         msg("Cannot exec: '%s'", copybuf);
  505.         goto fatal;
  506.         }
  507.         tprintf("\r\n%s %s\r\n",
  508.            save_mode & DO_PATCH ? "PATCHING FROM" : "UNPACKING",
  509.            ah->subject ? ah->subject : "ARTICLE"); fl;
  510.     } else {
  511.         if ((save_file = open_file(save_name, OPEN_APPEND)) == NULL) {
  512.         msg("Cannot write %s", save_name);
  513.         fclose(art);
  514.         return 0;
  515.         }
  516.         current_folder_type = -1;
  517.         if (ftell(save_file) != (off_t)0) {
  518.         if (mode != NO_HEADER) set_folder_type(save_name);
  519.         save_mode &= ~FILE_IS_NEW;
  520.         }
  521.     }
  522.     }
  523.  
  524.     clrline();
  525.     s_pipe = 0;
  526.  
  527.     with_header = mode != NO_HEADER &&
  528.     (save_mode & (IS_PIPE | DO_UNSHAR)) == 0;
  529.  
  530.     if (with_header)
  531.     mailbox_format(save_file, 1);
  532.  
  533.     if (mode == FULL_HEADER) {
  534.     off_t cnt = ah->fpos - ah->hpos;
  535.     while (--cnt >= 0) {
  536.         if ((c = getc(art)) == EOF) break;
  537.         putc(c, save_file);
  538.     }
  539.     } else
  540.     if (mode == SHORT_HEADER || mode == SHORT_HEADER_DG) {
  541.     char *name, *val;
  542.     scan_header_fields(short_header_lines, ah);
  543.     while (next_header_field(&name, &val, (fct_type *)NULL)) {
  544.         if (name == NULL) continue;
  545.         fprintf(save_file, "%s: %s\n", name, val);
  546.     }
  547.     fputc(NL, save_file);
  548.     }
  549.  
  550.     fflush(save_file);
  551.     if (s_pipe) goto broken_pipe;
  552.  
  553.     lcount = 0;
  554.     while (ftell(art) < ah->lpos && fgets(copybuf, 512, art)) {
  555.     lcount++;
  556.     if (rot13_active) rot13_line(copybuf);
  557.     if (saved_header_escape && with_header && is_header_line(copybuf))
  558.         fputs(saved_header_escape, save_file);
  559.     fputs(copybuf, save_file);
  560.     if (s_pipe) goto broken_pipe;
  561.     }
  562.  
  563.     if (with_header)
  564.     lcount += mailbox_format(save_file, 0);
  565.  
  566. broken_pipe:
  567.     fclose(art);
  568.  
  569.     if (save_mode & DO_UNSHAR) {
  570.     if ((c = pclose(save_file)) != 0) {
  571.         sprintf(delayed_msg, "Save command failed; exit = %d", c);
  572.         nn_st_flag = 0;
  573.     }
  574.     save_file = NULL;
  575.     } else {
  576.     if (s_pipe)
  577.         msg("Command did not read complete article!");
  578.     else
  579.         if (save_report)
  580.         msg((save_mode & IS_PIPE)     ? "%s: %d lines piped" :
  581.         (save_mode & FILE_IS_NEW) ? "%s created: %d lines written" :
  582.         "%s: %d lines appended", save_name, lcount);
  583.  
  584.     if (s_pipe || (save_mode & SEPARATE_FILES)) {
  585.         if (end_save() == 0) goto err;
  586.     } else
  587.         save_mode &= ~FILE_IS_NEW;
  588.     }
  589.  
  590. #ifdef MAIL_READING
  591.     if (mail_auto_delete && (save_mode & IS_PIPE) == 0)
  592.     if (current_group->group_flag & G_MAILBOX)
  593.         if (ah->attr != A_CANCEL)
  594.         fcancel(ah);
  595. #endif
  596.     if (set_visual) visual_on();
  597.     if (was_raw) nn_raw();
  598.  
  599.     ah->flag |= nn_st_flag;
  600.  
  601.     return !s_pipe || (save_mode & SEPARATE_FILES);
  602.  
  603.  fatal:
  604.     fclose(art);
  605.  err:
  606.     if (set_visual) visual_on();
  607.     if (was_raw) nn_raw();
  608.     return 0;
  609. }
  610.  
  611. int
  612. end_save()
  613. {
  614.     int c;
  615.     FILE *sf;
  616.     sf = save_file;
  617.     save_file = NULL;
  618.  
  619.     if (sf) {
  620.     if (save_mode & (IS_PIPE | DO_UNSHAR)) {
  621.         if ((c = pclose(sf)) != 0) {
  622.         if (c >= 256) c >>= 8;    /* HACK */
  623.         sprintf(delayed_msg, "Save command failed; exit = %d", c);
  624.         return 0;
  625.         }
  626.     } else
  627.         if (fclose(sf) == EOF) {
  628.         sprintf(delayed_msg, "Save failed (disk full?)");
  629.         return 0;
  630.         }
  631.     }
  632.  
  633.     if (save_mode & DO_DECODE) {
  634.     uud_end();
  635.     }
  636.     if (save_mode & DO_UNSHAR)
  637.     sprintf(delayed_msg, "Output is saved in %s/%s.Result",
  638.         save_name != NULL ? save_name : ".",
  639.         (save_mode & DO_PATCH) ? "Patch" : "Unshar");
  640.     return 1;
  641. }
  642.  
  643. void
  644. store_header(ah, f, dir, file)
  645. article_header *ah;
  646. FILE *f;
  647. char *dir, *file;
  648. {
  649.     register int c;
  650.     off_t endpos;
  651.     FILE *h;
  652.  
  653.     if (dir != (char *)NULL && file[0] != '/')
  654.     file = relative(dir, file);
  655.     if ((h = open_file(file, OPEN_APPEND)) == NULL) {
  656.     msg("Cannot open %s", file);
  657.     return;
  658.     }
  659.     fseek(h, (off_t)0, 2);
  660.     if (ftell(h) > 0)
  661.     set_folder_type(file);
  662.     else
  663.     current_folder_type = -1;
  664.     if (!use_mmdf_folders && ftell(h) > 0) putc(NL, h);  /* just in case */
  665.     mailbox_format(h, 1);
  666.     endpos = ftell(f) - ah->hpos;
  667.     fseek(f, ah->hpos, 0);
  668.     while (--endpos >= 0 && (c = getc(f)) != EOF)
  669.     putc(c, h);
  670.  
  671.     mailbox_format(h, 0);
  672.     fclose(h);
  673. }
  674.  
  675. int
  676. mailbox_format(f, top)
  677. FILE *f;
  678. int top;
  679. {
  680.     time_t now;
  681.     int do_mmdf, do_mail;
  682.  
  683.     do_mmdf = do_mail = 0;
  684.     switch (current_folder_type) {
  685.      case 0:
  686.     break;
  687.      case 1:
  688.     do_mail = 1;
  689.     break;
  690.      case 2:
  691.     do_mmdf = 1;
  692.     break;
  693.      default:
  694.     do_mmdf = use_mmdf_folders;
  695.     do_mail = use_mail_folders;
  696.     break;
  697.     }
  698.  
  699.     if (do_mmdf) {
  700.     fprintf(f, "\001\001\001\001\n");
  701.     return 0;
  702.     }
  703.  
  704.     if (top == 0) {
  705.     fputc(NL, f);
  706.     return 1;
  707.     }
  708.  
  709.     if (top > 0 && do_mail) {
  710.     now = cur_time();
  711.     fprintf(f, "From %s %s",
  712.         (use_path_in_from && news.ng_path) ? news.ng_path :
  713.         current_group->group_name, ctime(&now));
  714.     return 1;
  715.     }
  716.  
  717.     return 0;
  718. }
  719.  
  720. char *run_mkdir(dir, name_buf)
  721. char *dir, *name_buf;
  722. {
  723.     if (dir == NULL) {
  724.     prompt("\1Directory: \1");
  725.     dir = get_s(last_dir, NONE, NONE, file_completion);
  726.     if (dir == NULL || *dir == NUL) return NULL;
  727.     strcpy(last_dir, dir);
  728.     }
  729.  
  730.     if (*dir == '+' || *dir == '~') {
  731.     if (!expand_file_name(name_buf, dir, 1))
  732.         return NULL;
  733.     dir = name_buf;
  734.     }
  735.  
  736.     if (file_exist(dir, (char *)NULL)) {
  737.     msg("Directory %s already exists", dir);
  738.     return NULL;
  739.     }
  740.  
  741.     if (mkdir(dir, 0755)) {
  742.     msg("Cannot make %s", dir);
  743.     return NULL;
  744.     }
  745.  
  746.     return dir;
  747. }
  748.  
  749. int
  750. change_dir(dir, in_init)
  751. char *dir;
  752. int in_init;
  753. {
  754.     char dir_buf[FILENAME];
  755.  
  756.     if (dir == NULL) {
  757.     prompt("\1Directory: \1");
  758.     dir = get_s(last_dir, NONE, NONE, file_completion);
  759.     }
  760.  
  761.     if (dir == NULL || *dir == NUL) return 0;
  762.  
  763.     strcpy(last_dir, dir);
  764.  
  765.     if (*dir == '+' || *dir == '~') {
  766.     if (!expand_file_name(dir_buf, dir, 1)) return in_init;
  767.     dir = dir_buf;
  768.     }
  769.  
  770.     if (chdir(dir) == 0) {
  771.     if (!in_init) msg("Directory: %s", dir);
  772.     return 0;
  773.     }
  774.  
  775.     if (in_init) return 1;
  776.  
  777.     if (errno == EACCES)
  778.     msg("Cannot access directory %s", dir);
  779.     else {
  780.     /* should ask and create directory here */
  781.     msg("Directory not found: %s", dir);
  782.     }
  783.  
  784.     return 0;
  785. }
  786.  
  787.  
  788.