home *** CD-ROM | disk | FTP | other *** search
- /* @(#)folders.c (c) copyright 10/18/86 (Dan Heller) */
-
- #include "mush.h"
-
- static char oldfolder[MAXPATHLEN];
-
- /* folder %[user] --new mailfile is the spool/mail/login file [user].
- * folder # --new mailfile is the folder previous to the current folder
- * folder & --new mailfile is ~/mbox (or whatever "mbox" is set to)
- * folder +file --new mailfile is in the directory "folder"; name is 'file'
- * folder "path" --full path name or the one in current working directory.
- *
- * in all cases, changes are updated unless a '!' is specified after the
- * folder command (e.g. "f!", "folder !" "fo!" .. all permutations)
- * as usual, if new mail has arrived before the file is copied back, then
- * user will be notified beforehand.
- *
- * RETURN -1 on error -- else return 0. All bits in msg_list are set to true.
- */
- folder(argc, argv, list)
- register char **argv, list[];
- {
- int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
- char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
- struct stat statbuf;
- extern long last_spool_size;
-
- if (ison(glob_flags, IS_PIPE)) {
- print("You can't pipe to the %s command.\n", *argv);
- return -1;
- } else if (ison(glob_flags, IS_SENDING)) {
- print("You can't use the %s command while sending.\n", *argv);
- return -1;
- }
- while (*++argv && (**argv == '-' || **argv == '!'))
- if (!strcmp(*argv, "-?"))
- return help(0, "folder", cmd_help);
- else if (!strcmp(*argv, "-N"))
- no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
- else if (!strcmp(*argv, "-r"))
- do_read_only = 1;
- else if (!strcmp(*argv, "!"))
- turnoff(glob_flags, DO_UPDATE);
-
- if (updating) {
- (void) strcpy(buf, mailfile);
- if (ison(glob_flags, READ_ONLY))
- do_read_only = 1;
- } else {
- if (!*argv) {
- mail_status(0);
- return 0;
- }
- if (!strcmp(*argv, "#"))
- if (!*oldfolder) {
- print("No previous folder\n");
- return -1;
- } else
- newfolder = oldfolder;
- else if (!strcmp(*argv, "&")) {
- if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
- newfolder = DEF_MBOX;
- } else
- newfolder = *argv;
- n = 0;
- tmp = getpath(newfolder, &n);
- if (n == -1) {
- print("%s: %s\n", newfolder, tmp);
- return -1;
- } else if (n == 1) {
- print("%s: is a directory\n", tmp);
- return -1;
- }
- /* strcpy so copyback() below (which calls getpath) doesn't change
- * the data that tmp intended to point to.
- */
- (void) strcpy(buf, tmp);
- }
- if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) {
- error("Unable to read %s", buf);
- return -1;
- }
- /* If the file can't be opened for writing, autoset READ_ONLY */
- if (!(statbuf.st_mode & 0200))
- do_read_only = 1;
- #ifdef SUNTOOL
- if (istool) lock_cursors();
- #endif /* SUNTOOL */
-
- if (!copyback(updating ? "Update folder?" : "Change anyway?")) {
- #ifdef SUNTOOL
- if (istool) unlock_cursors();
- #endif /* SUNTOOL */
- /* an error occured updating the folder */
- return -1;
- }
- if (strcmp(mailfile, buf)) {
- if (!updating)
- (void) strcpy(oldfolder, mailfile);
- strdup(mailfile, buf);
- }
- do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
- last_size = spool_size = 0L;
- while (msg_cnt--) {
- xfree(msg[msg_cnt].m_date_recv);
- xfree(msg[msg_cnt].m_date_sent);
- msg[msg_cnt].m_date_recv = msg[msg_cnt].m_date_sent = NO_STRING;
- }
- msg_cnt = 0, msg[0].m_offset = 0L;
- turnoff(glob_flags, CONT_PRNT);
-
- turnon(glob_flags, IGN_SIGS);
- /* clear the tempfile */
- if (tmpf)
- (void) fclose(tmpf);
- if (!do_read_only) {
- if (!(tmpf = mask_fopen(tempfile, "w"))) {
- error("error truncating %s", tempfile);
- turnoff(glob_flags, IGN_SIGS);
- return -1;
- }
- }
- (void) load_folder(mailfile, TRUE, NULL);
- if (do_read_only && !(tmpf = fopen(mailfile, "r"))) {
- error(mailfile);
- turnoff(glob_flags, IGN_SIGS);
- return -1;
- }
- last_msg_cnt = msg_cnt; /* for check_new_mail */
- (void) mail_size();
- last_spool_size = spool_size; /* prevents bogus "new mail" messages */
- #ifdef SUNTOOL
- if (istool) {
- panel_set(next_scr, PANEL_SHOW_ITEM, FALSE, 0);
- panel_set(prev_scr, PANEL_SHOW_ITEM, FALSE, 0);
- pw_rop(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,PIX_CLR,0,0,0);
- if (!msg_cnt) {
- add_folder_to_menu(folder_item, 3);
- add_folder_to_menu(save_item, 1);
- }
- }
- #endif /* SUNTOOL */
- current_msg = 0;
- turnoff(glob_flags, IGN_SIGS);
-
- /* now sort messages according a user-defined default */
- if (!updating && msg_cnt > 1 && !strcmp(mailfile, spoolfile) &&
- (tmp = do_set(set_options, "sort"))) {
- (void) sprintf(buf, "sort %s", tmp);
- if (argv = make_command(buf, TRPL_NULL, &argc)) {
- /* msg_list can't be null for do_command and since we're not
- * interested in the result, call sort directly
- */
- (void) sort(argc, argv, NULL);
- free_vec(argv);
- }
- }
- turnoff(glob_flags, DO_UPDATE);
-
- /* go to first NEW message */
- while (current_msg < msg_cnt && ison(msg[current_msg].m_flags, OLD))
- current_msg++;
- if (current_msg == msg_cnt)
- /* no new message found -- try first unread message */
- for (current_msg = 0;
- current_msg < msg_cnt && isoff(msg[current_msg].m_flags, UNREAD);
- current_msg++)
- ;
- if (current_msg == msg_cnt)
- current_msg = 0;
-
- if ((!istool || istool && !msg_cnt) && !iscurses)
- mail_status(0);
- /* be quiet if we're piping */
- if ((istool || !updating) && isoff(glob_flags, DO_PIPE) &&
- (istool || !no_hdrs) && msg_cnt)
- (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
- #ifdef SUNTOOL
- if (istool) {
- if (!msg_cnt)
- print("No Mail in %s\n", mailfile);
- if (!getting_opts)
- if (msg_cnt && isoff(glob_flags, IS_GETTING))
- display_msg(current_msg, (long)0);
- else
- do_clear();
- unlock_cursors();
- }
- #endif /* SUNTOOL */
- if (list) {
- clear_msg_list(list);
- bitput(list, list, msg_cnt, =~) /* macro */
- }
- return 0;
- }
-
- folders(argc, argv)
- register char **argv;
- {
- register char *p;
- char buf[128], unused[MAXMSGS_BITS];
-
- if (!(p = do_set(set_options, "folder")) || !*p)
- p = DEF_FOLDER;
- (void) sprintf(buf, "ls %s", p);
- if (argv = make_command(buf, TRPL_NULL, &argc))
- return do_command(argc, argv, unused);
- return -1;
- }
-
- /* merge_folders filename -- concatenate the folder specified by filename
- * to the current folder.
- *
- * RETURN -1 on error -- else return 0. A bit in msg_list is set to true
- * for each of the "new" messages read in to the current folder.
- */
- merge_folders(n, argv, list)
- register char **argv, list[];
- {
- int no_hdrs = 0, newest_msg;
- long orig_offset;
- char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
-
- if (ison(glob_flags, IS_PIPE)) {
- print("You can't pipe to the %s command.\n", *argv);
- return -1;
- } else if (ison(glob_flags, IS_SENDING)) {
- print("You can't use the %s command while sending.\n", *argv);
- return -1;
- }
-
- while (*++argv && **argv == '-')
- if (!strcmp(*argv, "-?"))
- return help(0, "merge", cmd_help);
- else if (!strcmp(*argv, "-N"))
- no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
-
- if (!*argv)
- return 0;
-
- if (ison(glob_flags, READ_ONLY)) {
- print("Folder is read-only.\n");
- return -1;
- }
-
- if (!strcmp(*argv, "#"))
- if (!*oldfolder) {
- print("No previous folder\n");
- return -1;
- } else
- newfolder = oldfolder;
- else if (!strcmp(*argv, "&")) {
- if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
- newfolder = DEF_MBOX;
- } else
- newfolder = *argv;
- n = 0;
- tmp = getpath(newfolder, &n);
- if (n == -1) {
- print("%s: %s\n", newfolder, tmp);
- return -1;
- } else if (n == 1) {
- print("%s: is a directory\n", tmp);
- return -1;
- }
-
- turnon(glob_flags, IGN_SIGS);
- orig_offset = msg[msg_cnt].m_offset;
- (void) load_folder(tmp, 2, list);
- msg[msg_cnt].m_offset = orig_offset;
- newest_msg = last_msg_cnt;
- Debug("newest_msg = %d\n", newest_msg);
- last_msg_cnt = msg_cnt; /* for check_new_mail */
- Debug("msg_cnt = %d\n", msg_cnt);
- (void) mail_size();
- turnoff(glob_flags, IGN_SIGS);
-
- if ((!istool || istool && !msg_cnt)
- && !iscurses && !ison(glob_flags, PRE_CURSES))
- mail_status(0);
- /* be quiet if we're piping or if told not to show headers */
- if ((istool || !no_hdrs) && isoff(glob_flags, DO_PIPE)
- && newest_msg < msg_cnt)
- (void) cmd_line(sprintf(buf, "headers %d", newest_msg + 1), NULL);
- return 0;
- }
-
- /*
- * Undigestify messages. If a message is in digest-format, there are many
- * messages within this message which are to be extracted. Kinda like a
- * folder within a folder. By default, this routine will create a new
- * folder that contains the new messages. -m option will merge the new
- * messages into the current folder.
- */
- do_undigest(n, argv, list)
- char *argv[], list[];
- {
- int r, articles = 0, merge = 0, appending = 0;
- char buf[MAXPATHLEN], cmdbuf[MAXPATHLEN], newlist[MAXMSGS_BITS], *dir, c;
- FILE *fp;
-
- while (argv && *++argv && **argv == '-') {
- n = 1;
- while (c = argv[0][n++])
- switch(c) {
- case 'm':
- if (ison(glob_flags, READ_ONLY)) {
- print("Folder is read only.\n");
- return -1;
- }
- merge++;
- otherwise: return help(0, "undigest", cmd_help);
- }
- }
-
- if ((n = get_msg_list(argv, list)) == -1)
- return -1;
-
- argv += n;
-
- if (*argv) {
- int isdir = 1; /* Ignore file nonexistance errors */
- (void) strcpy(buf, getpath(*argv, &isdir));
- if (isdir < 0) {
- print("%s: %s\n", *argv, buf);
- return -1;
- } else if (isdir == 1) {
- print("%s: is a directory\n", buf);
- return -1;
- }
- } else {
- register char *p, *p2;
- if (Access(dir = ".", W_OK) &&
- !(dir = do_set(set_options, "folder")) &&
- !(dir = do_set(set_options, "tmpdir")))
- alted:
- dir = ALTERNATE_HOME;
- for (n = 0; n < msg_cnt; n++)
- if (msg_bit(list, n))
- break;
-
- if (!(p = header_field(n, "subject")))
- (void) mktemp(sprintf(buf, "%s/digestXXXXX", dir));
- else {
- if (!lcase_strncmp(p, "re: ", 4))
- p += 4;
- for (p2 = p; *p2; p2++)
- if (!isalnum(*p2) && *p2 != '-' && *p2 != '.') {
- *p2 = 0;
- break;
- }
- p2 = buf + Strcpy(buf, dir);
- *p2++ = '/';
- (void) strcpy(p2, p);
- }
- }
-
- if (!Access(buf, W_OK)) {
- fp = mask_fopen(buf, "a");
- appending = (fp > 0);
- } else
- fp = mask_fopen(buf, "w");
- if (!fp) {
- if (!*argv && strcmp(dir, ALTERNATE_HOME))
- goto alted;
- error("can't create %s", buf);
- return -1;
- }
-
- for (n = 0; n < msg_cnt; n++) {
- if (!msg_bit(list, n))
- continue;
-
- print("undigesting message %d\n", n+1);
- /* copy message into file making sure all headers exist. */
- r = undigest(n, fp);
- if (r <= 0)
- break;
- articles += r;
- }
- fclose(fp);
- if (r <= 0) {
- if (!appending)
- unlink(buf);
- return -1;
- }
- if (merge) {
- (void) cmd_line(sprintf(cmdbuf, "\\merge -N %s", buf), newlist);
- (void) unlink(buf);
- print("Merged in %d messages.\n", articles);
- } else
- print("Added %d messages to \"%s\".\n", articles, buf);
- clear_msg_list(list);
- for (n = 0; n < msg_cnt; n++)
- if (msg_bit(newlist, n))
- set_msg_bit(list, n);
- return 0;
- }
-
- /*
- * split digest-message 'n' to file "fp".
- * return number of articles copied or -1 if system error on fputs.
- * A digest is a folder-in-a-message in a special, semi-standard form.
- */
- undigest(n, fp)
- register int n;
- register FILE *fp;
- {
- int art_cnt = 0, on_hdr = -1; /* on_hdr is -1 if hdr not yet found */
- long get_hdr = 0L;
- char from[HDRSIZ], line[HDRSIZ], last_sep[HDRSIZ];
- char from_hdr[256], afrom[256], adate[64];
- char *fdate = "Xxx Xxx 00 00:00:00 0000"; /* Dummy date in ctime form */
- SIGRET (*oldint)(), (*oldquit)();
-
- if (!msg_get(n, from, sizeof from)) {
- error("Unable to find msg %d", n+1);
- return -1;
- }
- #ifndef MSG_SEPARATOR
- else {
- char *p = from + 5;
- skipspaces(0);
- p = index(p, ' ');
- if (p) {
- skipspaces(0);
- fdate = p;
- }
- if (fputs(from, fp) == EOF)
- return -1;
- }
- #endif /* !MSG_SEPARATOR */
-
- on_intr();
- *afrom = *adate = *last_sep = '\0';
- while (ftell(tmpf) < msg[n].m_offset + msg[n].m_size &&
- fgets(line, sizeof (line), tmpf)) {
- if (ison(glob_flags, WAS_INTR))
- goto handle_error;
- if (*line == '\n' && on_hdr > 0) /* blank line -- end of header */
- on_hdr = 0;
-
- /* Check for the beginning of a digest article */
- if (!strncmp(line, "--------", 8)) {
- if (get_hdr) {
- if (do_set(set_options, "warning"))
- wprint("Article with no header? (added to article #%d)\n",
- art_cnt);
- /* Don't start a new message for whatever this is,
- * just fseek back and keep appending to the last one.
- */
- if (fseek(tmpf, get_hdr, L_SET) < 0 ||
- fputs(last_sep, fp) == EOF) {
- art_cnt = -1;
- goto handle_error;
- }
- get_hdr = 0L;
- on_hdr = 0;
- } else {
- (void) strcpy(last_sep, line);
- get_hdr = ftell(tmpf);
- *afrom = *adate = '\0';
- on_hdr = -1; /* Haven't found the new header yet */
- }
- continue;
- }
-
- if (get_hdr) {
- char *p = *line == '>' ? line + 1 : line;
- if (*line == '\n') {
- if (*afrom || *adate) {
- (void) fseek(tmpf, get_hdr, L_SET);
- /* Terminate the previous article */
- art_cnt++;
- #ifdef MSG_SEPARATOR
- #ifdef END_MSG_SEP
- if (fputs(END_MSG_SEP, fp) == EOF) {
- art_cnt = -1;
- goto handle_error;
- }
- #endif /* END_MSG_SEP */
- #ifdef MMDF
- /* MMDF has a newline in MSG_SEPARATOR */
- if (fputs(MSG_SEPARATOR, fp) == EOF)
- #else /* !MMDF */
- /* Other MSG_SEPARATORs need a newline */
- if (fputs(MSG_SEPARATOR, fp) == EOF ||
- fputc('\n', fp) == EOF)
- #endif /* MMDF */
- #else /* !MSG_SEPARATOR */
- /* Everybody else needs a From_ line */
- if (fprintf(fp, "From %s %s", *afrom ? afrom : "unknown",
- *adate ? date_to_ctime(adate) : fdate) == EOF)
- #endif /* MSG_SEPARATOR */
- {
- art_cnt = -1;
- goto handle_error;
- }
- /* Make sure there is a From: without a leading > */
- if (*afrom && *from_hdr && fputs(from_hdr, fp) == EOF) {
- art_cnt = -1;
- goto handle_error;
- }
- get_hdr = 0L;
- } else if (on_hdr < 0)
- /* Skip blanks between "--------" and the hdr */
- get_hdr = ftell(tmpf);
- } else if (on_hdr < 0)
- on_hdr = 1;
- if (on_hdr > 0 && !strncmp(p, "From: ", 6)) {
- (void) get_name_n_addr(p + 6, NULL, afrom);
- (void) no_newln(afrom);
- /* Get the From: minus the leading > */
- if (p != line)
- (void) strcpy(from_hdr, p);
- else /* We don't need From: twice! */
- *from_hdr = '\0';
- } else if (on_hdr > 0 && !strncmp(line, "Date: ", 6)) {
- if (p = parse_date(line+6))
- (void) strcpy(adate, p);
- } else if (on_hdr > 0 && !lcase_strncmp(line, "end", 3)) {
- if (!*afrom && !*adate)
- break;
- }
- } else if (fputs(line, fp) == EOF) {
- /* Pipe broken, out of file space, etc */
- art_cnt = -1;
- goto handle_error;
- }
- }
- ++art_cnt;
- #ifdef END_MSG_SEP
- if (art_cnt > 0 && fputs(END_MSG_SEP, fp) == EOF) {
- art_cnt = -1;
- goto handle_error;
- }
- #endif /* END_MSG_SEP */
- /* If we're still looking for a header, there is some stuff left
- * at the end of the digest. Create an extra article for it.
- */
- if (get_hdr) {
- char *p;
- (void) fseek(tmpf, get_hdr, L_SET);
- if (ftell(tmpf) >= msg[n].m_offset + msg[n].m_size)
- goto handle_error;
- #ifdef MSG_SEPARATOR
- #ifdef MMDF
- if (fputs(MSG_SEPARATOR, fp) == EOF)
- #else /* !MMDF */
- if (fputs(MSG_SEPARATOR, fp) == EOF ||
- fputc('\n', fp) == EOF)
- #endif /* MMDF */
- #else /* !MSG_SEPARATOR */
- if (fputs(from, fp) == EOF)
- #endif /* MSG_SEPARATOR */
- art_cnt = -1;
- if (!(p = header_field(n, "from")))
- p = "Mush-Undigest (Real author unknown)";
- if (fprintf(fp, "From: %s\n", p) == EOF)
- art_cnt = -1;
- if (!(p = header_field(n, "date")))
- p = fdate, no_newln(p);
- if (fprintf(fp, "Date: %s\n", p) == EOF)
- art_cnt = -1;
- if (!(p = header_field(n, "subject")))
- p = "Digest";
- if (fprintf(fp, "Subject: Trailing part of %s\n\n", p) == EOF)
- art_cnt = -1;
- /* header_field() moves the pointer, so seek again */
- (void) fseek(tmpf, get_hdr, L_SET);
- while (art_cnt > 0 && ftell(tmpf) < msg[n].m_offset + msg[n].m_size
- && fgets(line, sizeof (line), tmpf)) {
- if (fputs(line, fp) == EOF)
- art_cnt = -1;
- #ifdef END_MSG_SEP
- if (!strncmp(line, END_MSG_SEP, strlen(END_MSG_SEP)))
- break;
- #endif /* END_MSG_SEP */
- }
- /* The END_MSG_SEP, if any, of the digest will have been output
- * by the while loop above, so we don't need to add one here.
- */
- ++art_cnt;
- }
- handle_error:
- if (art_cnt == -1)
- error("cannot completely undigest");
- else if (ison(glob_flags, WAS_INTR))
- art_cnt = -1;
- off_intr();
- return art_cnt;
- }
-