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