Commit 287248a0 287248a0e231306e4d53c1fb5e103ac4352ee019 by Sergey Poznyakoff

Implemented.

1 parent f70ddf27
......@@ -17,6 +17,10 @@
#include "mail.h"
static void alias_print __P((char *name));
static void alias_print_group __P((char *name, list_t list));
static int alias_create __P((char *name, list_t *plist));
/*
* a[lias] [alias [address...]]
* g[roup] [alias [address...]]
......@@ -25,7 +29,224 @@
int
mail_alias (int argc, char **argv)
{
fprintf (ofile, "Function not implemented in %s line %d\n",
__FILE__, __LINE__);
return 1;
if (argc == 1)
alias_print(NULL);
else if (argc == 2)
alias_print(argv[1]);
else
{
list_t list;
if (alias_create(argv[1], &list))
return 1;
argc --;
argv ++;
while (--argc)
util_slist_add(&list, *++argv);
}
return 0;
}
typedef struct _alias alias_t;
struct _alias
{
char *name;
list_t list;
};
/* Hash sizes. These are prime numbers, the distance between each
pair of them grows exponentially, starting from 64.
Hopefully no one will need more than 32797 aliases, and even if
someone will, it is easy enough to add more numbers to the sequence. */
size_t hash_size[] =
{
37, 101, 229, 487, 1009, 2039, 4091, 8191, 16411, 32797,
};
/* Maximum number of re-hashes: */
int max_rehash = sizeof (hash_size) / sizeof (hash_size[0]);
alias_t *aliases; /* Table of aliases */
size_t hash_num; /* Index to hash_size table */
static unsigned hash __P((char *name));
static int alias_rehash __P((void));
static alias_t *alias_lookup_or_install __P((char *name, int install));
static void alias_print_group __P((char *name, list_t list));
unsigned
hash(char *name)
{
unsigned i;
for (i = 0; *name; name++) {
i <<= 1;
i ^= *(unsigned char*) name;
}
return i % hash_size[hash_num];
}
int
alias_rehash()
{
alias_t *old_aliases = aliases;
alias_t *ap;
int i;
if (++hash_num >= max_rehash)
{
fprintf(ofile, "alias hash table full\n");
return 1;
}
aliases = calloc(hash_size[hash_num], sizeof (aliases[0]));
if (old_aliases)
{
for (i = 0; i < hash_size[hash_num-1]; i++)
{
if (old_aliases[i].name)
{
ap = alias_lookup_or_install(old_aliases[i].name, 1);
ap->name = old_aliases[i].name;
ap->list = old_aliases[i].list;
}
}
free (old_aliases);
}
return 0;
}
alias_t *
alias_lookup_or_install(char *name, int install)
{
unsigned i, pos;
if (!aliases)
{
if (install)
{
if (alias_rehash())
return NULL;
}
else
return NULL;
}
pos = hash(name);
for (i = pos;;)
{
if (aliases[i].name == NULL)
{
if (install)
return &aliases[i];
}
else if (strcmp(aliases[i].name, name) == 0)
return &aliases[i];
if (++i >= hash_size[hash_num])
i = 0;
if (i == pos)
break;
}
if (!install)
return NULL;
if (alias_rehash())
return NULL;
return alias_lookup_or_install(name, install);
}
int
alias_lookup(char *name, list_t *plist)
{
alias_t *ap = alias_lookup_or_install(name, 0);
if (ap)
{
*plist = ap->list;
return 1;
}
return 0;
}
void
alias_print(char *name)
{
if (!name)
{
int i;
if (!aliases)
return;
for (i = 0; i < hash_size[hash_num]; i++)
{
if (aliases[i].name)
alias_print_group(aliases[i].name, aliases[i].list);
}
}
else
{
list_t list;
if (!alias_lookup(name, &list))
{
fprintf (ofile, "\"%s\": not a group\n", name);
return;
}
alias_print_group(name, list);
}
}
int
alias_create(char *name, list_t *plist)
{
alias_t *ap = alias_lookup_or_install(name, 1);
if (!ap)
return 1;
if (!ap->name)
{
/* new entry */
if (list_create(&ap->list))
return 1;
ap->name = strdup(name);
if (!ap->name)
return 1;
}
*plist = ap->list;
return 0;
}
void
alias_print_group(char *name, list_t list)
{
fprintf(ofile, "%s ", name);
util_slist_print(list, 0);
fprintf(ofile, "\n");
}
void
alias_destroy(char *name)
{
alias_t *alias = alias_lookup_or_install(name, 0);
if (!alias)
return;
free(alias->name);
alias->name = NULL;
util_slist_destroy(&alias->list);
}
char *
alias_expand(char *name)
{
list_t list;
if (!alias_lookup(name, &list))
return strdup (name);
return util_slist_to_string(list, ",");
}
......
......@@ -17,6 +17,8 @@
#include "mail.h"
static list_t alternate_names = NULL;
/*
* alt[ernates] name...
*/
......@@ -24,7 +26,25 @@
int
mail_alt (int argc, char **argv)
{
fprintf (ofile, "Function not implemented in %s line %d\n",
__FILE__, __LINE__);
return 1;
if (argc == 1)
{
if (alternate_names)
{
util_slist_print (alternate_names, 0);
fprintf (ofile, "\n");
}
}
else
{
util_slist_destroy (&alternate_names);
while (--argc)
util_slist_add (&alternate_names, *++argv);
}
return 0;
}
int
mail_is_alt_name (char *name)
{
return util_slist_lookup (alternate_names, name);
}
......
......@@ -25,7 +25,21 @@
int
mail_hold (int argc, char **argv)
{
fprintf (ofile, "Function not implemented in %s line %d\n",
__FILE__, __LINE__);
return 1;
message_t msg;
attribute_t attr;
if (argc > 1)
return util_msglist_command (mail_hold, argc, argv);
else
{
if (mailbox_get_message (mbox, cursor, &msg))
{
fprintf (ofile, "%d: can't get message\n", cursor);
return 1;
}
message_get_attribute (msg, &attr);
attribute_unset_userflag (attr, MAIL_ATTRIBUTE_MBOXED);
}
return 0;
}
......
......@@ -24,7 +24,73 @@
int
mail_mbox (int argc, char **argv)
{
fprintf (ofile, "Function not implemented in %s line %d\n",
__FILE__, __LINE__);
return 1;
message_t msg;
attribute_t attr;
if (argc > 1)
return util_msglist_command (mail_mbox, argc, argv);
else
{
if (mailbox_get_message (mbox, cursor, &msg))
{
fprintf (ofile, "%d: can't get message\n", cursor);
return 1;
}
/* Mark the message */
message_get_attribute (msg, &attr);
attribute_set_userflag (attr, MAIL_ATTRIBUTE_MBOXED);
}
return 0;
}
int
mail_mbox_commit ()
{
int i;
mailbox_t dest_mbox = NULL;
int saved_count = 0;
message_t msg;
attribute_t attr;
for (i = 1; i <= total; i++)
{
if (mailbox_get_message (mbox, i, &msg))
{
fprintf (ofile, "%d: can't get message\n", i);
return 1;
}
message_get_attribute (msg, &attr);
if (attribute_is_userflag (attr, MAIL_ATTRIBUTE_MBOXED))
{
if (!dest_mbox)
{
char *name = getenv ("MBOX");
if (mailbox_create_default (&dest_mbox, name)
|| mailbox_open (dest_mbox,
MU_STREAM_WRITE | MU_STREAM_CREAT))
{
fprintf (ofile, "can't create mailbox %s\n", name);
return 1;
}
}
mailbox_append_message (dest_mbox, msg);
attribute_set_deleted (attr);
saved_count++;
}
}
if (saved_count)
{
url_t url = NULL;
mailbox_get_url (dest_mbox, &url);
fprintf(ofile, "Saved %d messages in %s\n", saved_count,
url_to_string (url));
mailbox_close (dest_mbox);
mailbox_destroy (&dest_mbox);
}
return 0;
}
......
......@@ -25,9 +25,66 @@
*/
int
mail_reply (int argc, char **argv)
mail_reply(int argc, char **argv)
{
fprintf (ofile, "Function not implemented in %s line %d\n",
__FILE__, __LINE__);
if (argc > 1)
return util_msglist_command(mail_reply, argc, argv);
else
{
message_t msg;
header_t hdr;
char *to = NULL, *cc = NULL, *subj = NULL;
char *str;
if (mailbox_get_message(mbox, cursor, &msg))
{
fprintf(ofile, "%d: can't get message\n", cursor);
return 1;
}
message_get_header(msg, &hdr);
to = util_get_sender(cursor, 0);
if (islower(argv[0][0]))
{
/* Add all recepients of the originate letter */
address_t addr = NULL;
size_t i, count = 0;
char buf[512];
header_aget_value(hdr, MU_HEADER_TO, &str);
address_create(&addr, str);
free(str);
address_get_count(addr, &count);
/* Make sure we do not include our alternate names */
for (i = 1; i <= count; i++)
{
address_get_email(addr, i, buf, sizeof(buf), NULL);
if (!mail_is_alt_name(buf))
{
util_strcat(&to, " ");
util_strcat(&to, buf);
}
}
/* Finally, add any Ccs */
header_aget_value(hdr, MU_HEADER_CC, &cc);
}
header_aget_value(hdr, MU_HEADER_SUBJECT, &str);
util_strcat(&subj, "Re: ");
util_strcat(&subj, str);
free(str);
fprintf(ofile, "To: %s\n", to);
if (cc)
fprintf(ofile, "Cc: %s\n", cc);
fprintf(ofile, "Subject: %s\n\n", subj);
return mail_send0(to, cc, NULL, subj);
}
return 1;
}
......
......@@ -24,7 +24,12 @@
int
mail_unalias (int argc, char **argv)
{
fprintf (ofile, "Function not implemented in %s line %d\n",
__FILE__, __LINE__);
return 1;
if (argc == 1)
{
fprintf (ofile, "unalias requires at least one argument\n");
return 1;
}
while (--argc)
alias_destroy (*++argv);
return 0;
}
......