home *** CD-ROM | disk | FTP | other *** search
- /*
- * MBMAIL.C - 2/04/89 The message file stuff, except for forwarding.
- */
-
- #include "mb.h"
-
- #define btmax 112 /* Max text in beacon line */
-
- char orgmsg[6], orgbbs[7], orgtime[5], orgdate[7];
-
- char *mbfile, *mbbfile, *msgdir, *bidfile;
-
- char *ufwd; /* Calls with unread msgs, for BT */
- char *bfwd; /* Calls with unread msgs, for forwarding */
-
- short ufwdm, ufwdn, bfwdm, bfwdn;
- short tstaleb, tstalen, tstaleu;
- int bidok, hidok, hasbid, needbid, holdit;
-
- char *mm[num_mm];
- char wpcall[ln_call];
- XBBS *xbbs;
- HOLD *hold;
-
- MAIL_HDR *mfhs;
- MSG_HDR *tmmhs;
-
- FILE *bfl;
-
- int mfl, mflb;
-
- msgfile(p, n)
- char *p;
- word n;
- {
- sprintf(p, "%s%u", msgdir, n);
- }
-
- /*
- * Open file to hold BIDs
- */
-
- opnbid()
- {
- if ((bfl = fopen(bidfile, "a+")) is NULL) { nofile(bidfile); exit(1); }
- fclose(bfl);
- }
-
- /*
- * Write message header.
- */
-
- wt_mmhs()
- {
- if (port->mmhs->rn) write_rec (mfl, port->mmhs->rn, (char *)port->mmhs);
- }
-
-
- /*
- * Get message title.
- */
-
- get_title()
- {
- while(!getdat());
- remnl(port->line);
- strncpy(port->mmhs->title, port->line, mhtitl);
- }
-
- /*
- * Parse the [@ bbs] and [< from] fields of a command.
- */
-
- atfrom(i)
- int i;
- {
- if (*port->fld[i] is '<') pcall(port->mmhs->from, port->fld[i + 1]);
- else if (*port->fld[i] is '@')
- {
- pcall(port->mmhs->bbs, port->fld[i +1]);
- if ((strchr(port->fld[i + 1], '.')) is NULL) return;
- port->mmhs->ext = 2;
- fill (port->mmhs->call, '\0', 125);
- strncpy(port->mmhs->call[0], port->fld[i + 1], 64);
- }
- }
-
- /*
- * Parse the fields of a send command.
- */
-
- pfld()
- {
- hasbid = false;
-
- port->mmhs->type = port->opt2;
- pcall(port->mmhs->to, port->fld[1]);
- strncpy(port->mmhs->from, port->user->call, ln_call);
- fill(port->mmhs->bbs, ' ', ln_call);
- fill(port->mmhs->bid, ' ', ln_bid);
- port->mmhs->ext = 0;
-
- if (port->flds > 3) atfrom(port->flds - 2);
- if (port->flds > 5) atfrom(port->flds - 4);
-
- if (port->flds > 2)
- if(*port->fld[port->flds-1] is '$')
- {
- if (*(port->fld[port->flds - 1] + 1) isnt NULL)
- {
- strncpy(port->mmhs->bid, port->fld[port->flds - 1] + 1, ln_bid);
- hasbid = true;
- }
- if (port->flds > 4) atfrom(port->flds - 3);
- if (port->flds > 6) atfrom(port->flds - 5);
- }
-
- initmsg(true);
- if(!bidok) {
- if (port->user->options & (u_bbs | u_expert)) outstr("Sj:\n");
- else prtx(mm[0]);
- get_title();
- return;
- }
- else {
- if (hasbid) {
- checkbid();
- if (!needbid) {
- outstr("No - Already have it\n");
- sprintf(port->mmhs->title, "<<%6.6s - %s>>",
- port->user->call, port->fld[port->flds-1]);
- wt_mmhs();
- return;
- }
- prtx("OK $C\n");
- get_title();
- return;
- }
- else {
- prtx("OK $C\n");
- get_title();
- needbid = true; /* will check and may assign one later */
- return;
- }
- }
- }
-
- /*
- * Create the header line.
- */
-
- makehdr()
- {
- register char st;
-
- st = 'N';
- if (port->mmhs->stat & m_stale) st = 'O';
- if (port->mmhs->stat & m_fwd) st = 'F';
- if (port->mmhs->stat & m_read) st = 'Y';
- if (port->mmhs->stat & m_hold) st = 'H';
- if (port->mmhs->stat & m_kill) st = 'K';
- if (port->mmhs->stat & m_busy) st = 'B';
- sprintf(tmp->scr,"%5u %c%c %5u %6.6s %6.6s %6.6s %4.4s/%4.4s %s\n",
- port->mmhs->number, port->mmhs->type, st, port->mmhs->size,
- port->mmhs->to, port->mmhs->from, port->mmhs->bbs,
- port->mmhs->date + 2, port->mmhs->time, port->mmhs->title);
- }
-
- /*
- * Write mail.dat header into text file
- */
-
- makehdr2()
- {
- register char st, c;
- int msfl;
- char flags[mmesn];
- fill (flags, ' ',mmesn);
- fill (tmp->scr, '\0', 256);
- tmp->scr[254] = '\r'; tmp->scr[255] = '\n';
- if (port->mmhs->ext is 1)
- {
- for (c=0; c < port->mmhs->count; c++)
- flags[c] = port->mmhs->flag[c] + '0';
- }
- st = 'N';
- if (port->mmhs->stat & m_stale) st = 'O';
- if (port->mmhs->stat & m_fwd) st = 'F';
- if (port->mmhs->stat & m_hold) st = 'H';
- if (port->mmhs->stat & m_read) st = 'Y';
- if (port->mmhs->stat & m_kill) st = 'K';
- sprintf(tmp->scr,
- "%5u %c%c %5u %6.6s %6.6s %6.6s %6.6s %4.4s %-12.12s %5u\r\n",
- port->mmhs->number, port->mmhs->type, st, port->mmhs->size,
- port->mmhs->to, port->mmhs->from, port->mmhs->bbs,
- port->mmhs->date, port->mmhs->time, port->mmhs->bid, port->mmhs->read);
- if (port->mmhs->ext is 2)
- sprintf(tmp->scr+68, "%c %s\r\n%s\r\n", port->mmhs->ext +'0',
- port->mmhs->call, port->mmhs->title);
- else sprintf(tmp->scr+68, "%c %16.16s\r\n%s\r\n", port->mmhs->ext +'0',
- flags, port->mmhs->title);
-
- msgfile(port->cmd, port->mmhs->number);
- if ((msfl = open(port->cmd, O_WRONLY | O_BINARY)) < 0) return;
- write_rec(msfl, 0, (char *)tmp->scr);
- close(msfl);
- }
-
- /*
- * Print a message header.
- */
-
- prthdr(tit)
- int tit;
- {
- char *a, *b;
-
- register short i;
- register short docc;
-
- if (tit) prtx(mm[3]);
- makehdr();
- outstr(tmp->scr);
- if((port->opt1 is'L')and((*port->fld[1]isnt';')and(*port->fld[2]isnt';')))
- return;
- if (port->mmhs->ext is 2)
- {
- outstr(" EF:");
- outstr(port->mmhs->call);
- outchar('\n');
- }
- if (port->mmhs->ext is 1) if (port->mode & ops)
- {
- docc = false;
- for (i = 0; i < port->mmhs->count; i++) if (port->mmhs->flag[i])
- docc = true;
-
- if (docc)
- {
- outstr(" cc:");
- for (i = 0; i < port->mmhs->count; i++)
- {
- if (port->mmhs->flag[i]) outchar(' '); else outstr(" *");
- outnb(port->mmhs->call[i], ln_call);
- }
- outchar('\n');
- }
- }
- if (port->mode & ops) if (*port->mmhs->bid isnt ' ')
- {
- outstr(" BID: ");
- a = port->line;
- b = port->mmhs->bid;
- unbl(a, b, ln_bid);
- outstr(port->line); outchar('\n');
- }
- }
-
- /*
- * Read the message, look for the last bbs header.
- * Set the @ field of the current message to the "at bbs" in that header.
- */
-
- findat()
- {
- register short i;
-
- fill(port->mmhs->bbs, ' ', ln_call);
- msgfile(port->line, port->mmhs->number);
- if ((port->fl = fopen(port->line, "r")) is NULL) { nofile(port->line); return; }
- fseek(port->fl, (long)RECSIZE, 0);
- while(fgets(port->line, linelen, port->fl) isnt NULL)
- {
- if (!parsehd(port->line)) break;
- pcall(port->mmhs->bbs, orgbbs);
- }
- fclose (port->fl);
- }
-
- /*
- * Parse a message header line.
- */
-
- parsehd(in)
- char *in;
- {
- register char *p;
- register int count, n;
-
- if (!ishead(in)) return false;
-
- if ((p = strchr(in, 'R')) is NULL) return false;
- {
- p++;
-
- if (*p is ':') p++;
- if (*p is ' ') p++;
- count = 6;
- n = 0;
- while (*p and count--)
- {
- if (!isalnum(*p)) break;
- orgdate[n++] = *p++;
- }
- orgdate[n] = '\0';
-
- if (*p is '/') p++;
-
- count = 4;
- n = 0;
- while (*p and count--)
- {
- if (!isalnum(*p)) break;
- orgtime[n++] = *p++;
- }
- orgtime[n] = '\0';
- }
-
- if ((p = strchr(in, '@')) is NULL) return false;
- {
- p++;
-
- /* skip colon or a space in @:call OR @ call */
-
- if (*p is ':') p++;
- if (*p is ' ') p++;
- count = ln_call;
- n = 0;
- while (*p and count--)
- {
- if (!isalnum(*p)) break;
- toupper(*p);
- orgbbs[n++] = *p++;
- }
- orgbbs[n] = '\0';
- }
-
- if ((p = strchr(in, '#')) isnt NULL)
- {
- p++;
-
- if (*p is ':') p++;
- if (*p is ' ') p++;
- count = 5;
- n = 0;
- while (*p and count--)
- {
- if (!isalnum(*p)) break;
- orgmsg[n++] = *p++;
- }
- orgmsg[n] = '\0';
- }
- else
- {
- p = strchr(in, '@');
- p--; count = 5;
- while(count-- and *p isnt ' ') p--;
- p++;
- if (*p is '<') p++;
- count = 5;
- n = 0;
- while (*p and count--)
- {
- if (*p is '@') break;
- orgmsg[n++] = *p++;
- }
- orgmsg[n] = '\0';
- }
- return true;
- }
-
-
- /*
- * Find a message given it's number.
- */
-
- findmsg(nr)
- word nr;
- {
- register word i;
-
- for (i = mfhs->last; i; i--)
- {
- read_rec(mfl, i, (char *)port->mmhs);
- if (port->mmhs->number is nr) return true;
- if (port->mmhs->number < nr) return false;
- }
- return false;
- }
-
- /*
- * Create the distribution list, if required.
- */
-
- dodis()
- {
- register FILE *dfl;
- if (port->mmhs->ext is 2) return;
- port->mmhs->ext = 0;
- if (*port->mmhs->bbs is ' ') return;
-
- unbl(tmp->scr, port->mmhs->bbs, ln_call);
-
- strcpy(port->line, msgdir);
- strcat(port->line, tmp->scr);
- strcat(port->line, ".DIS");
-
- if ((dfl = fopen(port->line, "r")) is NULL) return;
-
- port->mmhs->ext = 1 ;
-
- for (port->mmhs->count = 0;
- (port->mmhs->count < mmesn) and (fgets(tmp->scr, scrmax, dfl) isnt NULL);
- port->mmhs->count++)
- {
- strupr(tmp->scr);
- pcall(port->mmhs->call[port->mmhs->count], tmp->scr);
- if(matchn(port->mmhs->call[port->mmhs->count], port->user->call, ln_call))
- port->mmhs->flag[port->mmhs->count] = false;
- else port->mmhs->flag[port->mmhs->count] = true;
- }
- fclose(dfl);
- }
-
- /*
- * Do we hold this message?
- */
-
- ishold(c)
- char *c;
- {
- register HOLD *hp;
-
- for (hp = hold; hp isnt NULL; hp = hp->next)
- if (matchn(hp->call, c, ln_call)) return true;
-
- return false;
- }
-
- /*
- * Create message utilities - initmsg and cremsg.
- * Used by "send message", "make message from file",
- * "kill msg" (service messages), "copy message".
- */
-
- initmsg(h)
- int h;
- {
- if (s_flag & s_dv) begin_lock();
- read_rec(mfl, 0, (char *)mfhs);
-
- port->mmhs->rn = mfhs->next++;
- port->mmhs->number = mfhs->next_msg++;
- port->mmhs->stat = m_busy;
- strncpy(port->mmhs->date, l_date, ln_date);
- strncpy(port->mmhs->time, l_time, ln_time);
- port->mmhs->read = 0;
- port->mmhs->size = 0;
- if(port->mmhs->ext isnt 2) fill(port->mmhs->call, '\0', 125);
- if(h)sprintf(port->mmhs->title, "<<%6.6s -- disconnected>>",port->user->call);
-
-
- /*
- * Clean up the file header.
- */
-
- if (!mfhs->first) mfhs->first = port->mmhs->rn;
- mfhs->last = port->mmhs->rn;
- mfhs->count++;
- write_rec(mfl, 0, (char *)mfhs);
- wt_mmhs();
- mfhs->next_msg--;
- if (s_flag & s_dv) end_lock();
- }
-
- cremsg()
- {
- char *a, *b;
-
- register short i;
- register XBBS *xp;
- register FILE *out;
-
- port->mmhs->stat = 0;
- strncpy(port->mmhs->date, l_date, ln_date);
- strncpy(port->mmhs->time, l_time, ln_time);
- port->mmhs->read = 0;
- port->mmhs->size = filesize;
-
- for (xp = xbbs; xp isnt NULL; xp = xp->next)
- if (wcm(xp->from, port->mmhs->bbs))
- {
- strncpy(port->mmhs->bbs, xp->to, ln_call);
- break;
- }
-
- if (ishold(port->mmhs->to)) port->mmhs->stat = m_hold;
- if (ishold(port->mmhs->from)) port->mmhs->stat = m_hold;
- if (ishold(port->mmhs->bbs)) port->mmhs->stat = m_hold;
-
- if (holdit) port->mmhs->stat = m_hold;
-
- if (*port->mmhs->bid isnt ' ') {
- checkbid();
- if (hasbid) if (!holdit) if (needbid) {
- if ((out = fopen(bidfile,"a")) is NULL) {
- port->msg = mcant; return;
- }
-
- a = port->cmd;
- b = port->mmhs->bid;
- unbl(a, b, ln_bid);
-
- sprintf(port->line, "%4.4s%s\n", port->mmhs->date + 2, port->cmd);
- if (s_flag & s_dv) begin_lock();
- fputs(port->line, out);
- if (s_flag & s_dv) end_lock();
- fclose(out);
- }
- }
- dodis();
-
- if ((port->mmhs->ext is 1) and (*port->mmhs->bid is ' '))
- port->mmhs->stat = m_hold;
-
- wt_mmhs();
- makehdr2();
-
- if (*port->fld[port->flds-1] isnt '$') port->fld[port->flds-1] = nullstr;
-
- sprintf(port->line, "%u %-.6s@%-.6s %s %s", port->mmhs->number,
- port->mmhs->to, port->mmhs->bbs, port->fld[port->flds-1], port->mmhs->title);
-
- log('M', port->opt1, port->opt2, port->line);
- mfhs->next_msg++;
- }
-
- /*
- * Set up the beacon line.
- */
-
- setfwd()
- {
- register char *cp, *lp;
- register short i;
-
- bldfwd();
- if (ufwdm > 1)
- {
- strcpy(port->line, "BT Mail for:");
- cp = ufwd;
- lp = port->line + strlen(port->line);
- while ((cp < ufwd + ln_call * ufwdn) and (lp < port->line + btmax))
- {
- *lp++ = ' ';
- for (i = 0; i < ln_call; i++, cp++) if (*cp isnt ' ') *lp++ = *cp;
- }
- *lp++ = '\n';
- *lp = '\0';
- alltnc(port->line);
- }
- }
-
- /*
- * General permission check: sysop or TO or FROM.
- */
-
- permit()
- {
- if (port->mmhs->stat & (m_kill | m_busy)) return false;
- if (matchn(port->user->call, port->mmhs->to, ln_call)) return true;
- if (matchn(port->user->call, port->mmhs->from, ln_call)) return true;
- return false;
- }
-
- /*
- * Return true if user has kill permission for current message.
- */
-
- kpermit()
- {
- if (port->mmhs->stat & m_kill) return false;
- if (port->mode & ops) return true;
- if (permit()) return true;
- return ((port->mmhs->type is 'T') and (port->opt2 is 'T'));
- }
-
- /*
- * Return true if user has list permission for current message.
- */
-
- lpermit()
- {
- if (port->user->options & u_sysop) return true;
- if (permit()) return true;
- return ((port->mmhs->type isnt 'P')
- and !(port->mmhs->stat & (m_fwd | m_kill | m_busy)));
- }
-
- /*
- * Return true if user has read permission for current message.
- */
-
- rpermit()
- {
- if ( port->mode & ops) return true;
- if (permit()) return true;
- return (port->mmhs->type isnt 'P');
- }
-
- /*
- * Clean the mail file.
- * Force drain of buffers, update of directory item.
- */
-
- clnmsg()
- {
- close(mfl);
- mfl = open(mbfile, O_RDWR | O_BINARY);
- }
-
- /*
- * Close the mail file.
- */
-
- clsmsg()
- {
- close (mfl);
- }
-
- /*
- * Open the mail file.
- */
-
- opnmsg()
- {
- register char *tp;
-
- /*
- * Allocate space for the mail file records.
- */
-
- mfhs = (MAIL_HDR *) malloc(sizeof(MAIL_HDR));
- tmmhs = (MSG_HDR *) malloc(sizeof(MSG_HDR));
-
- /*
- * Allocate the "who has mail" lists.
- */
-
- ufwd = (char *) malloc (ln_call * ufwdm);
- bfwd = (char *) malloc (ln_call * bfwdm);
- if (bfwd is NULL) errall();
-
- /*
- * Open the file. If it does not exist, make one.
- */
-
- if ((mfl = open(mbfile, O_RDWR | O_BINARY)) < 0)
- {
- if ((mfl = open(mbfile, O_CREAT | O_RDWR | O_BINARY, pmode)) < 0)
- { nofile(mbfile); exit(1); }
- inithdr();
- mfhs->next_msg = 1;
- write_rec(mfl, 0, (char *)mfhs);
- }
-
- /*
- * Read the mail file header.
- */
-
- read_rec(mfl, 0, (char *)mfhs);
-
- /*
- * If wrong version mail file, quit now.
- */
-
- if (mfhs->version isnt mb_version)
- {
- printf("Expected version %d, got version %d\n",
- mb_version, mfhs->version);
- nofile(mbfile);
- exit(1);
- }
-
- }
-
- /*
- * Initialize the mail file header.
- */
-
- inithdr()
- {
- mfhs->next = 1;
- mfhs->first = 0;
- mfhs->last = 0;
- mfhs->version = mb_version;
- mfhs->free = 0;
- mfhs->count = 0;
- mfhs->unt_msg = 1;
-
- curtim();
- strncpy(mfhs->date, l_date, ln_date);
- strncpy(mfhs->time, l_time, ln_time);
- fill(mfhs->unu, '\0', mfhsunu);
- }
-
- /*
- * Open mail file and read first record.
- */
-
- readmsg()
- {
- mfl = open(mbfile, O_RDWR | O_BINARY);
- read_rec(mfl, 0, (char *)mfhs);
- }
-
- /*
- * Does this station want us to send BIDs ?
- */
-
- isbid()
- {
- register char *f;
-
- /* Is this a sid? It must have a '-' and end with a ']' */
-
- if ((port->line[strlen(port->line) - 2] isnt ']' ) or
- ((f = strrchr(port->line, '-')) is NULL))
- return;
-
- /* Look for specal characters in the last field. */
-
- f++;
- for (; *f isnt ']';f++)
- switch(*f)
- {
- case 'H' : hidok = true; break;
- case '$' : if(*(f+1) is ']') bidok = true; break;
- }
- }
-
- /*
- * Check to see whether we already have this BID.
- */
-
- checkbid()
- {
- FILE *out;
- char *a, *b;
-
- if (*port->mmhs->bid is ' ') { needbid = true; return; }
- if ((out = fopen(bidfile, "r")) is NULL) {
- nofile(bidfile); return;
- }
- while (fgets(port->line, linelen, out) isnt NULL) {
-
- /* the first 4 characters are the date */
-
- strcpy(port->cmd, port->line + 4);
- a = port->cmd;
- remnl(a);
-
- a = port->line;
- b = port->mmhs->bid;
- unbl(a, b, ln_bid);
-
- if (match(port->cmd, port->line)) {
- needbid = false;
- fclose(out);
- return;
- }
- }
- needbid = true;
- fclose(out);
- }
-
- /****************************************
- * *
- * Code for the commands starts here *
- * *
- ****************************************/
-
- /*
- * GM or GR command: backup the mail file.
- */
-
- untmsg()
- {
- register word inhdr, me;
- if (port->opt2 isnt 'A') { if (sure()) return; }
- if (!mfhs->count) { port->msg = mm[5]; return; }
- prtx(mm[6]);
-
- close(mfl); /* Close current. */
-
- unlink(mbbfile); /* Delete backup */
-
- /*
- * Copy current to backup.
- */
-
- if (samedir(mbfile, mbbfile)) rename(mbfile, mbbfile);
- else copy(mbfile, mbbfile, false);
-
- unlink(mbfile); /* Delete current. */
-
- /*
- * Open new current and backup.
- */
-
- mfl = open(mbfile, O_CREAT | O_RDWR | O_BINARY, pmode);
- mflb = open(mbbfile, O_RDONLY | O_BINARY);
-
- read_rec(mflb, 0, (char *)mfhs);
- me = mfhs->last;
- inhdr = mfhs->first;
- inithdr();
-
- if (port->opt2 is 'R')
- {
- if (port->flds is 1) mfhs->next_msg = 1;
- else mfhs->next_msg = atoi(port->fld[1]);
- }
-
-
- while(inhdr <= me) /* For each message header ... */
- {
- read_rec(mflb, inhdr, (char *)port->mmhs); /* Read the header. */
-
- /*
- * Tell the sysop about this message.
- */
-
- sprintf(port->line, "Hdr %6u Size %6u # %6u Read %6u",
- inhdr, port->mmhs->size, port->mmhs->number, port->mmhs->read);
- outstr(port->line);
-
- inhdr++;
-
- if (!(port->mmhs->stat & ( m_kill | m_busy)))
- {
- outstr("\n");
-
- /*
- * If renumbering messages, renumber this message.
- */
-
- if (port->opt2 is 'R')
- {
- msgfile(port->line, port->mmhs->number);
- msgfile(port->cmd, mfhs->next_msg);
- rename(port->line, port->cmd);
- port->mmhs->number = mfhs->next_msg++;
- }
-
- /*
- * Write the header.
- */
-
- port->mmhs->rn = ++mfhs->count;
- wt_mmhs();
- }
- else arcmsg();
- }
-
-
- /*
- * Write the file header.
- */
- if (mfhs->count) mfhs->first = 1;
- mfhs->next = mfhs->count + 1;
- mfhs->last = mfhs->count;
- mfhs->unt_msg = mfhs->next_msg;
- write_rec(mfl, 0, (char *)mfhs);
- close(mflb);
- clnmsg();
- }
-
-
- /*
- * Print headers of unread messages for this user.
- */
-
- newmsg()
- {
- if (findfwd(port->user->call, ufwd, ufwdn) or
- findfwd(port->user->call, bfwd, bfwdn))
- {
- prtx(mm[2]);
- port->opt2 = '\0';
- port->flds = 1;
- lstmsg();
- }
- }
-
- /*
- * L command, list messages.
- */
-
- lstmsg()
- {
- register char *p;
- register short done, ok;
- word h, found, more;
-
- /*
- * First set up arguments.
- */
-
- found = 0; more = 0; done = false;
- if ((*port->fld[1] is ';') or (*port->fld[2] is ';')) port->flds--;
- switch(port->opt2)
- {
- case '@' :
- case '<' :
- case '>' : pcall(tcall, port->fld[1]); break;
- case '\0': break;
- case 'E' :
- case ' ' : if (port->flds is 1) more = port->user->msg_number;
- default : if (port->flds is 2)
- {
- if (!num(port->fld[1])) { port->msg = mwhat; return; }
- more = atoi(port->fld[1]);
- }
- }
-
- /*
- * Log it, unless is initial login check for msgs.
- */
-
- if (port->opt2)
- {
- sprintf(port->line, "%u", more);
- log('M', 'L', port->opt2, port->line);
- }
-
- /*
- * Paw through the messages and show what requested.
- */
-
- for (h = mfhs->last; h and !done; h--)
- {
- read_rec(mfl, h, (char *)port->mmhs);
- if ((port->opt2 is 'L') or ((port->opt2 is 'E') and (port->flds is 2)))
- done = (found is more); else done = (port->mmhs->number < more);
-
- ok = !done;
-
- /*
- * Does this user have read permission for this message?
- */
-
- if (ok) ok = lpermit();
- if (ok) if (port->mmhs->stat & m_kill)
- ok = ((port->opt2 is 'K') or (port->opt2 is 'E'));
- if (ok) if (port->mmhs->stat & m_busy) ok = (port->opt2 is 'E');
-
- /*
- * Is this message wanted?
- */
-
- if (ok) switch(port->opt2)
- {
- case '\0': ok = matchn(port->user->call, port->mmhs->to, ln_call); break;
- case 'E' : break;
- case 'K' : ok = (port->mmhs->stat & m_kill); break;
- case 'F' : ok = (port->mmhs->stat & m_fwd); break;
- case 'H' : ok = (port->mmhs->stat & m_hold); break;
- case 'L' : break;
- case 'M' : ok = matchn(port->user->call, port->mmhs->to, ln_call);
- if (!ok) ok = matchn(port->user->call, port->mmhs->from, ln_call);
- break;
-
- case 'O' : ok = (port->mmhs->stat & m_stale); break;
- case 'U' : ok = !((port->mmhs->type is 'B')or(port->mmhs->type is 'A')
- or (port->mmhs->stat & (m_fwd | m_read))); break;
- case 'Y' : ok = (port->mmhs->stat & m_read); break;
- case '@' : ok = matchn(tcall, port->mmhs->bbs, ln_call); break;
- case '<' : ok = matchn(tcall, port->mmhs->from, ln_call); break;
- case '>' : ok = matchn(tcall, port->mmhs->to, ln_call); break;
- default : ok = ((port->mmhs->type is port->opt2) or
- (port->opt2 is ' '));
- }
- if (ok) prthdr(!found++);
- }
- if (!found) port->msg = mfind;
- s_flag setbit s_update;
- }
-
- /*
- * CM command: duplicate a message.
- */
-
- dupmsg()
- {
- word tmpsize;
- if (!findmsg(atoi(port->fld[2]))) { port->msg = mnmsg; return; }
- port->opt1 = 'S';
-
- prthdr(true);
- pcall(port->mmhs->to, port->fld[1]);
- fill(port->mmhs->bbs, ' ', ln_call);
- port->mmhs->ext = 0;
-
- if (port->flds > 3) atfrom(port->flds - 2);
- if (port->flds > 5) atfrom(port->flds - 4);
- tmpsize = port->mmhs->size;
-
- msgfile(port->cmd, port->mmhs->number);
- initmsg(false);
- msgfile(port->line, mfhs->next_msg);
- copy(port->cmd, port->line, false);
- filesize = tmpsize;
- cremsg();
- }
-
- /*
- * F command: copy a message to a file.
- */
-
- filmsg()
- {
- register char *p;
- register short hdr, append;
- register FILE *out;
-
- if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
-
- hdr = true;
- append = false;
-
- if (port->flds is 4) for (p = port->fld[3]; *p; p++) switch (*p)
- {
- case 'A' : append = true; break;
- case 'N' : hdr = false; break;
- default: ;
- }
-
- if (port->opt2 is ' ') strcpy(port->line, port->fld[2]);
- else if (getdir(port->fld[2]) is NULL) { port->msg = mndir; return; }
-
- if (append) out = fopen (port->line, "a"); else
- {
- if ((out = fopen (port->line, "r")) isnt NULL)
- { fclose(out); port->msg = mexst; return; }
- out = fopen (port->line, "w");
- }
-
- if (out is NULL) { port->msg = mcant; return; }
-
- sprintf(tmp->scr, "%s %s", port->fld[1], port->line);
- log('M', 'D', port->opt2, tmp->scr);
-
- prthdr(true);
-
- if (hdr) fputs(tmp->scr, out);
-
- msgfile(port->cmd, port->mmhs->number);
-
- if ((port->fl = fopen(port->cmd, "r")) is NULL)
- { fclose(out); nofile(port->cmd); return; }
- fseek( port->fl, (long)RECSIZE, 0);
- while (fgets(tmp->scr, scrmax, port->fl) isnt NULL) fputs(tmp->scr, out);
-
- fclose(port->fl);
- fclose(out);
- }
-
- /*
- * Upload the message text file.
- */
-
- uloadm(tname)
- char *tname;
- {
- register char *tp;
- register PORTS *p;
- short first;
-
- p = port;
-
- if ((p->fl = fopen(tname, "w")) is NULL) { p->msg = mcant; return false; }
- fseek( p->fl, (long)RECSIZE, 0);
-
- first = true;
- filesize = 0;
- while (true)
- {
- while(!getdat());
-
- /*
- * If user disconnected, timed out, or forced off, zap the file.
- */
-
- if (p->mode & gone)
- {
- fclose(p->fl);
- return false;
- }
-
- /*
- * If the first line is not a header (thus it is a human entering
- * the message), make sure there is an initial blank line before
- * the body of the message.
- */
-
- if (first)
- {
- first = false;
- if (!ishead(p->line)) if (*p->line isnt '\n') fputs("\n", p->fl);
- }
-
- /*
- * Stuff the line into the file.
- */
-
- if (match(p->line, "/EX\n") or match(p->line,"/ex\n"))
- {
- fclose(p->fl);
- return true;
- }
-
-
- if ((tp = strchr(p->line, cpmeof)) is NULL)
- {
- filesize += strlen(p->line);
- fputs(p->line, p->fl);
- }
- else
- {
- if (tp isnt p->line)
- {
- *tp++ = '\n';
- *tp = '\0';
- filesize += strlen(p->line);
- fputs(p->line, p->fl);
- }
- fclose(p->fl);
- return true;
- }
- }
- }
-
- /*
- * "Display the message text" utility.
- */
-
- dloadm(sh)
- short sh;
- {
- short first;
-
- sprintf(port->line, "%u", port->mmhs->number);
- log('M', 'R', port->opt2, port->line);
- port->mmhs->read++;
- if (matchn(port->user->call, port->mmhs->to, ln_call))
- port->mmhs->stat setbit m_read;
- wt_mmhs();
- makehdr2();
- prthdr(true);
-
- msgfile(port->line, port->mmhs->number);
-
- if ((port->fl = fopen(port->line, "r")) is NULL)
- { nofile(port->line); return; }
-
- fseek( port->fl, (long)RECSIZE, 0 );
- pgst(NULL);
- pgck(); /* First line of header */
- pgck(); /* Second line of header */
- pgck(); /* Path line */
- if (port->mmhs->ext) pgck();
- if (*port->mmhs->bid isnt ' ') pgck();
-
- strcpy(tmp->scr, " Path: ");
- first = true;
-
- while(fgets(port->line, linelen, port->fl) isnt NULL)
- {
- if (!sh)
- {
- sh = !parsehd(port->line);
- if (sh)
- {
- if (!first)
- {
- strcat(tmp->scr, "\n\n");
- outstr(tmp->scr);
- pgck();
- prtx("Date: $j/$k\n"); pgck();
- prtx("From: $P @ $a\n"); pgck();
- prtx("Message-Id: <$m@$a>\n"); pgck();
- prtx("To: $G @ ");
- if (*port->mmhs->bbs is ' ') prtx("$O\n");
- else if (port->mmhs->ext is 2) prtx("$h\n");
- else prtx("$A\n"); pgck();
- prtx("Subject: $E\n\n"); pgck();
- }
- }
- else
- {
- if (!first) strcat(tmp->scr, "!");
- strcat(tmp->scr, orgbbs);
- first = false;
- }
- }
-
- if (sh)
- {
- outstr(port->line);
- if ((pgck() is 'Q') or (chkdis())) { fclose(port->fl); return; }
- }
- }
- fclose (port->fl);
- }
-
- /*
- * RM command: read my messages.
- */
-
- rdmsgm()
- {
- register short found;
- register word h;
-
- found = false;
- for (h = mfhs->first; h and h <= mfhs->last; h++)
- {
- read_rec(mfl, h, (char *)port->mmhs);
- if (!(port->mmhs->stat & (m_read | m_fwd | m_hold | m_busy)) and
- matchn(port->user->call, port->mmhs->to, ln_call))
- {
- dloadm(false);
- found = true;
- if (pause() is 'Q') return;
- }
- }
- if (!found) port->msg = mfind;
- }
-
- /*
- * R command: read one message.
- */
-
- rdmsg()
- {
- if (!num(port->fld[1])) { port->msg = mwhat; return; }
- if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
- if (!rpermit()) { port->msg = mprot; return; }
-
- dloadm(port->opt2 is 'H');
- }
-
- /*
- * KF, KM, KO, KY, KK commands, kill multiple messages.
- */
-
- klmsgm()
- {
- register short ok;
- register short found;
- word h, next;
-
- if (port->flds is 2) pcall(tcall, port->fld[1]);
-
- found = false;
- for (h = mfhs->first; h and h <= mfhs->last; h++)
- {
- read_rec(mfl, h, (char *)port->mmhs);
-
- ok = kpermit();
- if (ok) ok = !(port->mmhs->stat & m_hold);
-
- if (ok) if (port->flds is 2) ok = matchn(tcall, port->mmhs->to, ln_call);
-
- if (ok) switch(port->opt2)
- {
- case 'F' : ok = (port->mmhs->stat & m_fwd); break;
- case 'M' :
- ok = ((port->mmhs->stat & m_read) and
- matchn(port->user->call, port->mmhs->to, ln_call));
- break;
- case 'O' : ok = (port->mmhs->stat & m_stale); break;
- case 'Y' : ok = (port->mmhs->stat & m_read); break;
- }
-
- if (ok)
- {
- sprintf(port->line, "%u", port->mmhs->number);
- log('M', 'K', port->opt2, port->line);
- prtx(mm[7]);
- found = true;
- port->mmhs->stat setbit m_kill;
- write_rec(mfl, port->mmhs->rn, (char *)port->mmhs);
- makehdr2();
- }
- }
- if (!found) port->msg = mfind;
- }
-
- /*
- * K command, kill a message.
- */
-
- klmsg()
- {
- register short dosvc;
-
- if (!num(port->fld[1])) { port->msg = mwhat; return; }
- if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
- if (port->mmhs->stat & m_kill) { port->msg = mnmsg; return; }
- if (!kpermit()) { port->msg = mprot; return; }
-
- log('M', 'K', port->opt2, port->fld[1]);
-
- dosvc = (port->opt2 is 'T') and
- (port->mmhs->type is 'T') and
- (s_param & s_svc);
-
- if (dosvc) findat();
-
- /*
- * Marked the message as Killed.
- */
-
- port->mmhs->stat setbit m_kill;
- write_rec(mfl, port->mmhs->rn, (char *)port->mmhs);
- makehdr2();
-
- /*
- * If this is KT of T type message, and we do service messages,
- * do the service message.
- */
-
- if (dosvc)
- {
- port->opt1 = 'S';
- strncpy(port->mmhs->to, port->mmhs->from, ln_call);
- strncpy(port->mmhs->from, cport->user->call, ln_call);
- port->mmhs->type = 'S';
- fill(port->mmhs->bid, ' ', ln_bid);
- port->mmhs->ext = 0;
- initmsg(false);
- msgfile(port->line, mfhs->next_msg);
- port->fl = fopen(port->line, "w");
- fseek(port->fl, (long)RECSIZE, 0);
- fprintf(port->fl, "Msg %5u taken from %6.6s by %6.6s at %4.4s on %6.6s\n",
- port->mmhs->number, cport->user->call, port->user->call, l_time, l_date);
- fclose(port->fl);
-
- filesize = 56;
- cremsg();
- }
- port->msg = mdone;
- }
-
- /*
- * S command: send a message.
- */
-
- sndmsg()
- {
- FILE *out;
- char *a, *b;
-
- holdit = false; /* initialize it to something */
-
- pfld();
- if (port->mode & gone) return;
-
- if (bidok) {
- if (!needbid) return;
- }
- else {
- if (port->user->options & (u_bbs | u_expert)) outstr("Msg:\n");
- else prtx(mm[1]);
- }
-
- msgfile(port->cmd, mfhs->next_msg);
- if (!uloadm(port->cmd)) return;
-
- /*
- * If this is a Bulletin and has no BID,
- * parse the headers and give it one.
- */
- if (!hasbid)
- if (!iscall(port->mmhs->to))
- if (port->mmhs->type is 'B')
- {
- msgfile(port->cmd, mfhs->next_msg);
- a = port->line;
- b = cport->user->call;
- unbl(a, b, 6);
-
- /* Default the BID as to coming from this BBS with our msg number. */
-
- sprintf(tmp->scr, "%-u_%-s", mfhs->next_msg, port->line);
-
- /* Now parse the headers if it came from another BBS. */
-
- if ((out = fopen(port->cmd, "r")) is NULL)
- {
- nofile(port->cmd); return;
- }
- fseek(out, (long)RECSIZE, 0);
- while (fgets(port->line, linelen, out) isnt NULL)
- {
- if (parsehd(port->line))
- {
- sprintf(tmp->scr, "%s_%s", orgmsg, orgbbs);
- }
- }
- fclose(out);
- strncpy(port->mmhs->bid, tmp->scr, ln_bid);
- hasbid = true;
- }
- checkbid();
- if (!needbid) holdit = true;
- else holdit = false;
-
- /* If a message is to an individual,
- * automatically make it a private message.
- */
-
- if (port->opt2 is ' ')
- if (iscall(port->mmhs->to)) port->mmhs->type = 'P';
-
- cremsg();
- }
-
- /*
- * SM command, send a message to a distribution list.
- */
-
- sndmlt()
- {
- register FILE *fl;
- char fn[80];
- register short first = true;
- word tmpsize;
-
- holdit = false;
- fill(port->mmhs->bid, ' ', ln_bid);
-
- if ((fl = fopen(port->fld[1], "r")) is NULL)
- { nofile(port->fld[1]); return; }
-
- prtx(mm[0]);
- get_title();
- if (port->mode & gone) { fclose(fl); return; }
-
- if (port->flds is 3) if (*port->fld[port->flds-1] is '$')
- {
- if (*(port->fld[port->flds-1] + 1) isnt NULL)
- {
- strncpy(port->mmhs->bid, port->fld[port->flds-1] + 1, ln_bid);
- hasbid = true;
- }
- }
-
- prtx(mm[1]);
-
- strncpy(port->mmhs->from, port->user->call, ln_call);
- port->mmhs->ext = 0;
- initmsg(false);
- msgfile(fn, mfhs->next_msg);
- if (!uloadm(fn)) { fclose(fl); return; }
- tmpsize = filesize;
-
- while (fgets(port->line, linelen, fl) isnt NULL)
- {
- parse();
- if (!first)
- {
- port->mmhs->ext = 0;
- initmsg(false);
- msgfile(port->line, mfhs->next_msg);
- copy(fn, port->line, false);
- }
- port->mmhs->type = port->opt2;
- pcall(port->mmhs->to, port->fld[1]);
- fill(port->mmhs->bbs, ' ', ln_call);
-
- if(port->flds > 3) atfrom(2);
- if(port->flds > 5) atfrom(4);
- filesize = tmpsize;
- cremsg();
- first = false;
- }
- fclose(fl);
- }
-
- /*
- * M command, make a message from a file.
- */
-
- makmsg()
- {
- if ((port->fl = fopen(port->fld[2], "r")) is NULL)
- { nofile(port->fld[2]); return; }
- fclose(port->fl);
- pfld();
- if (port->mode & gone) return;
- msgfile(port->line, mfhs->next_msg);
- copy(port->fld[2], port->line, true);
- cremsg();
- }
-
- /*
- * MM command, make multiple messages from a file.
- */
-
- makmlt()
- {
- register FILE *dfl;
- char tnm[80];
-
- holdit = false;
- fill(port->mmhs->bid, ' ', ln_bid);
-
- if ((port->fl = fopen(port->fld[2], "r")) is NULL)
- { nofile(port->fld[2]); return; }
- fclose(port->fl);
-
- if ((dfl = fopen(port->fld[1], "r")) is NULL)
- { nofile(port->fld[1]); return; }
-
- strcpy(tnm, port->fld[2]);
-
- if (port->flds is 4) if (*port->fld[port->flds-1] is '$')
- {
- if (*(port->fld[port->flds - 1] + 1) isnt NULL)
- {
- strncpy(port->mmhs->bid, port->fld[port->flds-1] + 1, ln_bid);
- hasbid = true;
- }
- }
-
- prtx(mm[0]);
- get_title();
- if (port->mode & gone) { fclose(dfl); return; }
-
- while (fgets(port->line, linelen, dfl) isnt NULL)
- {
- parse();
- port->mmhs->type = port->opt2;
- pcall(port->mmhs->to, port->fld[1]);
- strncpy(port->mmhs->from, port->user->call, ln_call);
- fill(port->mmhs->bbs, ' ', ln_call);
- port->mmhs->ext = 0;
-
- if (port->flds > 3) atfrom(2);
- if (port->flds > 5) atfrom(4);
- initmsg(false);
- msgfile(port->line, mfhs->next_msg);
- copy(tnm, port->line, true);
- cremsg();
- }
- fclose(dfl);
- }
-
- /*
- * Mark stale messages.
- */
-
- stale()
- {
- register word i;
- register int ts;
-
- for (i = mfhs->first; i and i <= mfhs->last; i++)
- {
- read_rec(mfl, i, (char *)port->mmhs);
-
- ts = tstaleb;
- if (port->mmhs->type is 'T') ts = tstalen;
- else if (iscall(port->mmhs->to)) ts = tstaleu;
-
- if (!(port->mmhs->stat & m_stale))
- if (ddiff(port->mmhs->date, l_date) > ts)
- {
- port->mmhs->stat setbit m_stale;
- write_rec(mfl, i, (char *)port->mmhs);
- }
- }
- }
-
- /*
- * DW command: make wp message from user file.
- */
-
- dwuser()
- {
- register int i;
- register short first = true;
- short doall;
-
- if (*wpcall is ' ') return;
-
- doall = port->flds is 2;
- port->opt1 = 'S';
- filesize = 0;
-
- for (i = 1; i <= ufhs->count; i++)
- {
- read_rec(ufl, i, (char *)tuser);
- if ((tuser->state & u_home) and (tuser->state & u_zip))
- if (doall or !(tuser->state & u_sent))
- {
- if (first)
- {
- first = false;
- port->mmhs->type = 'P';
- strncpy(port->mmhs->to, "WP ", ln_call);
- strncpy(port->mmhs->from, cport->user->call, ln_call);
- strncpy(port->mmhs->bbs, wpcall, ln_call);
- strcpy(port->mmhs->title, "WP Update");
- fill(port->mmhs->bid, ' ', ln_bid);
- port->mmhs->ext = 0;
- initmsg(false);
- msgfile(port->line, mfhs->next_msg);
- port->fl = fopen(port->line, "w");
- }
-
- filesize += 29;
- fseek(port->fl, (long)RECSIZE, 0);
- fprintf(port->fl, "%6.6s qth %6.6s zip %6.6s\n",
- tuser->call, tuser->home_bbs, tuser->zip);
- tuser->state setbit u_sent;
- write_rec(ufl, i, (char *)tuser);
- if (i is port->user->rn) port->user->state setbit u_sent;
- }
- }
-
- if (!first)
- {
- fclose(port->fl);
- cremsg();
- }
- }
-
- /*
- * E command, edit a message header.
- */
-
- edmsg()
- {
- FILE *out;
- char *a, *b;
-
- if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
- while (*port->fld[0] isnt '\0')
- {
- prthdr();
- outstr("t(Y)pe, (S)tatus, (T)o, (F)rom, (B)bs, t(I)tle, bi(D)\n");
- getcmd();
- if (port->mode & gone) return;
- switch (*port->fld[0])
- {
- case 'T' : pcall(port->mmhs->to, port->fld[1]); break;
- case 'F' : pcall(port->mmhs->from, port->fld[1]); break;
- case 'B' : edbbs(1); break;
- case 'I' : if (*port->fld[1])
- {
- remnl(port->line);
- strncpy(port->mmhs->title, port->line+2, mhtitl);
- }
- else *port->mmhs->title = '\0';
- break;
- case 'S' : switch(*port->fld[1])
- {
- case 'F' : port->mmhs->stat = m_fwd; break;
- case 'H' : port->mmhs->stat = m_hold; break;
- case 'N' : port->mmhs->stat = 0; break;
- case 'O' : port->mmhs->stat = m_stale; break;
- case 'Y' : port->mmhs->stat = m_read; break;
- }
- break;
- case 'Y' : if(*port->fld[1]) port->mmhs->type = *port->fld[1];
- else port->mmhs->type = ' '; break;
-
- case 'D' : if(*port->fld[1]) strncpy(port->mmhs->bid, port->fld[1], ln_bid);
- else fill(port->mmhs->bid, ' ', ln_bid);
- break;
- }
- }
- wt_mmhs();
- makehdr2();
- if (*port->mmhs->bid isnt ' ')
- {
- checkbid();
- if (needbid)
- {
- if ((out = fopen(bidfile,"a")) is NULL)
- {
- port->msg = mcant; return;
- }
-
- a = port->cmd;
- b = port->mmhs->bid;
- unbl(a, b, ln_bid);
-
- sprintf(port->line, "%4.4s%s\n", port->mmhs->date + 2, port->cmd);
- if (s_flag & s_dv) begin_lock();
- fputs(port->line, out);
- if (s_flag & s_dv) end_lock();
- fclose(out);
- }
- }
- }
-
- /*
- * ET command, edit an NTS traffic message header.
- */
-
- edtfc()
- {
- register short ok;
-
- if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
- prthdr();
-
- ok = (port->mmhs->type is 'T');
- if (!ok) ok = ((port->mmhs->type is ' ') and matchn(port->mmhs->to, "NTS", 3));
- if (!ok) { port->msg = mm[12]; return; }
-
- prtx(mm[8]);
- getcmd();
- if (port->mode & gone) return;
- if (port->flds) pcall(port->mmhs->to, port->fld[0]);
-
- prtx(mm[9]);
- getcmd();
- if (port->mode & gone) return;
- edbbs(0);
-
- prtx(mm[10]);
- getcmd();
- if (port->mode & gone) return;
- if (port->flds)
- {
- remnl(port->line);
- strncpy(port->mmhs->title, port->line, mhtitl);
- }
- else if (*port->line is ' ') *port->mmhs->title = '\0';
-
- prtx(mm[11]);
- getcmd();
- if (port->mode & gone) return;
- if (port->flds) port->mmhs->type = *port->fld[0];
- else if (*port->line is ' ') port->mmhs->type = ' ';
-
- port->mmhs->stat = 0;
- prthdr();
- wt_mmhs();
- makehdr2();
- sprintf(port->line, "%u %-.6s %s",
- port->mmhs->number, port->mmhs->to, port->mmhs->title);
- log('M', 'E', port->opt2, port->line);
- }
-
- edbbs(f)
- int f;
- {
- fill(port->mmhs->call, '\0', 125);
- port->mmhs->ext = 0;
- fill(port->mmhs->bbs, ' ', ln_call);
- if(*port->fld[f])
- {
- pcall(port->mmhs->bbs, port->fld[f]);
- if (strchr(port->fld[f], '.') is NULL) dodis();
- else
- {
- port->mmhs->ext = 2;
- strncpy(port->mmhs->call[0], port->fld[f], 64);
- }
- }
- }
-