From 4079ff5264e6b1237bd51b0ba4d10f334873b6f4 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Thu, 1 Jul 1999 09:45:12 +0000 Subject: [PATCH] Various patches from last week, including: - new mh/maildir access code. - subscribe/unsubscribe - various fixes. --- attach.c | 6 +- buffy.c | 3 +- copy.c | 6 +- curs_lib.c | 1 + globals.h | 1 + gnupgparse.c | 3 + hdrline.c | 22 ++- init.c | 156 ++++++++++------- init.h | 6 +- lib.c | 64 +++++++ lib.h | 2 + mailbox.h | 11 +- mh.c | 474 +++++++++++++++++++++++++++++++++++---------------- mutt.h | 3 +- mx.c | 187 +++++++++----------- mx.h | 19 ++- parse.c | 3 +- pattern.c | 4 +- pgpkey.c | 3 +- pgppubring.c | 4 +- pop.c | 7 +- postpone.c | 1 + protos.h | 1 + recvattach.c | 15 +- sendlib.c | 2 + 25 files changed, 667 insertions(+), 337 deletions(-) diff --git a/attach.c b/attach.c index f4a0d3b05..ea77dd042 100644 --- a/attach.c +++ b/attach.c @@ -1,5 +1,6 @@ /* * Copyright (C) 1996-8 Michael R. Elkins + * Copyright (C) 1999 Thomas Roessler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -699,9 +700,10 @@ int mutt_save_attachment (FILE *fp, BODY *m, char *path, int flags, HEADER *hdr) chflags |= (ctx.magic == M_MAILDIR ? CH_NOSTATUS : CH_UPDATE); if ((r = _mutt_copy_message (msg->fp, fp, hn, hn->content, 0, chflags)) == 0) mutt_message _("Attachment saved."); - + + mx_commit_message (msg, &ctx); mx_close_message (&msg); - mx_close_mailbox(&ctx); + mx_close_mailbox (&ctx); return r; } else diff --git a/buffy.c b/buffy.c index e28bd1f66..6fa30bf30 100644 --- a/buffy.c +++ b/buffy.c @@ -18,8 +18,9 @@ #include "mutt.h" #include "buffy.h" -#include "mx.h" #include "mailbox.h" +#include "mx.h" + #ifdef USE_IMAP #include "imap.h" #endif diff --git a/copy.c b/copy.c index 369980b3b..ce3e5ba2b 100644 --- a/copy.c +++ b/copy.c @@ -599,8 +599,10 @@ _mutt_append_message (CONTEXT *dest, FILE *fpin, CONTEXT *src, HEADER *hdr, chflags |= CH_FROM; chflags |= (dest->magic == M_MAILDIR ? CH_NOSTATUS : CH_UPDATE); r = _mutt_copy_message (msg->fp, fpin, hdr, body, flags, chflags); - if (mx_close_message (&msg) != 0) - return (-1); + if (mx_commit_message (msg, dest) != 0) + r = -1; + + mx_close_message (&msg); return r; } diff --git a/curs_lib.c b/curs_lib.c index edbe46d23..1cb35d138 100644 --- a/curs_lib.c +++ b/curs_lib.c @@ -300,6 +300,7 @@ int mutt_any_key_to_continue (const char *s) tcsetattr (f, TCSADRAIN, &old); close (f); fputs ("\r\n", stdout); + mutt_clear_error (); return (ch); } diff --git a/globals.h b/globals.h index 800d21136..612d3395d 100644 --- a/globals.h +++ b/globals.h @@ -100,6 +100,7 @@ WHERE LIST *HeaderOrderList INITVAL(0); WHERE LIST *Ignore INITVAL(0); WHERE LIST *UnIgnore INITVAL(0); WHERE LIST *MailLists INITVAL(0); +WHERE LIST *SubscribedLists INITVAL(0); /* bit vector for boolean variables */ #ifdef MAIN_C diff --git a/gnupgparse.c b/gnupgparse.c index b018035aa..4c66b7daf 100644 --- a/gnupgparse.c +++ b/gnupgparse.c @@ -146,6 +146,9 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) case 'r': k->flags |= KEYFLAG_REVOKED; break; + case 'd': + k->flags |= KEYFLAG_DISABLED; + break; case 'n': trust = 1; break; diff --git a/hdrline.c b/hdrline.c index da202e36b..b63b0cd8f 100644 --- a/hdrline.c +++ b/hdrline.c @@ -32,19 +32,27 @@ #include #include -int mutt_is_mail_list (ADDRESS *addr) +static int _mutt_is_mail_list (ADDRESS *addr, LIST *p) { - LIST *p; - if (addr->mailbox) { - for (p = MailLists; p; p = p->next) + for (;p; p = p->next) if (mutt_strncasecmp (addr->mailbox, p->data, mutt_strlen (p->data)) == 0) return 1; } return 0; } +int mutt_is_mail_list (ADDRESS *addr) +{ + return _mutt_is_mail_list (addr, MailLists); +} + +int mutt_is_subscribed_list (ADDRESS *addr) +{ + return _mutt_is_mail_list (addr, SubscribedLists); +} + /* Search for a mailing list in the list of addresses pointed to by adr. * If one is found, print pfx and the name of the list into buf, then * return 1. Otherwise, simply return 0. @@ -54,7 +62,7 @@ check_for_mailing_list (ADDRESS *adr, char *pfx, char *buf, int buflen) { for (; adr; adr = adr->next) { - if (mutt_is_mail_list (adr)) + if (mutt_is_subscribed_list (adr)) { if (pfx && buf && buflen) snprintf (buf, buflen, "%s%s", pfx, mutt_get_name (adr)); @@ -73,7 +81,7 @@ check_for_mailing_list_addr (ADDRESS *adr, char *buf, int buflen) { for (; adr; adr = adr->next) { - if (mutt_is_mail_list (adr)) + if (mutt_is_subscribed_list (adr)) { if (buf && buflen) snprintf (buf, buflen, "%s", adr->mailbox); @@ -88,7 +96,7 @@ static int first_mailing_list (char *buf, size_t buflen, ADDRESS *a) { for (; a; a = a->next) { - if (mutt_is_mail_list (a)) + if (mutt_is_subscribed_list (a)) { mutt_save_path (buf, buflen, a); return 1; diff --git a/init.c b/init.c index bcce6aef1..17405b8e4 100644 --- a/init.c +++ b/init.c @@ -286,112 +286,144 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags) return 0; } -void mutt_add_to_list (LIST **list, BUFFER *inp) +static void add_to_list (LIST **list, const char *str) { LIST *t, *last = NULL; - BUFFER buf; - memset (&buf, 0, sizeof (buf)); - do + /* check to make sure the item is not already on this list */ + for (last = *list; last; last = last->next) { - mutt_extract_token (&buf, inp, 0); - - /* check to make sure the item is not already on this list */ - for (last = *list; last; last = last->next) + if (mutt_strcasecmp (str, last->data) == 0) { - if (mutt_strcasecmp (buf.data, last->data) == 0) - { - /* already on the list, so just ignore it */ - last = NULL; - break; - } - if (!last->next) - break; + /* already on the list, so just ignore it */ + last = NULL; + break; } + if (!last->next) + break; + } - if (!*list || last) + if (!*list || last) + { + t = (LIST *) safe_calloc (1, sizeof (LIST)); + t->data = safe_strdup (str); + if (last) { - t = (LIST *) safe_calloc (1, sizeof (LIST)); - t->data = buf.data; - memset (&buf, 0, sizeof (buf)); - if (last) - { - last->next = t; - last = last->next; - } - else - *list = last = t; + last->next = t; + last = last->next; } + else + *list = last = t; } - while (MoreArgs (inp)); - FREE (&buf.data); } -static void remove_from_list (LIST **l, BUFFER *inp) +static void remove_from_list (LIST **l, const char *str) { LIST *p, *last = NULL; - BUFFER buf; - memset (&buf, 0, sizeof (buf)); - do + if (mutt_strcmp ("*", str) == 0) + mutt_free_list (l); /* ``unCMD *'' means delete all current entries */ + else { - mutt_extract_token (&buf, inp, 0); - - if (mutt_strcmp ("*", buf.data) == 0) - mutt_free_list (l); /* ``unCMD *'' means delete all current entries */ - else + p = *l; + last = NULL; + while (p) { - p = *l; - last = NULL; - while (p) + if (mutt_strcasecmp (str, p->data) == 0) { - if (mutt_strcasecmp (buf.data, p->data) == 0) - { - safe_free ((void **) &p->data); - if (last) - last->next = p->next; - else - (*l) = p->next; - safe_free ((void **) &p); - } + safe_free ((void **) &p->data); + if (last) + last->next = p->next; else - { - last = p; - p = p->next; - } + (*l) = p->next; + safe_free ((void **) &p); + } + else + { + last = p; + p = p->next; } } } - while (MoreArgs (inp)); - FREE (&buf.data); } static int parse_unignore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { - mutt_add_to_list (&UnIgnore, s); - remove_from_list (&Ignore, s); + do + { + mutt_extract_token (buf, s, 0); + add_to_list (&UnIgnore, buf->data); + remove_from_list (&Ignore, buf->data); + } + while (MoreArgs (s)); + return 0; } static int parse_ignore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { - mutt_add_to_list (&Ignore, s); - remove_from_list (&UnIgnore, s); + do + { + mutt_extract_token (buf, s, 0); + remove_from_list (&UnIgnore, buf->data); + add_to_list (&Ignore, buf->data); + } + while (MoreArgs (s)); + return 0; } static int parse_list (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { - mutt_add_to_list ((LIST **) data, s); + do + { + mutt_extract_token (buf, s, 0); + add_to_list ((LIST **) data, buf->data); + } + while (MoreArgs (s)); + return 0; } static int parse_unlist (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { - remove_from_list ((LIST **) data, s); + do + { + mutt_extract_token (buf, s, 0); + remove_from_list ((LIST **) data, buf->data); + } + while (MoreArgs (s)); + return 0; } + +static int parse_unlists (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +{ + do + { + mutt_extract_token (buf, s, 0); + remove_from_list (&MailLists, buf->data); + remove_from_list (&SubscribedLists, buf->data); + } + while (MoreArgs (s)); + + return 0; +} + +static int parse_subscribe (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +{ + do + { + mutt_extract_token (buf, s, 0); + add_to_list (&MailLists, buf->data); + add_to_list (&SubscribedLists, buf->data); + } + while (MoreArgs (s)); + + return 0; +} + static int parse_unalias (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { ALIAS *tmp, *last = NULL; diff --git a/init.h b/init.h index caac6b43c..23fc67488 100644 --- a/init.h +++ b/init.h @@ -340,6 +340,7 @@ const struct mapping_t SortKeyMethods[] = { static int parse_list (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_unlist (BUFFER *, BUFFER *, unsigned long, BUFFER *); +static int parse_unlists (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_alias (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_unalias (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_ignore (BUFFER *, BUFFER *, unsigned long, BUFFER *); @@ -348,6 +349,7 @@ static int parse_source (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_set (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_my_hdr (BUFFER *, BUFFER *, unsigned long, BUFFER *); static int parse_unmy_hdr (BUFFER *, BUFFER *, unsigned long, BUFFER *); +static int parse_subscribe (BUFFER *, BUFFER *, unsigned long, BUFFER *); struct command_t { @@ -388,14 +390,16 @@ struct command_t Commands[] = { { "send-hook", mutt_parse_hook, M_SENDHOOK }, { "set", parse_set, 0 }, { "source", parse_source, 0 }, + { "subscribe", parse_subscribe, 0 }, { "toggle", parse_set, M_SET_INV }, { "unalias", parse_unalias, 0 }, { "unhdr_order", parse_unlist, UL &HeaderOrderList }, { "unignore", parse_unignore, 0 }, - { "unlists", parse_unlist, UL &MailLists }, + { "unlists", parse_unlists, 0 }, { "unmono", mutt_parse_unmono, 0 }, { "unmy_hdr", parse_unmy_hdr, 0 }, { "unscore", mutt_parse_unscore, 0 }, { "unset", parse_set, M_SET_UNSET }, + { "unsubscribe", parse_unlist, UL &SubscribedLists }, { NULL } }; diff --git a/lib.c b/lib.c index 6607014f9..d5ecdb0ae 100644 --- a/lib.c +++ b/lib.c @@ -119,6 +119,17 @@ void safe_free (void **p) } } +int safe_fclose (FILE **f) +{ + int r = 0; + + if (*f) + r = fclose (*f); + + *f = NULL; + return r; +} + char *safe_strdup (const char *s) { char *p; @@ -254,6 +265,59 @@ int safe_symlink(const char *oldpath, const char *newpath) return 0; } +/* + * This function is supposed to do nfs-safe renaming of files. + * + * Warning: We don't check whether src and target are equal. + */ + +int safe_rename (const char *src, const char *target) +{ + struct stat ssb, tsb; + + if (!src || !target) + return -1; + + if (link (src, target) != 0) + { + return -1; + } + + /* + * Stat both links and check if they are equal. + */ + + if (stat (src, &ssb) == -1) + { + return -1; + } + + if (stat (target, &tsb) == -1) + { + return -1; + } + + /* + * pretend that the link failed because the target file + * did already exist. + */ + + if (compare_stat (&ssb, &tsb) == -1) + { + errno = EEXIST; + return -1; + } + + /* + * Unlink the original link. Should we really ignore the return + * value here? XXX + */ + + unlink (src); + + return 0; +} + int safe_open (const char *path, int flags) { struct stat osb, nsb; diff --git a/lib.h b/lib.h index eb7a99192..c628663c3 100644 --- a/lib.h +++ b/lib.h @@ -107,6 +107,8 @@ int mutt_strncasecmp (const char *, const char *, size_t); int mutt_strncmp (const char *, const char *, size_t); int safe_open (const char *, int); int safe_symlink (const char *, const char *); +int safe_rename (const char *, const char *); +int safe_fclose (FILE **); size_t mutt_quote_filename (char *, size_t, const char *); size_t mutt_strlen (const char *); diff --git a/mailbox.h b/mailbox.h index 66e747382..183f55c7f 100644 --- a/mailbox.h +++ b/mailbox.h @@ -16,6 +16,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifndef _MAILBOX_H +#define _MAILBOX_H + /* flags for mutt_open_mailbox() */ #define M_NOSORT (1<<0) /* do not sort the mailbox after opening it */ #define M_APPEND (1<<1) /* open mailbox for appending messages */ @@ -36,10 +39,7 @@ enum typedef struct { FILE *fp; /* pointer to the message data */ -#ifdef USE_IMAP - CONTEXT *ctx; /* context (mailbox) for this message */ char *path; /* path to temp file */ -#endif /* USE_IMAP */ short magic; /* type of mailbox this message belongs to */ short write; /* nonzero if message is open for writing */ } MESSAGE; @@ -53,7 +53,8 @@ void mx_fastclose_mailbox (CONTEXT *); int mx_close_mailbox (CONTEXT *); int mx_sync_mailbox (CONTEXT *); -int mx_close_message (MESSAGE **msg); +int mx_commit_message (MESSAGE *, CONTEXT *); +int mx_close_message (MESSAGE **); int mx_get_magic (const char *); int mx_set_magic (const char *); int mx_check_mailbox (CONTEXT *, int *); @@ -61,3 +62,5 @@ int mx_check_mailbox (CONTEXT *, int *); int mx_is_imap (const char *); #endif + +#endif diff --git a/mh.c b/mh.c index 5b398b501..5281247b0 100644 --- a/mh.c +++ b/mh.c @@ -1,5 +1,6 @@ /* * Copyright (C) 1996-8 Michael R. Elkins + * Copyright (C) 1999 Thomas Roessler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,8 +23,8 @@ */ #include "mutt.h" -#include "mx.h" #include "mailbox.h" +#include "mx.h" #include "copy.h" #include "buffy.h" #include "sort.h" @@ -32,10 +33,16 @@ #include #include #include +#include + +#include +#include #include #include #include + + struct maildir { HEADER *h; @@ -327,30 +334,77 @@ int maildir_read_dir (CONTEXT * ctx) return 0; } -/* Open a new (unique) message in a maildir mailbox. In order to avoid the - * need for locks, the filename is generated in such a way that it is unique, - * even over NFS: