home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
OSKBox.lzh
/
MAILBOX
/
CC
/
mail.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-16
|
20KB
|
936 lines
#include <stdio.h>
#include <ctype.h>
#include <modes.h>
#include <direct.h>
#include <module.h>
#include <dir.h>
#include <errno.h>
#include "mailbox.h"
#define BUFFSIZE 25
int read_event, write_event;
mod_exec *mail_module, *modlink();
struct msg_header *mail_dir, *curdir,
dir_buff[BUFFSIZE], *buff_start, *buff_end;
extern struct userstruct user;
static int passed_count;
int xflag = 0, eflag = 0;
static struct msg_header mail_head, org_head, *mail_ptr;
struct dist_list *distboxes = NULL;
int mail_open = 0;
open_mail ()
{
if (mail_open) return;
if ((read_event = _ev_link ("mail_read")) == -1)
exit (_errmsg (0, "Error %d linking to read event.\n", errno));
if ((write_event = _ev_link ("mail_write")) == -1)
exit (_errmsg (0, "Error %d linking to write event.\n", errno));
if ((int)(mail_module = modlink ("mail_dir", 0x0400)) == -1)
exit (_errmsg (0, "Error %d linking to mail directory module.\n", errno));
mail_dir = (struct msg_header *)((char *)mail_module + mail_module->_mexec);
curdir = mail_dir;
passed_count = -1;
buff_start = buff_end = dir_buff;
mail_open++;
}
reset_mail ()
{
curdir = mail_dir;
buff_start = buff_end = dir_buff;
passed_count = -1;
}
struct msg_header *next_mail (comp, arg, arg2)
int (*comp)(), arg, arg2;
{
char *entry;
int f;
while (get_dir (&mail_head)) {
if ((*comp)(&mail_head, arg, arg2)) {
_strass (&org_head, &mail_head, sizeof (struct msg_header));
return (&mail_head);
}
}
return NULL;
}
get_dir (head)
struct msg_header *head;
{
if (buff_start >= buff_end) {
read_lock ();
buff_start = buff_end = dir_buff;
while (buff_end - buff_start < BUFFSIZE) {
if (curdir - mail_dir >= MAXMAIL) break;
if (curdir->mhstat != ' ')
_strass (buff_end++, curdir, sizeof (struct msg_header));
curdir++;
}
read_unlock ();
}
if (buff_start < buff_end) {
_strass (head, buff_start++, sizeof (struct msg_header));
return (1);
}
else
return (0);
}
read_lock ()
{
_ev_wait (write_event, 0, 0);
_ev_wait (read_event, 0, 9999);
_ev_signal (write_event, 0);
}
read_unlock ()
{
_ev_signal (read_event, 0);
}
write_lock ()
{
_ev_wait (write_event, 0, 0);
_ev_wait (read_event, 0, 0);
}
write_unlock ()
{
int f=0;
struct msg_header *entry;
/* write-through to disk */
for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
if (entry->mhstat != ' ' && entry->mhdirty) {
entry->mhdirty = 0;
if (!f)
f = open ("mail_dir", S_IWRITE);
lseek (f, (char *)entry - (char *)mail_dir, 0);
write (f, entry, sizeof (struct msg_header));
}
if (f) close (f);
_ev_signal (read_event, 0);
_ev_signal (write_event, 0);
}
close_mail ()
{
if (!mail_open) return;
_ev_unlink (read_event);
_ev_unlink (write_event);
if (munlink (mail_module) == -1)
printf ("Error %d unlinking mail directory module.\n", errno);
xflag = eflag = mail_open = 0;
}
struct msg_header *new_mail (number)
{
int max = 0;
struct msg_header *entry;
int time, date, tick;
short day;
write_lock ();
if (number == 0)
{
for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
if (entry->mhstat != ' ' && entry->mhnr > max)
max = entry->mhnr;
number = max+1;
}
for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
if (entry->mhstat == ' ') break;
if (entry - mail_dir == MAXMAIL)
return (NULL); /* no mail entries left */
entry->mhnr = number;
entry->mhstat = 'X';
entry->mhdirty = 1;
_sysdate (0, &time, &date, &day, &tick);
entry->mhdate = entry->mhdate_mod = date;
_julian (&time, &date);
date += 7;
gregorian (&time, &date);
entry->mhdate_xpir = date;
entry->mhtime = time;
entry->mhdist = 0;
entry->mhsize = 0;
_strass (&mail_head, entry, sizeof (struct msg_header));
write_unlock ();
_strass (&org_head, &mail_head, sizeof (struct msg_header));
return (&mail_head);
}
struct msg_header *find_bid (bid)
char *bid;
{
struct msg_header *entry;
read_lock ();
for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
if (entry->mhstat != ' ' && strcmp (bid, entry->mhbid) == 0) {
_strass (&mail_head, entry, sizeof (struct msg_header));
_strass (&org_head, entry, sizeof (struct msg_header));
break;
}
read_unlock ();
return ((entry - mail_dir < MAXMAIL) ? &mail_head : NULL);
}
update_mail ()
{
struct msg_header *entry;
int time, date, tick;
short day;
write_lock ();
for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
if (entry->mhnr == mail_head.mhnr) break;
if (entry - mail_dir >= MAXMAIL) {
write_unlock ();
return (0);
}
if (mail_head.mhtype != org_head.mhtype)
entry->mhtype = mail_head.mhtype;
if (mail_head.mhstat != org_head.mhstat)
entry->mhstat = mail_head.mhstat;
if (mail_head.mhsize != org_head.mhsize)
entry->mhsize = mail_head.mhsize;
if (mail_head.mhdate != org_head.mhdate)
entry->mhdate = mail_head.mhdate;
if (mail_head.mhtime != org_head.mhtime)
entry->mhtime = mail_head.mhtime;
if (mail_head.mhdate_xpir != org_head.mhdate_xpir)
entry->mhdate_xpir = mail_head.mhdate_xpir;
if (strcmp (mail_head.mhto, org_head.mhto))
strcpy (entry->mhto, mail_head.mhto);
if (strcmp (mail_head.mhfrom, org_head.mhfrom))
strcpy (entry->mhfrom, mail_head.mhfrom);
if (strcmp (mail_head.mhbbs, org_head.mhbbs))
strcpy (entry->mhbbs, mail_head.mhbbs);
if (strcmp (mail_head.mhtit, org_head.mhtit))
strcpy (entry->mhtit, mail_head.mhtit);
if (strcmp (mail_head.mhbid, org_head.mhbid))
strcpy (entry->mhbid, mail_head.mhbid);
_sysdate (0, &time, &date, &day, &tick);
entry->mhdate_mod = date;
entry->mhdirty = 1;
_strass (&org_head, entry, sizeof (struct msg_header));
write_unlock ();
return (1);
}
update_dist (head, bit)
struct msg_header *head;
int bit; /* bits are 1 thru 16 or -1 thru -16 */
{
struct msg_header *entry;
char *p1, *p2, *p3;
if (bit == 0) return (0);
write_lock ();
for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
if (entry->mhnr == head->mhnr) break;
if (entry - mail_dir >= MAXMAIL) {
write_unlock ();
return (0);
}
if (bit < 0)
entry->mhdist &= ~(1 << (-bit - 1)); /* remove a bit */
else
entry->mhdist |= 1 << (bit - 1); /* add a bit */
entry->mhdirty = 1;
mail_head.mhdist = org_head.mhdist = entry->mhdist;
write_unlock ();
return (1);
}
rename_file (name, newname)
char *name, *newname;
{
char *argv[4];
int stat;
extern char **environ;
extern int os9fork();
argv[0] = "rename";
argv[1] = name;
argv[2] = newname;
argv[3] = 0;
os9exec (os9fork, argv[0], argv, environ, 0, 0, 3);
wait (&stat);
return ((stat == 0) ? 0 : -1);
}
is_arbitrary (head, func)
struct msg_header *head;
int (*func)();
{
return ((*func) (head));
}
is_private (head)
struct msg_header *head;
{
return (head->mhtype == 'P' &&
strcmp (head->mhfrom, user.uscall) != 0 &&
strcmp (head->mhto, user.uscall) != 0 &&
!(user.usopt & ISSUPER));
}
is_deleted (head)
struct msg_header *head;
{
if (xflag) return 0;
return (head->mhstat == 'X' ||
(head->mhstat == 'H' && !((user.usopt & ISSUPER) ||
(head->mhtype == 'T') ||
(strcmp (head->mhfrom, user.uscall) == 0))));
}
is_to (head, call)
struct msg_header *head;
char *call;
{
if (is_deleted (head) || is_private (head)) return 0;
return (strcmp (head->mhto, call) == 0);
}
is_from (head, call)
struct msg_header *head;
char *call;
{
if (is_deleted (head) || is_private (head)) return 0;
return (strcmp (head->mhfrom, call) == 0);
}
is_at (head, call)
struct msg_header *head;
char *call;
{
char w[10];
if (is_deleted (head) || is_private (head)) return 0;
scanaddr (head->mhbbs, w, 10);
return (strcmp (w, call) == 0);
}
is_mail (head, call)
struct msg_header *head;
char *call;
{
if (is_deleted (head) || is_private (head)) return 0;
return (is_to (head, call) && head->mhstat == 'N');
}
is_new (head)
struct msg_header *head;
{
if (is_deleted (head)) return 0;
return (head->mhstat == 'N' && head->mhtype != 'B');
}
is_nmail (head, call)
struct msg_header *head;
char *call;
{
if (is_deleted (head) || is_private (head)) return 0;
return (is_to (head, call) && head->mhstat == 'Y');
}
is_type (head, type, num)
struct msg_header *head;
{
if (is_deleted (head) || is_private (head)) return 0;
if (head->mhtype != type) return 0;
return (head->mhnr >= num);
}
is_hold (head, num)
struct msg_header *head;
{
if (is_deleted (head) || is_private (head)) return 0;
if (head->mhstat != 'H') return 0;
return (head->mhnr >= num);
}
is_num (head, num)
struct msg_header *head;
{
if ((is_deleted (head) && !(user.usopt & ISSUPER)) ||
is_private (head))
return 0;
return (head->mhnr == num);
}
is_multnum (head, num)
struct msg_header *head;
int num[];
{
int i;
if ((is_deleted (head) && !(user.usopt & ISSUPER)) ||
is_private (head))
return 0;
for (i = 0; num[i] >= 0; i++)
if (num[i] == head->mhnr) return 1;
return (0);
}
is_gnum (head, num)
struct msg_header *head;
{
if (is_deleted (head) || is_private (head)) return 0;
return (head->mhnr >= num);
}
is_forwarded (head, num)
struct msg_header *head;
{
if (is_deleted (head) || is_private (head)) return 0;
if (head->mhnr < num) return 0;
return (head->mhstat == 'F');
}
is_nforwarded (head, num)
struct msg_header *head;
{
if (is_deleted (head) || is_private (head)) return 0;
if (head->mhnr < num) return 0;
return (head->mhstat == 'N' ||
(head->mhstat == 'Y' && strcmp (head->mhto, "WP") == 0));
}
is_read (head, num)
struct msg_header *head;
{
if (is_deleted (head) || is_private (head)) return 0;
if (head->mhnr < num) return 0;
return (head->mhstat == 'Y');
}
is_last (head, num)
struct msg_header *head;
{
struct msg_header *head2;
if (passed_count == -1) {
read_lock ();
for (head2 = mail_dir + MAXMAIL-1; head2 >= mail_dir; head2--)
if (head2->mhstat != ' ' &&
!is_deleted (head2) && !is_private (head2))
if (--num <= 0) break;
read_unlock ();
passed_count = head2->mhnr;
}
return (head->mhnr >= passed_count &&
!is_deleted (head) && !is_private (head));
}
is_title (head, str)
struct msg_header *head;
char *str;
{
if (is_deleted (head) || is_private (head)) return 0;
return (_cmpnam (head->mhtit, str, strlen (str))+1);
}
header_to_name (head, name)
struct msg_header *head;
char *name;
{
sprintf (name, "%06d", head->mhnr);
}
print_header (head, file, flag)
struct msg_header *head;
{
char str[200];
char bbs[7];
int date, time, tick, day;
int jdate, jtime;
char datestr[10];
_sysdate (0, &time, &date, &day, &tick);
_julian (&time, &date);
jdate = head->mhdate; jtime = head->mhtime;
_julian (&jtime, &jdate);
if (date - jdate < 365)
sprintf (datestr, "%02d%02d/%02d%02d",
(head->mhdate >> 8) & 0xff,
head->mhdate & 0xff,
(head->mhtime >> 16) & 0xff,
(head->mhtime >> 8) & 0xff);
else
sprintf (datestr, " %02d/%02d/%02d",
(head->mhdate >> 8) & 0xff,
head->mhdate & 0xff,
(head->mhdate >> 16) % 100);
if (flag) {
sprintf (str, " Msg# TR Size From To @ BBS Date/Time Title\n");
writeln (file, str, strlen (str));
}
scanaddr (head->mhbbs, bbs, 7);
sprintf (str, "%6d %c%c%6d %-6s %-6s %-6s %9s %s\n",
head->mhnr,
head->mhtype,
head->mhstat,
head->mhsize,
head->mhfrom,
head->mhto,
bbs,
datestr,
head->mhtit);
writeln (file, str, strlen (str));
if (eflag) {
sprintf (str, " XPR: %02d/%02d/%02d MOD:%02d/%02d DIST:%04X HROUTE:%s BID:%-12s\n",
(head->mhdate_xpir >> 8) & 0xff,
head->mhdate_xpir & 0xff,
(head->mhdate_xpir >> 16) % 100,
(head->mhdate_mod >> 8) & 0xff,
head->mhdate_mod & 0xff,
head->mhdist,
head->mhbbs,
head->mhbid);
writeln (file, str, strlen (str));
}
}
log (str, a1, a2, a3, a4, a5, a6, a7, a8)
char *str;
{
int f;
char s1[20], s2[100], s3[128];
int date, time, tick;
short day;
_sysdate (0, &time, &date, &day, &tick);
sprintf (s1, "%-6s %02d%02d%02d%02d%02d", user.uscall,
(date >> 16) % 100,
(date >> 8) & 0xff,
date & 0xff,
(time >> 16) & 0xff,
(time >> 8) & 0xff);
sprintf (s2, str, a1, a2, a3, a4, a5, a6, a7, a8);
sprintf (s3, "%s%s\n", s1, s2);
if ((f = open ("logfile", 2)) < 0) return;
lseek (f, 0L, 2);
write (f, s3, strlen (s3));
close (f);
}
log_send (head, fromflag)
struct msg_header *head;
{
char ctl[30];
char fields[3][40];
int count = 0;
strcpy (ctl, "S%c %d %s");
if (*head->mhbbs) {
strcpy (fields[count++], head->mhbbs);
strcat (ctl, " @%s");
}
if (fromflag) {
strcpy (fields[count++], head->mhfrom);
strcat (ctl, " <%s");
}
if (*head->mhbid) {
strcpy (fields[count++], head->mhbid);
strcat (ctl, " $%s");
}
strcat (ctl, " %s");
switch (count) {
case 0: log (ctl, head->mhtype, head->mhnr, head->mhto, head->mhtit);
break;
case 1: log (ctl, head->mhtype, head->mhnr, head->mhto,
fields[0], head->mhtit);
break;
case 2: log (ctl, head->mhtype, head->mhnr, head->mhto,
fields[0], fields[1], head->mhtit);
break;
case 3: log (ctl, head->mhtype, head->mhnr, head->mhto,
fields[0], fields[1], fields[2], head->mhtit);
break;
}
}
get_ssid (call)
char *call;
{
/* strips ssid from callsign and returns its value */
int ssid = 0;
for ( ; *call && *call != '-'; call++)
;
if (*call == '-') {
ssid = atoi (call+1);
*call = '\0';
}
return ssid;
}
open_msg (head)
struct msg_header *head;
{
int f, len;
char name[40];
struct fildes buffer;
char *maildir = "MAIL/";
strcpy (name, maildir);
header_to_name (head, name + strlen (maildir));
if ((f = open (name, 1)) < 0) {
printf ("error %d opening %s.\n", errno, name);
return -1;
}
return f;
}
strncpy (s1, s2, len)
register char *s1, *s2;
register int len;
{
while (*s2 && --len)
*s1++ = *s2++;
*s1 = '\0';
}
strncmp (s1, s2, len)
register char *s1, *s2;
register int len;
{
while (*s1 == *s2 && --len)
s1++, s2++;
return (*s1 - *s2);
}
movmem (from, to, count)
register char *from, *to;
register int count;
{
if (from > to)
while (count--)
*to++ = *from++;
else {
from += count;
to += count;
while (count--)
*--to = *--from;
}
}
char *strchr (str, c)
char *str;
{
while (*str && *str != c)
str++;
return ((*str) ? str : 0);
}
char *strrchr (str, c)
char *str;
{
char *p;
for (p = str; *p; p++) ;
while (p >= str && *p != c)
p--;
return ((p >= str) ? p : 0);
}
bulletin (head)
struct msg_header *head;
{
struct dist_list *dp;
if (head->mhtype == 'T')
return 0;
else if (head->mhtype == 'B')
return 1;
else
{
for (dp = distboxes; dp; dp = dp->dlnext)
if (strcmp (head->mhbbs, dp->dlname) == 0) break;
return (dp != 0);
}
}
callsign (s)
char *s;
{
char *p;
int i;
for (i = 0, p = s; *p; p++) {
if (p - s >= 6)
return 0;
if (isalpha (*p))
continue;
else if (isdigit (*p)) {
if (p == s)
return (callsign (p+1));
if (*(p+1) == '\0')
return 0;
if (++i > 1)
return 0;
}
else
return 0;
}
if (p - s < 4 || i == 0)
return 0;
return 1;
}
read_dist_list ()
{
DIR *dirptr;
struct direct *entry;
char str[80], w[32], *p;
struct dist_list *new;
int f, len;
static char target[] = "*.dis";
if ((dirptr = opendir (DISDIR)) == NULL)
exit (_errmsg (0, "Error %d opening mailbox directory.\n", errno));
while (entry = readdir (dirptr)) {
if (_cmpnam (entry->d_name, target, strlen (target)) == 0) {
sprintf (str, "%s/%s", DISDIR, entry->d_name);
if ((f = open (str, S_IREAD)) < 0) continue;
new = (struct dist_list *)malloc (sizeof (struct dist_list));
new->dlnext = distboxes;
distboxes = new;
strncpy (new->dlname, entry->d_name, 7);
for (p = new->dlname; *p && *p != '.'; p++) ;
*p = '\0';
upper (new->dlname);
for (new->dlcount = 0; len = readln (f, str, 80); new->dlcount++) {
str[len+1] = '\0';
scanword (str, w, 32);
upper (w);
get_ssid (w);
strcpy (new->dlbbs[new->dlcount], w);
}
close (f);
}
}
closedir (dirptr);
}
/*
** Flags the message *head as having been distributed to the mailbox <mbox>.
** Sets appropriate bit in message distribution flag field and, if all bits
** are set, changes the status to 'F'. mail_dir is updated. If the message
** is not addressed to a distribution list designator, returns FALSE,
** otherwise returns TRUE.
*/
checkoff (head, mbox)
struct msg_header *head;
char *mbox;
{
struct dist_list *dp;
int i;
if (*head->mhbbs) {
for (dp = distboxes; dp; dp = dp->dlnext)
if (strcmp (head->mhbbs, dp->dlname) == 0) break;
if (dp) {
for (i = 0; i < dp->dlcount; i++)
if (strcmp (mbox, dp->dlbbs[i]) == 0)
update_dist (head, i+1);
if (head->mhdist == (1 << dp->dlcount) - 1) {
head->mhstat = 'F';
}
/* if (!bulletin (head))
head->mhtype = 'B'; */
update_mail ();
return (1);
}
else
return 0;
}
return (0);
}
creat_msg (head, new_head)
struct msg_header *head, **new_head;
{
char *maildir = "MAIL/";
char str[40], str2[40];
int f;
*new_head = new_mail (0);
(*new_head)->mhsize = head->mhsize;
(*new_head)->mhtype = head->mhtype;
(*new_head)->mhstat = head->mhstat;
strcpy ((*new_head)->mhfrom, head->mhfrom);
strcpy ((*new_head)->mhto, head->mhto);
strcpy ((*new_head)->mhbbs, head->mhbbs);
strcpy ((*new_head)->mhtit, head->mhtit);
strcpy (str, maildir);
strcpy ((*new_head)->mhbid, "");
header_to_name (*new_head, str + strlen (str));
if ((f = create (str, S_IWRITE, S_IOREAD+S_IREAD+S_IWRITE)) == -1) {
return -1;
}
return (f);
}
scanword (s, d, len)
char *s, *d;
{
char *p;
int num = 0;
while (*s && isspace (*s)) {
s++;
num++;
}
p = d;
while (*s && !isspace (*s)) {
if (p - d < len - 1) *p++ = *s;
s++;
num++;
}
*p = '\0';
return (num);
}
scanaddr (s, d, len)
char *s, *d;
{
char *p;
int num = 0;
while (*s && *s == '.') {
s++;
num++;
}
p = d;
while (*s && !(*s == '.')) {
if (p - d < len - 1) *p++ = *s;
s++;
num++;
}
*p = '\0';
return (num);
}
upper (s)
char *s;
{
while (*s) {
*s = toupper (*s);
s++;
}
}
int stricmp (a, b)
register char *a, *b;
{
while (*a && (*a == *b || (*a ^ *b) == ' ' && toupper (*a) == toupper (*b)))
a++, b++;
return (toupper (*a) - toupper (*b));
}
int strnicmp (a, b, len)
register char *a, *b;
register int len;
{
while (--len && *a &&
(*a == *b || (*a ^ *b) == ' ' && toupper (*a) == toupper (*b)) )
a++, b++;
return (toupper (*a) - toupper (*b));
}
parse_head (line, out)
char *line, *out;
{
int field_count = 0;
char *p, *p2, *p3;
int num;
char bbs[80], w[40];
*out = '\0';
if (*line != 'R' || *(line+1) != ':')
return 0;
p = line;
p += scanword (p, w, 40);
p += scanword (p, w, 40);
if (sscanf (w, "%d@%s ", &num, bbs) == 2) {
p2 = out;
*p2++ = 'R';
for (p3 = line+2; p3 < p; )
*p2++ = *p3++;
*p2++ = '\0';
*p2++ = '#';
p2 += sprintf (p2, "%d", num) + 1;
*p2++ = '@';
p2 += sprintf (p2, "%s", bbs) + 1;
*p2++ = '\0';
return (3);
}
p = line;
while (*p) {
if (*p == ':') {
if (field_count) {
out--;
while (isspace (*(out-1))) out--;
*out++ = '\0';
}
*out++ = *(p-1);
p++;
field_count++;
}
else if (field_count)
*out++ = *p++;
else
p++;
}
if (field_count)
while (isspace (*(out-1))) out--;
*out++ = '\0';
*out++ = '\0';
return (field_count);
}
#asm
gregorian:
link.w a5,#0
movem.l d1-d2/a0,-(a7)
move.l a1,-(a7)
movea.l d0,a0
movea.l d1,a1
move.l (a0),d0
move.l (a1),d1
os9 F$Gregor
bcs _sysret
move.l d0,(a0)
move.l d1,(a1)
bra.w _sysret
#endasm
ztime (time, date, weekday)
int *time, *date, *weekday;
{
int oneday = 60 * 60 * 24;
_julian (time, date);
*time += 60 * 60 * UTC;
if (*time >= oneday) {
*time -= oneday;
(*date)++;
*weekday = (*weekday + 1) % 7;
}
gregorian (time, date);
}