/* * Create file request list for the Hydra or Binkp protocol. */ file_list *create_freqlist(fa_list *al) { file_list *st = NULL, *tmpf; fa_list *tmpa; char *nm, tmpreq[13]; struct stat stbuf; Syslog('o', "create_freqlist(%s)", al?ascfnode(al->addr, 0x1f):"<none>"); made_request = 0; for (tmpa = al; tmpa; tmpa = tmpa->next) { nm = reqname(tmpa->addr); if ((nm != NULL) && (stat(nm, &stbuf) == 0)) { snprintf(tmpreq, 13, "%04X%04X.REQ", tmpa->addr->net, tmpa->addr->node); add_list(&st, nm, tmpreq, DSF, 0L, NULL, 1); made_request = 1; } } if (made_request) { for (tmpf = st; tmpf; tmpf = tmpf->next) Syslog('o', "flist: \"%s\" -> \"%s\" dsp:%d flofp:%lu floff:%lu", MBSE_SS(tmpf->local), MBSE_SS(tmpf->remote), tmpf->disposition, tmpf->flofp, tmpf->floff); } return st; }
void gold_akamatch(FILE *fp) { char temp[PATH_MAX]; FILE *fido; faddr *want, *ta; int i; snprintf(temp, PATH_MAX, "%s/etc/fidonet.data", getenv("MBSE_ROOT")); if ((fido = fopen(temp, "r")) == NULL) return; fprintf(fp, "; AKA Matching\n;\n"); want = (faddr *)malloc(sizeof(faddr)); fread(&fidonethdr, sizeof(fidonethdr), 1, fido); while ((fread(&fidonet, fidonethdr.recsize, 1, fido)) == 1) { if (fidonet.available) { for (i = 0; i < 6; i++) { if (fidonet.zone[i]) { want->zone = fidonet.zone[0]; want->net = 0; want->node = 0; want->point = 0; want->name = NULL; want->domain = NULL; ta = bestaka_s(want); fprintf(fp, "AKAMATCH %d:* %s\n", fidonet.zone[i], ascfnode(ta, 0xf)); tidy_faddr(ta); } } } } free(want); fprintf(fp, ";\n"); fprintf(fp, "AKAMATCHNET YES\n"); fprintf(fp, "AKAMATCHECHO YES\n"); fprintf(fp, "AKAMATCHLOCAL NO\n\n"); fprintf(fp, "; NODELISTS\n;\n"); fprintf(fp, "NODEPATH %s/\n", CFG.nodelists); fseek(fido, fidonethdr.hdrsize, SEEK_SET); while ((fread(&fidonet, fidonethdr.recsize, 1, fido)) == 1) { if (fidonet.available) { fprintf(fp, "NODELIST %s.*\n", fidonet.nodelist); for (i = 0; i < 6; i++) if (strlen(fidonet.seclist[i].nodelist) || fidonet.seclist[i].zone) fprintf(fp, "NODELIST %s.*\n", fidonet.seclist[i].nodelist); } } // fprintf(fp, "USERLIST golded.lst\n"); fprintf(fp, "LOOKUPNET YES\n"); fprintf(fp, "LOOKUPECHO NO\n"); fprintf(fp, "LOOKUPLOCAL NO\n\n"); fclose(fido); }
char *arcname(faddr *addr, unsigned short Zone, int ARCmailCompat) { static char *buf; char *p; char *ext; time_t tt; struct tm *ptm; faddr *bestaka; tt = time(NULL); ptm = localtime(&tt); ext = dow[ptm->tm_wday]; bestaka = bestaka_s(addr); buf = prepbuf(addr); p = strrchr(buf, '/'); if (!ARCmailCompat && (Zone != addr->zone)) { /* * Generate ARCfile name from the CRC of the ASCII string * of the node address. */ snprintf(p, PATH_MAX -1, "/%08x.%s0", StringCRC32(ascfnode(addr, 0x1f)), ext); } else { if (addr->point) { snprintf(p, PATH_MAX -1, "/%04x%04x.%s0", ((bestaka->net) - (addr->net)) & 0xffff, ((bestaka->node) - (addr->node) + (addr->point)) & 0xffff, ext); } else if (bestaka->point) { /* * Inserted the next code for if we are a point, * I hope this is ARCmail 0.60 compliant. 21-May-1999 */ snprintf(p, PATH_MAX -1, "/%04x%04x.%s0", ((bestaka->net) - (addr->net)) & 0xffff, ((bestaka->node) - (addr->node) - (bestaka->point)) & 0xffff, ext); } else { snprintf(p, PATH_MAX -1, "/%04x%04x.%s0", ((bestaka->net) - (addr->net)) & 0xffff, ((bestaka->node) - (addr->node)) &0xffff, ext); } } tidy_faddr(bestaka); return buf; }
void CloseMail(FILE *qp, faddr *t) { time_t Now; struct tm *tm; faddr *ta; putc('\r', qp); Now = time(NULL); tm = gmtime(&Now); ta = bestaka_s(t); fprintf(qp, "\001Via %s @%d%02d%02d.%02d%02d%02d.UTC mbfido %s\r", ascfnode(ta, 0x1f), tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, VERSION); tidy_faddr(ta); putc(0, qp); fclose(qp); net_out++; }
int Bounce(faddr *f, faddr *t, FILE *fp, char *reason) { int rc = 0, count = 0; char *Buf; FILE *np; time_t Now; faddr *from; Now = time(NULL); if (SearchFidonet(f->zone)) f->domain = xstrcpy(fidonet.domain); Syslog('+', "Bounce msg from %s", ascfnode(f, 0xff)); Buf = calloc(MAX_LINE_LENGTH +1, sizeof(char)); rewind(fp); np = tmpfile(); from = bestaka_s(f); from->zone = t->zone; from->net = t->net; from->node = t->node; from->point = t->point; from->name = xstrcpy((char *)"Postmaster"); if (f->point) fprintf(np, "\001TOPT %d\r", f->point); if (from->point) fprintf(np, "\001FMPT %d\r", from->point); fprintf(np, "\001INTL %d:%d/%d %d:%d/%d\r", f->zone, f->net, f->node, from->zone, from->net, from->node); /* * Add MSGID, REPLY and PID */ fprintf(np, "\001MSGID: %s %08x\r", ascfnode(from, 0x1f), sequencer()); while ((fgets(Buf, MAX_LINE_LENGTH, fp)) != NULL) { Striplf(Buf); if (strncmp(Buf, "\001MSGID:", 7) == 0) { fprintf(np, "\001REPLY:%s\r", Buf+7); } } fprintf(np, "\001PID: FTND-FIDO %s (%s-%s)\r", VERSION, OsName(), OsCPU()); fprintf(np, "\001TZUTC: %s\r", gmtoffset(Now)); fprintf(np, " Dear %s\r\r", FTND_SS(f->name)); fprintf(np, "Your message could not be delevered, reason: %s\r\r", reason); fprintf(np, "Here are the first lines of the original message from you:\r\r"); fprintf(np, "======================================================================\r"); rewind(fp); while ((fgets(Buf, MAX_LINE_LENGTH, fp)) != NULL) { Striplf(Buf); if (Buf[0] == '\001') { fprintf(np, "^a"); fwrite(Buf + 1, strlen(Buf) -1, 1, np); } else { fwrite(Buf, strlen(Buf), 1, np); } fputc('\r', np); count++; if (count == 50) break; } fprintf(np, "======================================================================\r"); if (count == 50) { fprintf(np, "\rOnly the first 50 lines are displayed\r"); } fprintf(np, "\rWith regards, %s\r\r", CFG.sysop_name); fprintf(np, "%s\r", TearLine()); Now = time(NULL) - (gmt_offset((time_t)0) * 60); rc = postnetmail(np, from, f, NULL, (char *)"Bounced message", Now, 0x0000, FALSE, from->zone, f->zone); tidy_faddr(from); fclose(np); free(Buf); return rc; }
/* * Return codes: * 0 - All Seems Well * 1 - Invalid type (not 2 or 2+) * 2 - Read header error * 3 - Not for me * 4 - Password error * 5 - Unsecure session * * If session is TRUE, the password is checked as being the session password, * otherwise it is checked as the mail password. */ int getheader(faddr *f, faddr *t, FILE *pkt, char *pname, int session) { unsigned char buffer[0x3a]; int i, capword, prodx, major, minor = 0, tome = FALSE; char *p, *prodn = NULL, *fa, *ta, buf[5]; int year, month, day, hour, min, sec; f->domain = NULL; f->name = NULL; t->domain = NULL; t->name = NULL; /* * Read type 2+ packet header, see FSC-0039 version 4 and FTS-0001 */ if (fread(buffer, 1, 0x3a, pkt) != 0x3a) { WriteError("Could not read header (%s)", pname); return 2; } if ((buffer[0x12] + (buffer[0x13] << 8)) != 2) { WriteError("Not a type 2 packet (%s)", pname); return 1; } f->node = (buffer[0x01] << 8) + buffer[0x00]; t->node = (buffer[0x03] << 8) + buffer[0x02]; f->net = (buffer[0x15] << 8) + buffer[0x14]; t->net = (buffer[0x17] << 8) + buffer[0x16]; f->zone = (buffer[0x23] << 8) + buffer[0x22]; t->zone = (buffer[0x25] << 8) + buffer[0x24]; year = (buffer[0x05] << 8) + buffer[0x04]; /* * Check for Y2K bugs, if there are any this is not important, * it is just for logging! */ if (year < 50) year = year + 2000; else if (year < 1900) year = year + 1900; month = (buffer[0x07] << 8) + buffer[0x06] + 1; day = (buffer[0x09] << 8) + buffer[0x08]; hour = (buffer[0x0b] << 8) + buffer[0x0a]; min = (buffer[0x0d] << 8) + buffer[0x0c]; sec = (buffer[0x0f] << 8) + buffer[0x0e]; prodx = buffer[0x18]; major = buffer[0x19]; capword = (buffer[0x2d] << 8) + buffer[0x2c]; if (capword != ((buffer[0x28] << 8) + buffer[0x29])) capword = 0; if (capword & 0x0001) { /* * FSC-0039 packet type 2+ */ prodx = prodx + (buffer[0x2a] << 8); minor = buffer[0x2b]; f->zone = buffer[0x2e] + (buffer[0x2f] << 8); t->zone = buffer[0x30] + (buffer[0x31] << 8); f->point = buffer[0x32] + (buffer[0x33] << 8); t->point = buffer[0x34] + (buffer[0x35] << 8); } else { /* * Stone age @%#$@ */ f->zone = buffer[0x22] + (buffer[0x23] << 8); t->zone = buffer[0x24] + (buffer[0x25] << 8); if ((f->zone == 0) && (t->zone == 0)) { /* * No zone info, since the packet should be for us, guess the zone * against our aka's from the setup using a 2d test. */ for (i = 0; i < 40; i++) { if ((CFG.akavalid[i]) && (t->net == CFG.aka[i].net) && (t->node == CFG.aka[i].node)) { t->zone = CFG.aka[i].zone; f->zone = CFG.aka[i].zone; Syslog('!', "Warning, zone %d assumed", CFG.aka[i].zone); break; } } } } for (i = 0; i < 8; i++) pktpwd[i] = buffer[0x1a + i]; pktpwd[8]='\0'; for (p = pktpwd + 7; (p >= pktpwd) && (*p == ' '); p--) *p='\0'; if (pktpwd[0]) f->name = pktpwd; /* * Fill in a default product code in case it doesn't exist */ snprintf(buf, 5, "%04x", prodx); prodn = xstrcpy((char *)"Unknown 0x"); prodn = xstrcat(prodn, buf); for (i = 0; ftscprod[i].name; i++) if (ftscprod[i].code == prodx) { free(prodn); prodn = xstrcpy(ftscprod[i].name); break; } pktfrom.name = NULL; pktfrom.domain = NULL; pktfrom.zone = f->zone; pktfrom.net = f->net; pktfrom.node = f->node; if (capword & 0x0001) pktfrom.point = f->point; else pktfrom.point = 0; for (i = 0; i < 40; i++) { if ((CFG.akavalid[i]) && ((t->zone == 0) || (t->zone == CFG.aka[i].zone)) && (t->net == CFG.aka[i].net) && (t->node == CFG.aka[i].node) && ((!(capword & 0x0001)) || (t->point == CFG.aka[i].point) || (t->point && !CFG.aka[i].point))) tome = TRUE; } fa = xstrcpy(ascfnode(f, 0x1f)); ta = xstrcpy(ascfnode(t, 0x1f)); Syslog('+', "Packet : %s type %s", pname, (capword & 0x0001) ? "2+":"stone-age"); Syslog('+', "From : %s to %s", fa, ta); Syslog('+', "Dated : %02u-%02u-%u %02u:%02u:%02u", day, month, year, hour, min, sec); Syslog('+', "Program : %s %d.%d", prodn, major, minor); free(ta); free(fa); if (capword & 0x0001) { buf[0] = buffer[0x36]; buf[1] = buffer[0x37]; buf[2] = buffer[0x38]; buf[3] = buffer[0x39]; buf[4] = '\0'; } if (prodn) free(prodn); if (!tome) return 3; if (session) { /* * FTS-0001 session setup mode. */ if (noderecord(f) && strlen(nodes.Spasswd)) { if (strcasecmp(nodes.Spasswd, pktpwd) == 0) { return 0; /* Secure session */ } else { Syslog('!', "Password : got \"%s\", expected \"%s\"", pktpwd, nodes.Spasswd); return 4; /* Bad password */ } } else { Syslog('+', "Node not in setup or no password set"); return 5; /* Unsecure session */ } } else { /* * Mail password check */ if (noderecord(f) && nodes.MailPwdCheck && strlen(nodes.Epasswd)) { if (strcasecmp(nodes.Epasswd, pktpwd) == 0) { return 0; /* Password Ok */ } else { Syslog('!', "Password : got \"%s\", expected \"%s\"", pktpwd, nodes.Epasswd); return 4; /* Bad password */ } } else { return 0; /* Not checked, still Ok */ } } return 0; }
int ftnmsgid(char *msgid, char **s, unsigned int *n, char *areaname) { char *buf, *l, *r, *p; unsigned int nid = 0L; faddr *tmp; static int ftnorigin = 0; Syslog('m', "Make ftn msgid from \"%s\"", MBSE_SS(msgid)); if (msgid == NULL) { *s = NULL; *n = 0L; return ftnorigin; } buf = malloc(strlen(msgid)+65); strcpy(buf, msgid); if ((l = strchr(buf,'<'))) l++; else l = buf; while (isspace(*l)) l++; if ((r = strchr(l,'>'))) *r = '\0'; r = l + strlen(l) - 1; while (isspace(*r) && (r > l)) (*r--)='\0'; if ((tmp = parsefaddr(l))) { if (tmp->name) { if (strspn(tmp->name,"0123456789") == strlen(tmp->name)) nid = atoul(tmp->name); else nid = 0xffffffff; if (nid == 0xffffffff) { hash_update_s(&nid, tmp->name); } else ftnorigin = 1; } else { hash_update_s(&nid,l); } *s = xstrcpy(ascfnode(tmp, 0x1f)); tidy_faddr(tmp); } else { if ((r=strchr(l,'@')) == NULL) { /* should never happen */ Syslog('!', "ftnmsgid: should never happen: %s", printable(l, 0)); *s = xstrcpy(l); hash_update_s(&nid,l); /* <*****@*****.**> */ } else if (strncmp(l,"MSGID_",6) == 0) { *r = '\0'; r = strrchr(l+6,'_'); if (r) *r++ = '\0'; *s = xstrcpy(l+6); if (r) sscanf(r,"%x",&nid); ftnorigin = 1; /* <*****@*****.**> */ } else if (strncmp(l,"NOMSGID_",8) == 0) { *s = NULL; *n = 0L; ftnorigin = 1; return ftnorigin; /* <[email protected]> */ } else if (strncmp(l,"ftn_",4) == 0) { *r = '\0'; if ((r = strchr(l+4,'$')) || (r=strchr(l+4,'#'))) { if (*r=='$') *r='@'; if ((r=strchr(l+4,'.'))) *r=':'; if ((r=strchr(l+4,'.'))) *r='/'; } while ((r=strrchr(l+4,'_')) != strchr(l+4,'_')) *r='\0'; r=strchr(l+4,'_'); *r++='\0'; *s=xstrcpy(l+4); sscanf(r,"%x",&nid); ftnorigin=1; /* <[email protected]> */ } else if (strncmp(l,"wgcid$",6) == 0) { *r='\0'; if ((r=strstr(l+6,"$g"))) { *r='\0'; *s=xstrcpy(l+6); *s=xstrcat(*s,(char *)":"); l=r+2; } if ((r=strstr(l,"$h"))) { *r++='\0'; *s=xstrcat(*s,l); *s=xstrcat(*s,(char *)"/"); l=r+2; } if ((r=strstr(l,"$i"))) { *r='\0'; *s=xstrcat(*s,l); *s=xstrcat(*s,(char *)"."); l=r+2; } if ((r=strstr(l,"$k"))) { *r='\0'; *s=xstrcat(*s,l); *s=xstrcat(*s,(char *)"@"); l=r+2; } if ((r=strstr(l,"$j"))) { *r='\0'; *s=xstrcat(*s,l); sscanf(r+2,"%x",&nid); } } else { *r='\0'; if ((p=strchr(l,'%'))) { *p='\0'; if (strspn(l,"0123456789") == strlen(l)) { *r='@'; r=p; } else *p='%'; } r++; if (strspn(l,"0123456789") == strlen(l)) nid = atoul(l); else nid = 0xffffffff; if (nid == 0xffffffff) hash_update_s(&nid,l); *s=xstrcpy(r); } } *n=nid; free(buf); return ftnorigin; }
ftnmsg *mkftnhdr(rfcmsg *msg, int newsmode, faddr *recipient) { char *freename = NULL, *rfcfrom = NULL, *p, *q, *l, *r; char *fbuf = NULL, *ftnfrom=NULL; static ftnmsg *tmsg; int needreplyaddr = 1; faddr *tmp, *tmp2; tmsg=(ftnmsg *)malloc(sizeof(ftnmsg)); memset(tmsg, 0, sizeof(ftnmsg)); if (newsmode) { p = xstrcpy(hdr((char *)"Comment-To",msg)); if (p == NULL) p = xstrcpy(hdr((char *)"X-Comment-To",msg)); if (p == NULL) p = xstrcpy(hdr((char *)"X-FTN-To",msg)); if (p == NULL) p = xstrcpy(hdr((char *)"X-Fidonet-Comment-To",msg)); if (p == NULL) p = xstrcpy(hdr((char *)"X-Apparently-To",msg)); if (p == NULL) p = xstrcpy(hdr((char *)"To", msg)); /* 14-Aug-2001 MB */ if (p) { Syslog('m', "Getting `to' address from \"%s\"", MBSE_SS(p)); if ((tmsg->to = parsefaddr(p)) == NULL) tmsg->to = parsefaddr((char *)"[email protected]"); if ((l = strrchr(p,'<')) && (r = strchr(p,'>')) && (l < r)) { r = l; *r-- = '\0'; if ((l = strchr(p,'"')) && (r = strrchr(p,'"')) && (l < r)) { l++; *r-- = '\0'; } while (isspace(*r)) *r-- = '\0'; if (!l) l = p; while (isspace(*l)) l++; } else if ((l = strrchr(p,'(')) && (r = strchr(p,')')) && (l < r)) { *r-- = '\0'; while (isspace(*r)) *r-- = '\0'; l++; while (isspace(*l)) l++; } else { l = p; while (isspace(*l)) l++; r = p + strlen(p) -1; if (*r == '\n') *r-- = '\0'; while (isspace(*r)) *r-- = '\0'; } if (*l) { if (strlen(l) > MAXNAME) l[MAXNAME]='\0'; free(tmsg->to->name); tmsg->to->name=xstrcpy(l); } free(p); /* * It will become echomail, the destination FTN address must * be our address. 14-Aug-2001 MB. */ tmsg->to->zone = msgs.Aka.zone; tmsg->to->net = msgs.Aka.net; tmsg->to->node = msgs.Aka.node; tmsg->to->point = msgs.Aka.point; tmsg->to->domain = xstrcpy(msgs.Aka.domain); } else { /* * Filling a default To: address. */ tmsg->to = (faddr*)malloc(sizeof(faddr)); tmsg->to->name = xstrcpy((char *)"All"); tmsg->to->zone = msgs.Aka.zone; tmsg->to->net = msgs.Aka.net; tmsg->to->node = msgs.Aka.node; tmsg->to->point = msgs.Aka.point; tmsg->to->domain = xstrcpy(msgs.Aka.domain); } } else { if (recipient) { /* * In mbmail mode the recipient is valid and must be used * as the destination address. The To: field is probably * an RFC address an cannot be used to route the message. */ tmsg->to = (faddr *)malloc(sizeof(faddr)); tmsg->to->point = recipient->point; tmsg->to->node = recipient->node; tmsg->to->net = recipient->net; tmsg->to->zone = recipient->zone; tmsg->to->name = xstrcpy(recipient->name); if (tmsg->to->name && (strlen(tmsg->to->name) > MAXNAME)) tmsg->to->name[MAXNAME]='\0'; tmsg->to->domain = xstrcpy(recipient->domain); Syslog('m', "Recipient TO: %s", ascfnode(tmsg->to,0xff)); } else { p = xstrcpy(hdr((char *)"To",msg)); if (p == NULL) p = xstrcpy(hdr((char *)"X-Apparently-To",msg)); if (p) { if ((tmsg->to = parsefaddr(p)) == NULL) WriteError("Unparsable destination address"); else Syslog('m', "RFC parsed TO: %s",ascfnode(tmsg->to,0xff)); } } } /* else (newsmode) */ p = fbuf = xstrcpy(hdr((char *)"Reply-To", msg)); if (fbuf == NULL) p = fbuf = xstrcpy(hdr((char *)"From", msg)); if (fbuf == NULL) p = fbuf = xstrcpy(hdr((char *)"X-UUCP-From", msg)); if (p) { q = p; while (isspace(*q)) q++; fbuf = parserfcaddr(q).remainder; if (parserfcaddr(q).target) { fbuf = xstrcat(fbuf, (char *)"@"); fbuf = xstrcat(fbuf, parserfcaddr(q).target); } rfcfrom = fbuf; } if (p) free(p); p = NULL; if (!rfcfrom) rfcfrom = xstrcpy((char *)"postmaster"); p = fbuf = xstrcpy(hdr((char *)"From", msg)); if (fbuf == NULL) p = fbuf = xstrcpy(hdr((char *)"X-UUCP-From", msg)); if (p) { q = p; while (isspace(*q)) q++; if ((q) && (*q != '\0')) freename = parserfcaddr(q).comment; else freename = NULL; } else freename = xstrcpy((char *)"Unidentified User"); if (freename) { while (isspace(*freename)) freename++; } if (rfcfrom) { while (isspace(*rfcfrom)) rfcfrom++; p = rfcfrom + strlen(rfcfrom) -1; while ((isspace(*p)) || (*p == '\n')) *(p--)='\0'; } if ((freename) && (*freename != '\0')) { while (isspace(*freename)) freename++; p = freename + strlen(freename) -1; while ((isspace(*p)) || (*p == '\n')) *(p--)='\0'; if ((*freename == '\"') && (*(p=freename+strlen(freename)-1) == '\"')) { freename++; *p='\0'; } } // if (*freename == '\0') freename=rfcfrom; if ((!freename) || ((freename) && (*freename == '\0')) || (strcmp(freename,".")==0)) freename=rfcfrom; if (! newsmode) Syslog('+', "from: %s <%s>",freename,rfcfrom); needreplyaddr = 1; if ((tmsg->from=parsefaddr(rfcfrom)) == NULL) { if (freename && rfcfrom) if (!strchr(freename,'@') && !strchr(freename,'%') && strncasecmp(freename,rfcfrom,MAXNAME) && strncasecmp(freename,"uucp",4) && strncasecmp(freename,"usenet",6) && strncasecmp(freename,"news",4) && strncasecmp(freename,"super",5) && strncasecmp(freename,"admin",5) && strncasecmp(freename,"postmaster",10) && strncasecmp(freename,"sys",3)) needreplyaddr=registrate(freename,rfcfrom); } else { tmsg->ftnorigin = 1; tmsg->from->name = xstrcpy(freename); if (strlen(tmsg->from->name) > MAXNAME) tmsg->from->name[MAXNAME]='\0'; } if (replyaddr) { free(replyaddr); replyaddr=NULL; } if (needreplyaddr && (tmsg->from == NULL)) { replyaddr=xstrcpy(rfcfrom); } if (tmsg->from) Syslog('m', "From address was%s distinguished as ftn", tmsg->from ? "" : " not"); if (newsmode) { tmp2 = fido2faddr(msgs.Aka); bestaka = bestaka_s(tmp2); tidy_faddr(tmp2); } else bestaka = bestaka_s(tmsg->to); if ((tmsg->from == NULL) && (bestaka)) { if (CFG.dontregate) { p = xstrcpy(hdr((char *)"X-FTN-Sender",msg)); if (p == NULL) { if ((p = hdr((char *)"X-FTN-From",msg))) { tmp = parsefnode(p); p = xstrcpy(ascinode(tmp, 0xff)); tidy_faddr(tmp); } } if (p) { q = p; while (isspace(*q)) q++; ftnfrom = parserfcaddr(q).remainder; if (parserfcaddr(q).target) { ftnfrom = xstrcat(ftnfrom,(char *)"@"); ftnfrom = xstrcat(ftnfrom,parserfcaddr(q).target); } Syslog('m', "Ftn gateway: \"%s\"", ftnfrom); Syslog('+', "Ftn sender: %s",ftnfrom); if (ftnfrom) tmsg->from = parsefaddr(ftnfrom); if ((tmsg->from) && (!tmsg->from->name)) tmsg->from->name = xstrcpy(rfcfrom); } if (p) free(p); p = NULL; if (tmsg->from == NULL) { tmsg->from=(faddr *)malloc(sizeof(faddr)); tmsg->from->name=xstrcpy(freename); if (tmsg->from->name && (strlen(tmsg->from->name) > MAXNAME)) tmsg->from->name[MAXNAME]='\0'; tmsg->from->point=bestaka->point; tmsg->from->node=bestaka->node; tmsg->from->net=bestaka->net; tmsg->from->zone=bestaka->zone; tmsg->from->domain=xstrcpy(bestaka->domain); } } else { tmsg->from=(faddr *)xmalloc(sizeof(faddr)); tmsg->from->name=xstrcpy(freename); if (tmsg->from->name && (strlen(tmsg->from->name) > MAXNAME)) tmsg->from->name[MAXNAME]='\0'; tmsg->from->point=bestaka->point; tmsg->from->node=bestaka->node; tmsg->from->net=bestaka->net; tmsg->from->zone=bestaka->zone; tmsg->from->domain=xstrcpy(bestaka->domain); } } if (fbuf) free(fbuf); fbuf = NULL; p = hdr((char *)"Subject", msg); if (p) { while (isspace(*p)) p++; tmsg->subj = xstrcpy(p); if (*(p=tmsg->subj+strlen(tmsg->subj)-1) == '\n') *p='\0'; if (strlen(tmsg->subj) > MAXSUBJ) tmsg->subj[MAXSUBJ]='\0'; } else { tmsg->subj = xstrcpy((char *)" "); } if ((p = hdr((char *)"X-FTN-FLAGS",msg))) tmsg->flags |= flagset(p); if (hdr((char *)"Return-Receipt-To",msg)) tmsg->flags |= M_RRQ; if (hdr((char *)"Notice-Requested-Upon-Delivery-To",msg)) tmsg->flags |= M_RRQ; if (!newsmode) { tmsg->flags |= M_PVT; tmsg->flags |= M_KILLSENT; } if ((p = hdr((char *)"X-Origin-Date",msg))) tmsg->date = parsedate(p, NULL) - (gmt_offset((time_t)0) * 60); else if ((p = hdr((char *)"Date",msg))) tmsg->date = parsedate(p, NULL) - (gmt_offset((time_t)0) * 60); else tmsg->date = time((time_t *)NULL); /* * SunMail 1.0 creates invalid date formats like: Wed, 19 Jun 2002 18:21:07 GMT-08:00 * ^---- not allowed. */ if (tmsg->date == -1) { Syslog('!', "Parsing date \"%s\" failed, using current date", p); tmsg->date = time((time_t *)NULL); } if ((p = hdr((char *)"X-FTN-MSGID", msg))) { tmsg->ftnorigin &= 1; while (isspace(*p)) p++; tmsg->msgid_s = xstrcpy(p); if (*(p = tmsg->msgid_s + strlen(tmsg->msgid_s) -1) == '\n') *p='\0'; } else if ((p = hdr((char *)".MSGID",msg))) { tmsg->ftnorigin &= 1; while (isspace(*p)) p++; tmsg->msgid_s = xstrcpy(p); if (*(p = tmsg->msgid_s + strlen(tmsg->msgid_s) -1) == '\n') *p='\0'; } else if ((p = hdr((char *)"Message-ID",msg))) { tmsg->ftnorigin &= ftnmsgid(p,&(tmsg->msgid_a),&(tmsg->msgid_n),tmsg->area); } else tmsg->msgid_a = NULL; if ((p = hdr((char *)"X-FTN-REPLY",msg))) { while (isspace(*p)) p++; tmsg->reply_s = xstrcpy(p); if (*(p=tmsg->reply_s + strlen(tmsg->reply_s) -1) == '\n') *p='\0'; } else { if (newsmode) { p = hdr((char *)"References",msg); if (p) { l = xstrcpy(p); r = strtok(l," \t\n"); while ((l=strtok(NULL," \t\n")) != NULL) r = l; p = r; free(l); } } else p = hdr((char *)"In-Reply-To",msg); } if (p) (void)ftnmsgid(p,&(tmsg->reply_a),&(tmsg->reply_n),NULL); else tmsg->reply_a=NULL; p = hdr((char *)"Organization",msg); if (p == NULL) p = hdr((char *)"Organisation",msg); if (p) { while (isspace(*p)) p++; tmsg->origin = xstrcpy(p); if (tmsg->origin) if (*(p = tmsg->origin + strlen(tmsg->origin)-1) == '\n') *p='\0'; } else { /* * No Organization header, insert the default BBS origin. */ tmsg->origin = xstrcpy(CFG.origin); } return tmsg; }
/* * Post netmail message for temp file. The tempfile is an FTN style message. * * 0 - All seems well. * 1 - Can't access messagebase. * 2 - Can't find netmail board. * */ int postnetmail(FILE *fp, faddr *f, faddr *t, char *orig, char *subject, time_t mdate, int flags, int DoPing, unsigned int fzone, unsigned int tzone) { char *p, *msgid = NULL, *reply = NULL, *flagstr = NULL; char name[37], *buf, *l, *r, *q, System[37], ext[4]; int result = 1, email = FALSE, fmpt = 0, topt = 0; faddr *ta, *ra; fidoaddr na, routeto, Orig; FILE *sfp, *net; time_t now; struct tm *tm; Syslog('m', "Post netmail from: %s", ascfnode(f, 0xff)); Syslog('m', "Post netmail to : %s", ascfnode(t, 0xff)); Syslog('m', "Post netmail subj: %s", MBSE_SS(subject)); net_in++; /* * Extract MSGID and REPLY kludges from this netmail. */ buf = calloc(MAX_LINE_LENGTH +1, sizeof(char)); rewind(fp); while ((fgets(buf, MAX_LINE_LENGTH, fp)) != NULL) { Striplf(buf); Syslogp('M', printable(buf, 0)); if (!strncmp(buf, "\001MSGID: ", 8)) { msgid = xstrcpy(buf + 8); /* * Extra test to see if the mail comes from a pointaddress. */ l = strtok(buf," \n"); l = strtok(NULL," \n"); if ((ta = parsefnode(l))) { if (ta->net == f->net && ta->node == f->node && !fmpt && ta->point) { Syslog('m', "Setting pointinfo (%d) from MSGID", ta->point); fmpt = f->point = ta->point; } if ((ta->net == f->net) && (ta->node == f->node) && (f->zone == 0)) { /* * Missing zone info, maybe later we will see a INTL kludge or so, but for * now, just in case we fix it. And we need that for some Aka collecting * sysop who doesn't know how to configure his system right. */ Syslog('m', "No from zone set, setting zone %d from MSGID", ta->zone); f->zone = ta->zone; /* * 99.9 % chance that the destination zone is also missing. */ if (t->zone == 0) { t->zone = ta->zone; Syslog('m', "No dest zone set, setting zone %d from MSGID", ta->zone); } } tidy_faddr(ta); } if (msgid) free(msgid); msgid = NULL; } if (!strncmp(buf, "\001FMPT", 5)) { p = strtok(buf, " \n"); p = strtok(NULL, " \n"); fmpt = atoi(p); } if (!strncmp(buf, "\001TOPT", 5)) { p = strtok(buf, " \n"); p = strtok(NULL, " \n"); topt = atoi(p); } if (!strncmp(buf, "\001REPLY: ", 8)) reply = xstrcpy(buf + 8); /* * Check DOMAIN and INTL kludges */ if (!strncmp(buf, "\001DOMAIN", 7)) { l = strtok(buf," \n"); l = strtok(NULL," \n"); p = strtok(NULL," \n"); r = strtok(NULL," \n"); q = strtok(NULL," \n"); if ((ta = parsefnode(p))) { t->point = ta->point; t->node = ta->node; t->net = ta->net; t->zone = ta->zone; tidy_faddr(ta); } t->domain = xstrcpy(l); if ((ta = parsefnode(q))) { f->point = ta->point; f->node = ta->node; f->net = ta->net; f->zone = ta->zone; tidy_faddr(ta); } f->domain = xstrcpy(r); } else { if (!strncmp(buf, "\001INTL", 5)) { l = strtok(buf," \n"); l = strtok(NULL," \n"); r = strtok(NULL," \n"); if ((ta = parsefnode(l))) { t->point = ta->point; t->node = ta->node; t->net = ta->net; t->zone = ta->zone; if (ta->domain) { if (t->domain) free(t->domain); t->domain = ta->domain; ta->domain = NULL; } tidy_faddr(ta); } if ((ta = parsefnode(r))) { f->point = ta->point; f->node = ta->node; f->net = ta->net; f->zone = ta->zone; if (ta->domain) { if (f->domain) free(f->domain); f->domain = ta->domain; ta->domain = NULL; } tidy_faddr(ta); } } } /* * Check FLAGS kludge */ if (!strncmp(buf, "\001FLAGS ", 7)) { flagstr = xstrcpy(buf + 7); Syslog('m', "^aFLAGS %s", flagstr); } if (!strncmp(buf, "\001FLAGS: ", 8)) { flagstr = xstrcpy(buf + 8); Syslog('m', "^aFLAGS: %s", flagstr); } /* * Check for X-FTN- kludges, this could be gated email. * This should be impossible. */ if (!strncmp(buf, "\001X-FTN-", 7)) { email = TRUE; Syslog('?', "Warning: detected ^aX-FTN- kludge in netmail"); } } free(buf); /* * Only set point info if there was any info. * GoldED doesn't set FMPT and TOPT kludges. */ if (fmpt) f->point = fmpt; if (topt) t->point = topt; /* * If zone info is still missing, set the defaults which came from the * original mail packet addressing. */ if (fzone && (f->zone == 0)) f->zone = fzone; if (tzone && (t->zone == 0)) t->zone = tzone; l = xstrcpy(ascfnode(f, 0xff)); r = xstrcpy(ascfnode(t, 0xff)); Syslog('+', "Netmail from \"%s\" to \"%s\"", l, r); free(l); free(r); memset(&na, 0, sizeof(na)); na.zone = t->zone; na.net = t->net; na.node = t->node; na.point = t->point; if (SearchFidonet(na.zone)) snprintf(na.domain, 13, "%s", fidonet.domain); switch(TrackMail(na, &routeto)) { case R_LOCAL: /* * Check the To: field. */ if (strchr(t->name, '@') != NULL) { snprintf(name, 36, "%s", strtok(t->name, "@")); snprintf(System, 36, "%s", strtok(NULL, "\000")); email = TRUE; } else { snprintf(name, 36, "%s", t->name); snprintf(System, 36, "%s", CFG.sysdomain); } if (email) { /* * Send this netmail via ftn2rfc -> postemail. */ return result = ftn2rfc(f, t, subject, orig, mdate, flags, fp); } /* * If message to "sysop" or "postmaster" replace it * with the sysops real name. */ if ((strncasecmp(name, "sysop", 5) == 0) || (strcasecmp(name, "postmaster") == 0) || (strcasecmp(name, "coordinator") == 0)) { Syslog('+', " Readdress from %s to %s", name, CFG.sysop_name); snprintf(name, 36, "%s", CFG.sysop_name); } /* * If the message is a service message, check the * services database to see what action is needed. * First make sure that the right noderecord is loaded. */ (void)noderecord(f); p = calloc(PATH_MAX, sizeof(char)); snprintf(p, PATH_MAX, "%s/etc/service.data", getenv("MBSE_ROOT")); if ((sfp = fopen(p, "r")) == NULL) { WriteError("$Can't open %s", p); } else { fread(&servhdr, sizeof(servhdr), 1, sfp); while (fread(&servrec, servhdr.recsize, 1, sfp) == 1) { if ((strncasecmp(servrec.Service, name, strlen(servrec.Service)) == 0) && servrec.Active) { switch (servrec.Action) { case AREAMGR: result = AreaMgr(f, t, msgid, subject, mdate, flags, fp); break; case FILEMGR: result = FileMgr(f, t, msgid, subject, mdate, flags, fp); break; case EMAIL: result = ftn2rfc(f, t, subject, orig, mdate, flags, fp); if (result) { if (result == 2) Bounce(f, t, fp, (char *)"Could not post email"); else Bounce(f, t, fp, (char *)"Could not convert to email"); } break; } Syslog('m', "Handled service %s, rc=%d", servrec.Service, result); fclose(sfp); return result; } } fclose(sfp); } free(p); /* * Ping function */ if (!strcasecmp(name, (char *)"ping") && DoPing) { return Ping(f, t, fp, FALSE); } /* * Check userlist real names, handles, unix names. * Import if one fits. */ if (SearchUser(name)) { return storenet(f, t, mdate, flags, subject, msgid, reply, fp, flagstr); } Syslog('+', " \"%s\" is not a known BBS user", name); /* * Unknown, readdress it to the sysop. */ net_bad++; Syslog('+', " Readdress from %s to %s", name, CFG.sysop_name); snprintf(name, 36, "%s", CFG.sysop_name); if (SearchUser(name)) { return storenet(f, t, mdate, flags, subject, msgid, reply, fp, flagstr); } else { WriteError("Readdress import failed, sysop doesn't exist. CHECK YOUR SETUP"); return 0; } break; case R_DIRECT: case R_ROUTE: Syslog('+', "Route netmail via %s", aka2str(routeto)); if (!strcasecmp(t->name, (char *)"ping") && DoPing) { Syslog('+', "In transit \"Ping\" message detected"); Ping(f, t, fp, TRUE); (void)noderecord(f); } /* * Forward this message. Will not work for unknown * direct links. */ if (SearchNode(routeto)) { memset(&Orig, 0, sizeof(Orig)); ra = fido2faddr(routeto); ta = bestaka_s(ra); Orig.zone = ta->zone; Orig.net = ta->net; Orig.node = ta->node; Orig.point = ta->point; tidy_faddr(ra); tidy_faddr(ta); memset(&ext, 0, sizeof(ext)); if (nodes.PackNetmail) snprintf(ext, 4, (char *)"qqq"); else if (nodes.Crash) snprintf(ext, 4, (char *)"ccc"); else if (nodes.Hold) snprintf(ext, 4, (char *)"hhh"); else snprintf(ext, 4, (char *)"nnn"); if ((net = OpenPkt(Orig , routeto, (char *)ext)) == NULL) { net_bad++; WriteError("Can't create netmail"); return 0; } } else { /* * If it's not a direct link, create a outbound * .pkt anyway, better then that this mail is * lost. It gets the normal status, it might * get delivered during ZMH this way. */ Syslog('!', "Warning: not a direct link, check setup"); memset(&Orig, 0, sizeof(Orig)); ra = fido2faddr(routeto); ta = bestaka_s(ra); Orig.zone = ta->zone; Orig.net = ta->net; Orig.node = ta->node; Orig.point = ta->point; tidy_faddr(ra); tidy_faddr(ta); if ((net = OpenPkt(Orig , routeto, (char *)"nnn")) == NULL) { net_bad++; WriteError("Can't create netmail"); return 0; } } /* * Now start forward. */ Syslog('m', "Net from %s", ascfnode(f, 0xff)); Syslog('m', "Net to %s", ascfnode(t, 0xff)); Syslog('m', "Net flags %08x", flags); Syslog('m', "Net subj %s", subject); if (AddMsgHdr(net, f, t, flags, 0, mdate, t->name, f->name, subject)) { WriteError("Can't write message header"); net_bad++; return 0; } rewind(fp); /* * Copy all text including kludges, when * finished, insert our ^aVia line. */ buf = calloc(MAX_LINE_LENGTH +1, sizeof(char)); while ((fgets(buf, MAX_LINE_LENGTH, fp)) != NULL) fprintf(net, "%s\r", buf); now = time(NULL); tm = gmtime(&now); ta = bestaka_s(t); fprintf(net, "\001Via %s @%d%02d%02d.%02d%02d%02d.UTC mbfido %s\r", ascfnode(ta, 0x1f), tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, VERSION); tidy_faddr(ta); putc(0, net); fclose(net); free(buf); net_out++; Syslog('m', "Forward done."); return 0; default: /* * If we came this far, there's definitly something wrong * with this netmail. */ WriteError("No ROUTE for this netmail"); net_bad++; flags |= M_ORPHAN; return storenet(f, t, mdate, flags, subject, msgid, reply, fp, flagstr); break; } /* Never reached */ return result; }
/* * Check TIC group AREAS file if requested area exists. * If so, create tic area and if SendUplink is TRUE, * send the uplink a FileMgr request to connect this area. * The tic group record (fgroup) must be in memory. * Return codes: * 0 - All Seems Well * 1 - Some error * * The current nodes record may be destroyed after this, * make sure it is saved. */ int CheckTicGroup(char *Area, int SendUplink, faddr *f) { char *temp, *buf, *tag = NULL, *desc = NULL, *p, *raid = NULL, *flow = NULL; FILE *ap, *mp, *fp; int offset, AreaNr; int i, rc = 0, Found = FALSE; sysconnect System; faddr *From, *To; struct _fdbarea *fdb_area = NULL; temp = calloc(PATH_MAX, sizeof(char)); Syslog('f', "Checking file group \"%s\" \"%s\"", fgroup.Name, fgroup.Comment); snprintf(temp, PATH_MAX, "%s/%s", CFG.alists_path , fgroup.AreaFile); if ((ap = fopen(temp, "r")) == NULL) { WriteError("Filegroup %s: area taglist %s not found", fgroup.Name, temp); free(temp); return 1; } buf = calloc(4097, sizeof(char)); if (fgroup.FileGate) { /* * filegate.zxx format */ while (fgets(buf, 4096, ap)) { /* * Each filegroup starts with "% FDN: Filegroup Description" */ if (strlen(buf) && !strncmp(buf, "% FDN:", 6)) { tag = strtok(buf, "\t \r\n\0"); p = strtok(NULL, "\t \r\n\0"); p = strtok(NULL, "\r\n\0"); desc = p; while ((*desc == ' ') || (*desc == '\t')) desc++; if (!strcmp(desc, fgroup.Comment)) { while (fgets(buf, 4096, ap)) { if (!strncasecmp(buf, "Area ", 5)) { tag = strtok(buf, "\t \r\n\0"); tag = strtok(NULL, "\t \r\n\0"); if (!strcasecmp(tag, Area)) { raid = strtok(NULL, "\t \r\n\0"); flow = strtok(NULL, "\t \r\n\0"); p = strtok(NULL, "\r\n\0"); desc = p; while ((*desc == ' ') || (*desc == '\t')) desc++; Syslog('f', "Found area \"%s\" \"%s\" \"%s\" \"%s\"", tag, raid, flow, desc); Found = TRUE; break; } } if (strlen(buf) && !strncmp(buf, "% FDN:", 6)) { /* * All entries in group are seen, the area wasn't there. */ break; } } } if (Found) break; } } } else { /* * Normal taglist format */ while (fgets(buf, 4096, ap)) { if (strlen(buf) && isalnum(buf[0])) { tag = strtok(buf, "\t \r\n\0"); p = strtok(NULL, "\r\n\0"); if (p == NULL) p = tag; /* If no description after the TAG, use TAG as description */ desc = p; while ((*desc == ' ') || (*desc == '\t')) desc++; if (strcasecmp(tag, Area) == 0) { Syslog('f', "Found tag \"%s\" desc \"%s\"", tag, desc); Found = TRUE; break; } } } } if (!Found) { Syslog('f', "Area %s not found in taglist", Area); free(buf); fclose(ap); free(temp); return 1; } /* * Some people write taglists with lowercase tagnames... */ for (i = 0; i < strlen(tag); i++) tag[i] = toupper(tag[i]); Syslog('m', "Found tag \"%s\" desc \"%s\"", tag, desc); /* * Area is in AREAS file, now create area. * If needed, connect at uplink. */ if (SendUplink && SearchNode(fgroup.UpLink)) { if (nodes.UplFmgrBbbs) snprintf(temp, PATH_MAX, "file +%s", tag); else snprintf(temp, PATH_MAX, "+%s", tag); From = fido2faddr(fgroup.UseAka); To = fido2faddr(fgroup.UpLink); if (UplinkRequest(To, From, TRUE, temp)) { WriteError("Can't send netmail to uplink"); fclose(ap); free(buf); free(temp); tidy_faddr(From); tidy_faddr(To); return 1; } tidy_faddr(From); tidy_faddr(To); } /* * Open tic area and set filepointer to the end to append * a new record. */ snprintf(temp, PATH_MAX, "%s/etc/tic.data", getenv("MBSE_ROOT")); if ((mp = fopen(temp, "r+")) == NULL) { WriteError("$Can't open %s", temp); fclose(ap); free(buf); free(temp); return 1; } fread(&tichdr, sizeof(tichdr), 1, mp); fseek(mp, 0, SEEK_END); memset(&tic, 0, sizeof(tic)); Syslog('f', "TIC area open, filepos %ld", ftell(mp)); /* * Open files area, and find a free slot */ snprintf(temp, PATH_MAX, "%s/etc/fareas.data", getenv("MBSE_ROOT")); if ((fp = fopen(temp, "r+")) == NULL) { WriteError("$Can't open %s", temp); fclose(ap); fclose(mp); free(buf); free(temp); return 1; } fread(&areahdr, sizeof(areahdr), 1, fp); Syslog('f', "File area is open"); /* * Verify the file is large enough */ fseek(fp, 0, SEEK_END); offset = areahdr.hdrsize + ((fgroup.StartArea -1) * (areahdr.recsize)); Syslog('+', "file end at %ld, offset needed %ld", ftell(fp), offset); if (ftell(fp) < offset) { Syslog('f', "Database too small, expanding..."); memset(&area, 0, sizeof(area)); while (TRUE) { fwrite(&area, sizeof(area), 1, fp); if (ftell(fp) >= areahdr.hdrsize + ((fgroup.StartArea -1) * (areahdr.recsize))) break; } } if (fseek(fp, offset, SEEK_SET)) { WriteError("$Can't seek in %s to position %ld", temp, offset); fclose(ap); fclose(mp); fclose(fp); free(buf); free(temp); return 1; } /* * Search a free record */ Syslog('f', "Start search record"); while (fread(&area, sizeof(area), 1, fp) == 1) { if (!area.Available) { fseek(fp, - areahdr.recsize, SEEK_CUR); rc = 1; break; } } if (!rc) { Syslog('f', "No free slot, append after last record"); fseek(fp, 0, SEEK_END); if (ftell(fp) < areahdr.hdrsize + ((fgroup.StartArea -1) * (areahdr.recsize))) { Syslog('f', "Database too small, expanding..."); memset(&area, 0, sizeof(area)); while (TRUE) { fwrite(&area, sizeof(area), 1, fp); if (ftell(fp) >= areahdr.hdrsize + ((fgroup.StartArea -1) * (areahdr.recsize))) break; } } rc = 1; } AreaNr = ((ftell(fp) - areahdr.hdrsize) / (areahdr.recsize)) + 1; Syslog('f', "Found free slot at %ld", AreaNr); /* * Create the records */ memset(&area, 0, sizeof(area)); strncpy(area.Name, desc, 44); strcpy(temp, tag); temp = tl(temp); for (i = 0; i < strlen(temp); i++) if (temp[i] == '.') temp[i] = '/'; snprintf(area.Path, 81, "%s/%s", fgroup.BasePath, temp); area.DLSec = fgroup.DLSec; area.UPSec = fgroup.UPSec; area.LTSec = fgroup.LTSec; area.New = area.Dupes = area.Free = area.AddAlpha = area.FileFind = area.Available = area.FileReq = TRUE; strncpy(area.BbsGroup, fgroup.BbsGroup, 12); strncpy(area.NewGroup, fgroup.AnnGroup, 12); strncpy(area.Archiver, fgroup.Convert, 5); area.Upload = fgroup.Upload; fwrite(&area, sizeof(area), 1, fp); fclose(fp); /* * Create download path */ snprintf(temp, PATH_MAX, "%s/foobar", area.Path); if (!mkdirs(temp, 0775)) WriteError("Can't create %s", temp); /* * Create download database */ if ((fdb_area = mbsedb_OpenFDB(AreaNr, 30))) mbsedb_CloseFDB(fdb_area); /* * Setup new TIC area. */ strncpy(tic.Name, tag, 20); strncpy(tic.Comment, desc, 55); tic.FileArea = AreaNr; strncpy(tic.Group, fgroup.Name, 12); tic.AreaStart = time(NULL); tic.Aka = fgroup.UseAka; strncpy(tic.Convert, fgroup.Convert, 5); strncpy(tic.Banner, fgroup.Banner, 14); tic.Replace = fgroup.Replace; tic.DupCheck = fgroup.DupCheck; tic.Secure = fgroup.Secure; tic.Touch = fgroup.Touch; tic.VirScan = fgroup.VirScan; tic.Announce = fgroup.Announce; tic.UpdMagic = fgroup.UpdMagic; tic.FileId = fgroup.FileId; tic.ConvertAll = fgroup.ConvertAll; tic.SendOrg = fgroup.SendOrg; tic.Active = TRUE; tic.LinkSec.level = fgroup.LinkSec.level; tic.LinkSec.flags = fgroup.LinkSec.flags; tic.LinkSec.notflags = fgroup.LinkSec.notflags; fwrite(&tic, sizeof(tic), 1, mp); memset(&System, 0, sizeof(System)); System.aka = fgroup.UpLink; if (flow && !strcmp(flow, "*&")) /* * Areas direction HQ's go the other way */ System.sendto = TRUE; else /* * Normal distribution areas. */ System.receivefrom = TRUE; fwrite(&System, sizeof(System), 1, mp); memset(&System, 0, sizeof(System)); for (i = 1; i < (tichdr.syssize / sizeof(System)); i++) fwrite(&System, sizeof(System), 1, mp); fclose(mp); fclose(ap); free(buf); free(temp); if (f == NULL) Mgrlog("Auto created TIC area %s, group %s, bbs area %ld", tic.Name, tic.Group, AreaNr); else Mgrlog("Auto created TIC area %s, group %s, bbs area %ld, for node %s", tic.Name, tic.Group, AreaNr, ascfnode(f, 0x1f)); return 0; }
int Post(char *To, int Area, char *Subj, char *File, char *Flavor) { int i, rc = FALSE, has_tear = FALSE, has_origin = FALSE; char *aka, *temp, *sAreas; FILE *fp, *tp; unsigned int crc = -1; time_t tt; struct tm *t; ftnd_CleanSubject(Subj); if (!do_quiet) { ftnd_colour(CYAN, BLACK); printf("Post \"%s\" to \"%s\" in area %d\n", File, To, Area); } IsDoing("Posting"); Syslog('+', "Post \"%s\" area %d to \"%s\" flavor %s", File, Area, To, Flavor); Syslog('+', "Subject: \"%s\"", Subj); if ((tp = fopen(File, "r")) == NULL) { WriteError("$Can't open %s", File); if (!do_quiet) printf("Can't open \"%s\"\n", File); return -1; } sAreas = calloc(PATH_MAX, sizeof(char)); snprintf(sAreas, PATH_MAX, "%s/etc/mareas.data", getenv("FTND_ROOT")); if ((fp = fopen(sAreas, "r")) == NULL) { WriteError("$Can't open %s", sAreas); free(sAreas); fclose(tp); return -1; } fread(&msgshdr, sizeof(msgshdr), 1, fp); if (fseek(fp, (msgshdr.recsize + msgshdr.syssize) * (Area - 1), SEEK_CUR) == 0) { if (fread(&msgs, msgshdr.recsize, 1, fp) == 1) { rc = TRUE; } else { WriteError("$Can't read area %ld", Area); } } else { WriteError("$Can't seek area %ld", Area); } free(sAreas); if (rc == FALSE) { fclose(fp); fclose(tp); return -1; } if (!msgs.Active) { WriteError("Area %s not active", msgs.Name); fclose(fp); fclose(tp); return -1; } /* * Check the proper syntax in the To parameter, in netmail areas * it must have a destination address, in all other areas just a * full name. */ if (msgs.Type == NETMAIL) { if ((strchr(To, '@') == NULL) || (strstr(To, (char *)".n") == NULL) || (strstr(To, (char *)".z") == NULL)) { WriteError("No address in \"%s\" and area is netmail", To); if (!do_quiet) printf("No address in \"%s\" and area is netmail\n", To); fclose(fp); fclose(tp); return -1; } } else { if ((strchr(To, '@')) || (strstr(To, (char *)".n")) || (strstr(To, (char *)".z"))) { WriteError("Address present in \"%s\" and area is not netmail", To); if (!do_quiet) printf("Address present in \"%s\" and area is not netmail\n", To); fclose(fp); fclose(tp); return -1; } } if (!Msg_Open(msgs.Base)) { WriteError("Can't open %s", msgs.Base); fclose(fp); fclose(tp); return -1; } if (!Msg_Lock(30L)) { WriteError("Can't lock %s", msgs.Base); Msg_Close(); fclose(fp); fclose(tp); return -1; } tt = time(NULL); t = localtime(&tt); Diw = t->tm_wday; Miy = t->tm_mon; memset(&Msg, 0, sizeof(Msg)); Msg_New(); /* * Update statistic counter for message area */ fseek(fp, - msgshdr.recsize, SEEK_CUR); msgs.Posted.total++; msgs.Posted.tweek++; msgs.Posted.tdow[Diw]++; msgs.Posted.month[Miy]++; fwrite(&msgs, msgshdr.recsize, 1, fp); fclose(fp); /* * Start writing the message */ snprintf(Msg.From, 101, CFG.sysop_name); snprintf(Msg.To, 101, To); /* * If netmail, clean the To field. */ if ((msgs.Type == NETMAIL) && strchr(To, '@')) { for (i = 0; i < strlen(Msg.To); i++) { if (Msg.To[i] == '_') Msg.To[i] = ' '; if (Msg.To[i] == '@') { Msg.To[i] = '\0'; break; } } } snprintf(Msg.Subject, 101, "%s", Subj); snprintf(Msg.FromAddress, 101, "%s", aka2str(msgs.Aka)); Msg.Written = Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); Msg.Local = TRUE; if (strchr(Flavor, 'c')) Msg.Crash = TRUE; if (strchr(Flavor, 'p')) Msg.Private = TRUE; if (strchr(Flavor, 'h')) Msg.Hold = TRUE; switch (msgs.Type) { case LOCALMAIL: Msg.Localmail = TRUE; break; case NETMAIL: Msg.Netmail = TRUE; snprintf(Msg.ToAddress, 101, "%s", ascfnode(parsefaddr(To), 0xff)); break; case ECHOMAIL: Msg.Echomail = TRUE; break; case NEWS: Msg.News = TRUE; break; } temp = calloc(PATH_MAX, sizeof(char)); snprintf(temp, PATH_MAX, "\001MSGID: %s %08x", aka2str(msgs.Aka), sequencer()); MsgText_Add2(temp); Msg.MsgIdCRC = upd_crc32(temp, crc, strlen(temp)); Msg.ReplyCRC = 0xffffffff; snprintf(temp, PATH_MAX, "\001PID: FTND-FIDO %s (%s-%s)", VERSION, OsName(), OsCPU()); MsgText_Add2(temp); if (msgs.Charset != FTNC_NONE) { snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(msgs.Charset)); } else { snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(FTNC_LATIN_1)); } MsgText_Add2(temp); snprintf(temp, PATH_MAX, "\001TZUTC: %s", gmtoffset(tt)); MsgText_Add2(temp); while ((Fgets(temp, PATH_MAX, tp)) != NULL) { if (strncmp(temp, "--- ", 4) == 0) has_tear = TRUE; if (strncmp(temp, " * Origin: ", 11) == 0) has_origin = TRUE; } rewind(tp); Syslog('m', "has tearline=%s, has origin=%s", has_tear?"True":"False", has_origin?"True":"False"); /* * Add the file as text */ Msg_Write(tp); fclose(tp); /* * Finish the message */ if ((! has_tear) && (! has_origin)) { MsgText_Add2((char *)""); MsgText_Add2(TearLine()); } if (! has_origin) { aka = calloc(40, sizeof(char)); if (msgs.Aka.point) snprintf(aka, 40, "(%d:%d/%d.%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node, msgs.Aka.point); else snprintf(aka, 40, "(%d:%d/%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node); if (strlen(msgs.Origin)) snprintf(temp, 81, " * Origin: %s %s", msgs.Origin, aka); else snprintf(temp, 81, " * Origin: %s %s", CFG.origin, aka); MsgText_Add2(temp); free(aka); } Msg_AddMsg(); Msg_UnLock(); Syslog('+', "Posted message %ld", Msg.Id); if (msgs.Type != LOCALMAIL) { snprintf(temp, PATH_MAX, "%s/tmp/%smail.jam", getenv("FTND_ROOT"), (msgs.Type == ECHOMAIL) ? "echo" : "net"); if ((fp = fopen(temp, "a")) != NULL) { fprintf(fp, "%s %u\n", msgs.Base, Msg.Id); fclose(fp); } CreateSema((char *)"mailout"); } free(temp); Msg_Close(); return 0; }
/* * Start a netmail to one of our nodes in the setup. * Return a file descriptor if success else NULL. * Later the pack routine will add these mails to the outbound. */ FILE *SendMgrMail(faddr *t, int Keep, int FileAttach, char *bymgr, char *subj, char *reply) { FILE *qp; time_t Now; fidoaddr Orig, Dest; faddr From; unsigned flags = M_PVT; char ext[4]; From = *bestaka_s(t); memset(&Orig, 0, sizeof(Orig)); Orig.zone = From.zone; Orig.net = From.net; Orig.node = From.node; Orig.point = From.point; snprintf(Orig.domain, 13, "%s", From.domain); memset(&Dest, 0, sizeof(Dest)); Dest.zone = t->zone; Dest.net = t->net; Dest.node = t->node; Dest.point = t->point; snprintf(Dest.domain, 13, "%s", t->domain); if (!SearchNode(Dest)) { Syslog('!', "SendMgrMail(): Can't find node %s", aka2str(Dest)); return NULL; } Syslog('m', " Netmail from %s to %s", aka2str(Orig), ascfnode(t, 0x1f)); Now = time(NULL) - (gmt_offset((time_t)0) * 60); flags |= (nodes.Crash) ? M_CRASH : 0; flags |= (FileAttach) ? M_FILE : 0; flags |= (nodes.Hold) ? M_HOLD : 0; /* * Increase counters, update record and reload. */ StatAdd(&nodes.MailSent, 1L); UpdateNode(); SearchNode(Dest); memset(&ext, 0, sizeof(ext)); if (nodes.PackNetmail) snprintf(ext, 4, (char *)"qqq"); else if (nodes.Crash) snprintf(ext, 4, (char *)"ccc"); else if (nodes.Hold) snprintf(ext, 4, (char *)"hhh"); else snprintf(ext, 4, (char *)"nnn"); if ((qp = OpenPkt(Orig, Dest, (char *)ext)) == NULL) return NULL; if (AddMsgHdr(qp, &From, t, flags, 0, Now, nodes.Sysop, tlcap(bymgr), subj)) { fclose(qp); return NULL; } if (Dest.point) fprintf(qp, "\001TOPT %d\r", Dest.point); if (Orig.point) fprintf(qp, "\001FMPT %d\r", Orig.point); fprintf(qp, "\001INTL %d:%d/%d %d:%d/%d\r", Dest.zone, Dest.net, Dest.node, Orig.zone, Orig.net, Orig.node); /* * Add MSGID, REPLY and PID */ fprintf(qp, "\001MSGID: %s %08x\r", aka2str(Orig), sequencer()); if (reply != NULL) fprintf(qp, "\001REPLY: %s\r", reply); fprintf(qp, "\001PID: MBSE-FIDO %s (%s-%s)\r", VERSION, OsName(), OsCPU()); fprintf(qp, "\001TZUTC: %s\r", gmtoffset(Now)); return qp; }
int tx_yoohoo(void) { int rc; unsigned short capabilities; char *pwd; y_akas = 0; if (strlen(nodes.Spasswd)) pwd = xstrcpy(nodes.Spasswd); else pwd = NULL; capabilities = LOCALCAPS; if (localoptions & NOZMODEM) capabilities &= ~(ZED_ZAPPER|ZED_ZIPPER); if (localoptions & NOZEDZAP) capabilities &= ~ZED_ZAPPER; if (localoptions & NOHYDRA) capabilities &= ~DOES_HYDRA; if ((localoptions & NOFREQS) == 0) capabilities |= WZ_FREQ; else emsi_local_opts |= OPT_NRQ; fillhello(capabilities,pwd); iscaller=1; if ((rc = txyoohoo()) == 0) { rc = rxyoohoo(); checkhello(); capabilities = hello2.capabilities; if (capabilities & WZ_FREQ) session_flags |= SESSION_WAZOO; else session_flags &= ~SESSION_WAZOO; } if (y_akas == 0) { Syslog('+', "All akas busy, abort"); return FTNERR_SESSION_ERROR; } if ((rc == 0) && ((capabilities & LOCALCAPS) == 0)) { Syslog('+', "No common protocols"); return FTNERR_SESSION_ERROR; } if (rc) return FTNERR_YOOHOO; IsDoing("Outbound %s", ascfnode(remote->addr, 0x0f)); session_state = STATE_SECURE; session_flags |= SESSION_WAZOO; if (capabilities & DOES_HYDRA) return hydra(1); else if ((capabilities & ZED_ZAPPER) || (capabilities & ZED_ZIPPER)) { if (capabilities & ZED_ZAPPER) emsi_local_protos = PROT_ZAP; else emsi_local_protos = PROT_ZMO; return txwazoo(); } else if (capabilities & Y_DIETIFNA) return txdietifna(); WriteError("YooHoo internal error - no proto for 0x%04xh",capabilities); return FTNERR_YOOHOO; }
int rx_yoohoo(void) { int rc, protect = FALSE; unsigned short capabilities,localcaps; char *pwd = NULL; callstat *cst; pwd = NULL; y_akas = 0; localcaps = LOCALCAPS; if (localoptions & NOZMODEM) localcaps &= ~(ZED_ZAPPER|ZED_ZIPPER); if (localoptions & NOZEDZAP) localcaps &= ~ZED_ZAPPER; if (localoptions & NOHYDRA) localcaps &= ~DOES_HYDRA; emsi_local_opts = 0; emsi_remote_opts = 0; iscaller = 0; if ((rc = rxyoohoo()) == 0) { Loaded = checkhello(); if (y_akas == 0) { Syslog('+', "All akas busy, abort"); return FTNERR_SESSION_ERROR; } capabilities = hello2.capabilities; if (capabilities & WZ_FREQ) session_flags |= SESSION_WAZOO; else session_flags &= ~SESSION_WAZOO; localcaps &= capabilities; if (localcaps & DOES_HYDRA) localcaps &= DOES_HYDRA; else if (localcaps & ZED_ZAPPER) localcaps &= ZED_ZAPPER; else if (localcaps & ZED_ZIPPER) localcaps &= ZED_ZIPPER; else if (localcaps & FTB_USER) localcaps &= FTB_USER; else if (localcaps & Y_DIETIFNA) localcaps &= Y_DIETIFNA; if ((localoptions & NOFREQS) == 0) localcaps |= WZ_FREQ; else emsi_local_opts |= OPT_NRQ; if (((nlent=getnlent(remote->addr))) && (nlent->pflag != NL_DUMMY)) { Syslog('+', "Remote is a listed system"); strncpy(history.location, nlent->location, 35); UserCity(mypid, nlent->sysop, nlent->location); } cst = getstatus(remote->addr); if (cst->trystat) laststat = cst->trystat; Syslog('s', "Last session status %d", laststat); if (nlent) rdoptions(Loaded); if (strlen(nodes.Spasswd)) { if ((strncasecmp((char*)hello2.my_password, nodes.Spasswd, strlen(nodes.Spasswd)) == 0) && (strlen((char*)hello2.my_password) == strlen(nodes.Spasswd))) { Syslog('+', "Password correct, protected mail session"); protect = TRUE; pwd = xstrcpy(nodes.Spasswd); } else { if (pwd) free(pwd); pwd = xstrcpy((char *)"BAD_PASS"); Syslog('?', "Remote password \"%s\", expected \"%s\"", (char*)hello2.my_password, nodes.Spasswd); localcaps = 0; } } else Syslog('s', "No YooHoo password check"); inbound_open(remote->addr, protect, FALSE); fillhello(localcaps,pwd); rc = txyoohoo(); if (pwd) free(pwd); } if ((rc == 0) && ((localcaps & LOCALCAPS) == 0)) { Syslog('+', "No common protocols or bad password"); return 0; } if (rc) return FTNERR_YOOHOO; IsDoing("Inbound %s", ascfnode(remote->addr, 0x0f)); if (protect) session_state = STATE_SECURE; else session_state = STATE_UNSECURE; session_flags |= SESSION_WAZOO; if (localcaps & DOES_HYDRA) return hydra(0); else if ((localcaps & ZED_ZAPPER) || (localcaps & ZED_ZIPPER)) { if (localcaps & ZED_ZAPPER) emsi_local_protos = PROT_ZAP; else emsi_local_protos = PROT_ZMO; return rxwazoo(); } else if (localcaps & Y_DIETIFNA) return rxdietifna(); WriteError("YooHoo internal error - no proto for 0x%04xh",localcaps); return FTNERR_YOOHOO; }
/* * Input a RFC news message. */ int rfc2ftn(FILE *fp) { char sbe[16], *p, *q, *temp, *origin, newsubj[4 * (MAXSUBJ+1)], *oldsubj; int i, rc, newsmode, seenlen, oldnet; rfcmsg *msg = NULL, *tmsg, *tmp; ftnmsg *fmsg = NULL; FILE *ofp, *qfp; fa_list *sbl = NULL, *ptl = NULL, *tmpl; faddr *ta, *fta; int sot_kludge = FALSE, eot_kludge = FALSE, tinyorigin = FALSE; int needsplit, hdrsize, datasize, splitpart, forbidsplit, rfcheaders; time_t Now; struct tm *l_date; char *charset = NULL; temp = calloc(4097, sizeof(char)); Syslog('m', "Entering rfc2ftn"); rewind(fp); msg = parsrfc(fp); newsmode = hdr((char *)"Newsgroups", msg) ?TRUE:FALSE; if (newsmode == FALSE) { WriteError("Not a news article"); return 1; } if ((fmsg = mkftnhdr(msg, newsmode, NULL)) == NULL) { WriteError("Unable to create FTN headers from RFC ones, aborting"); tidyrfc(msg); return 1; } fmsg->area = xstrcpy(msgs.Tag); if ((p = hdr((char *)"Message-ID",msg))) { ftnmsgid(p, &fmsg->msgid_a, &fmsg->msgid_n, fmsg->area); hash_update_s(&fmsg->msgid_n, fmsg->area); } if ((p = hdr((char *)"References",msg))) { p = strrchr(p,' '); ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); //Griffin fmsg->reply_s=calloc(256,sizeof(char)); findorigmsg(p,fmsg->reply_s); fmsg->to->name=calloc(strlen(Msg.From)+1,sizeof(char)); strcpy(fmsg->to->name,Msg.From); Syslog('m', "fmsg to-name %s",fmsg->to->name); Syslog('m', "reply_s %s",fmsg->reply_s); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } else if ((p = hdr((char *)"In-Reply-To",msg))) { ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } chkftnmsgid(hdr((char *)"Message-ID",msg)); // ?? removemime = FALSE; removemsgid = FALSE; removeref = FALSE; removeinreply = FALSE; removereplyto = TRUE; removereturnto = TRUE; ftnorigin = fmsg->ftnorigin; q = hdr((char *)"Content-Transfer-Encoding",msg); if (q) while (*q && isspace(*q)) q++; if (!(q)) q = (char *)"8bit"; if ((p = hdr((char *)"Content-Type",msg))) { while (*p && isspace(*p)) p++; /* * Check for mime to remove. */ if ((strncasecmp(p, "text/plain", 10) == 0) && ((q == NULL) || (strncasecmp(q,"7bit",4) == 0) || (strncasecmp(q,"8bit",4) == 0))) { removemime = TRUE; /* no need in MIME headers */ } q = strtok(p, " \n\0"); q = strtok(NULL, "; \n\0"); if (q) { while (*q && isspace(*q)) q++; Syslog('m', "charset part: %s", printable(q, 0)); if (q && (strncasecmp(q, "charset=", 8) == 0)) { /* * google.com quotes the charset name */ if (strchr(q, '"')) { charset = xstrcpy(q + 9); charset[strlen(charset)-1] = '\0'; Syslog('m', "Unquoted charset name"); } else { charset = xstrcpy(q + 8); } Syslog('m', "Charset \"%s\"", printable(charset, 0)); } } } if (charset == NULL) { charset = xstrcpy((char *)"ISO-8859-1"); Syslog('m', "No charset, setting default to iso-8859-1"); } chartran_init(charset, get_ic_ftn(msgs.Charset), 'm'); if ((p = hdr((char *)"Message-ID",msg))) { if (!removemsgid) removemsgid = chkftnmsgid(p); } if ((!removeref) && (p = hdr((char *)"References",msg))) { p = xstrcpy(p); q = strtok(p," \t\n"); if ((q) && (strtok(NULL," \t\n") == NULL)) removeref = chkftnmsgid(q); free(p); } if ((p = hdr((char *)"Reply-To",msg))) { removereplyto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while(*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereplyto = TRUE; } } if ((p = hdr((char *)"Return-Receipt-To",msg))) { removereturnto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while (*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereturnto = TRUE; } } Syslog('m', "removemime=%s removemsgid=%s removeref=%s removeinreply=%s removereplyto=%s removereturnto=%s", removemime ?"TRUE ":"FALSE", removemsgid ?"TRUE ":"FALSE", removeref ?"TRUE ":"FALSE", removeinreply ?"TRUE ":"FALSE", removereplyto ?"TRUE ":"FALSE", removereturnto ?"TRUE ":"FALSE"); p = ascfnode(fmsg->from,0x1f); i = 79-11-3-strlen(p); if (ftnorigin && fmsg->origin && (strlen(fmsg->origin) > i)) { /* This is a kludge... I don't like it too much. But well, if this is a message of FTN origin, the original origin (:) line MUST have been short enough to fit in 79 chars... So we give it a try. Probably it would be better to keep the information about the address format from the origin line in a special X-FTN-... header, but this seems even less elegant. Any _good_ ideas, anyone? */ /* OK, I am keeping this, though if should never be used al long as X-FTN-Origin is used now */ p = ascfnode(fmsg->from,0x0f); Syslog('m', "checkorigin 3"); i = 79-11-3-strlen(p); tinyorigin = TRUE; } if (tinyorigin) Syslog('m', "tinyorigin = %s", tinyorigin ? "True":"False"); if ((fmsg->origin) && (strlen(fmsg->origin) > i)) fmsg->origin[i]='\0'; forbidsplit = (ftnorigin || ((p = hdr((char *)"X-FTN-Split",msg)) && (strcasecmp(p," already\n") == 0))); needsplit = 0; splitpart = 0; hdrsize = 20; hdrsize += (fmsg->subj)?strlen(fmsg->subj):0; if (fmsg->from) hdrsize += (fmsg->from->name)?strlen(fmsg->from->name):0; if (fmsg->to) hdrsize += (fmsg->to->name)?strlen(fmsg->to->name):0; do { Syslog('m', "split loop, splitpart = %d", splitpart); datasize = 0; if (splitpart) { snprintf(newsubj,4 * (MAXSUBJ+1),"[part %d] ",splitpart+1); strncat(newsubj,fmsg->subj,MAXSUBJ-strlen(newsubj)); } else { strncpy(newsubj,fmsg->subj,MAXSUBJ); } newsubj[MAXSUBJ]='\0'; if (splitpart) { hash_update_n(&fmsg->msgid_n,splitpart); } oldsubj = fmsg->subj; fmsg->subj = newsubj; /* * Create a new temp message in FTN style format */ if ((ofp = tmpfile()) == NULL) { WriteError("$Can't open second tmpfile"); tidyrfc(msg); return 1; } if ((fmsg->msgid_a == NULL) && (fmsg->msgid_n == 0)) { Syslog('n', "No Messageid from poster, creating new MSGID"); fprintf(ofp, "\001MSGID: %s %08x\n", aka2str(msgs.Aka), sequencer()); } else { fprintf(ofp, "\001MSGID: %s %08x\n", MBSE_SS(fmsg->msgid_a),fmsg->msgid_n); } if (fmsg->reply_s) fprintf(ofp, "\1REPLY: %s\n", fmsg->reply_s); else if (fmsg->reply_a) fprintf(ofp, "\1REPLY: %s %08x\n", fmsg->reply_a, fmsg->reply_n); Now = time(NULL) - (gmt_offset((time_t)0) * 60); fprintf(ofp, "\001TZUTC: %s\n", gmtoffset(Now)); fprintf(ofp, "\001CHRS: %s\n", getftnchrs(msgs.Charset)); fmsg->subj = oldsubj; if ((p = hdr((char *)"X-FTN-REPLYADDR",msg))) { hdrsize += 10+strlen(p); fprintf(ofp,"\1REPLYADDR:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 10+strlen(replyaddr); fprintf(ofp,"\1REPLYADDR: "); kludgewrite(replyaddr,ofp); } if ((p = hdr((char *)"X-FTN-REPLYTO",msg))) { hdrsize += 8+strlen(p); fprintf(ofp,"\1REPLYTO:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 15; if (newsmode) fprintf(ofp,"\1REPLYTO: %s UUCP\n", aka2str(msgs.Aka)); else { fta = bestaka_s(fmsg->to); fprintf(ofp,"\1REPLYTO: %s UUCP\n", ascfnode(fta, 0x1f)); tidy_faddr(fta); } } else if ((p = hdr((char *)"Reply-To",msg))) { if ((ta = parsefaddr(p))) { if ((q = hdr((char *)"From",msg))) { if (!strcasestr(q,p)) { fprintf(ofp,"\1REPLYTO: %s %s\n", ascfnode(ta,0x1f), ta->name); } } tidy_faddr(ta); } } if ((p=strip_flags(hdr((char *)"X-FTN-FLAGS",msg)))) { hdrsize += 15; fprintf(ofp,"\1FLAGS:%s\n",p); free(p); } if (!hdr((char *)"X-FTN-PID", msg)) { p = hdr((char *)"User-Agent", msg); if (p == NULL) p = hdr((char *)"X-Newsreader", msg); if (p == NULL) p = hdr((char *)"X-Mailer", msg); if (p) { hdrsize += 4 + strlen(p); fprintf(ofp, "\1PID:"); kludgewrite(p, ofp); } else { fprintf(ofp, "\001PID: MBSE-NNTPD %s (%s-%s)\n", VERSION, OsName(), OsCPU()); } } if (!(hdr((char *)"X-FTN-Tearline", msg)) && !(hdr((char *)"X-FTN-TID", msg))) { snprintf(temp, 4096, " MBSE-NNTPD %s (%s-%s)", VERSION, OsName(), OsCPU()); hdrsize += 4 + strlen(temp); fprintf(ofp, "\1TID:"); kludgewrite(temp, ofp); } if ((splitpart == 0) || (hdrsize < MAXHDRSIZE)) { for (tmp = msg; tmp; tmp = tmp->next) { if ((!strncmp(tmp->key,"X-Fsc-",6)) || (!strncmp(tmp->key,"X-FTN-",6) && strcasecmp(tmp->key,"X-FTN-Tearline") && strcasecmp(tmp->key,"X-FTN-Origin") && strcasecmp(tmp->key,"X-FTN-Sender") && strcasecmp(tmp->key,"X-FTN-Split") && strcasecmp(tmp->key,"X-FTN-FLAGS") && strcasecmp(tmp->key,"X-FTN-AREA") && strcasecmp(tmp->key,"X-FTN-MSGID") && strcasecmp(tmp->key,"X-FTN-REPLY") && strcasecmp(tmp->key,"X-FTN-SEEN-BY") && strcasecmp(tmp->key,"X-FTN-PATH") && strcasecmp(tmp->key,"X-FTN-REPLYADDR") && strcasecmp(tmp->key,"X-FTN-REPLYTO") && strcasecmp(tmp->key,"X-FTN-To") && strcasecmp(tmp->key,"X-FTN-From") && strcasecmp(tmp->key,"X-FTN-CHARSET") && strcasecmp(tmp->key,"X-FTN-CHRS") && strcasecmp(tmp->key,"X-FTN-CODEPAGE") && strcasecmp(tmp->key,"X-FTN-ORIGCHRS") && strcasecmp(tmp->key,"X-FTN-SOT") && strcasecmp(tmp->key,"X-FTN-EOT") && strcasecmp(tmp->key,"X-FTN-Via"))) { if ((strcasecmp(tmp->key,"X-FTN-KLUDGE") == 0)) { if (!strcasecmp(tmp->val," SOT:\n")) sot_kludge = TRUE; else if (!strcasecmp(tmp->val," EOT:\n")) eot_kludge = TRUE; else { hdrsize += strlen(tmp->val); fprintf(ofp,"\1"); /* we should have restored the original string here... */ kludgewrite((tmp->val)+1,ofp); } } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+6); kludgewrite(tmp->val,ofp); } } } /* ZConnect are X-ZC-*: in usenet, \1ZC-*: in FTN */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,"X-ZC-",5))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+2); kludgewrite(tmp->val,ofp); } /* mondo.org gateway uses ".MSGID: ..." in usenet */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,".",1)) && (strcasecmp(tmp->key,".MSGID"))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+1); kludgewrite(tmp->val,ofp); } for (tmp = msg; tmp; tmp = tmp->next) { if ((needputrfc(tmp, newsmode) == 1)) { if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"\1RFC-Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1RFC-%s:",tmp->key); } kludgewrite(tmp->val, ofp); } } rfcheaders=0; for (tmp=msg;tmp;tmp=tmp->next) { if ((needputrfc(tmp, newsmode) > 1)) { rfcheaders++; if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"%s:",tmp->key); } charwrite(tmp->val, ofp); } } if (rfcheaders) charwrite((char *)"\n",ofp); if ((hdr((char *)"X-FTN-SOT",msg)) || (sot_kludge)) fprintf(ofp,"\1SOT:\n"); } if (replyaddr) { replyaddr = NULL; } if (needsplit) { fprintf(ofp," * Continuation %d of a split message *\n\n", splitpart); needsplit = FALSE; } else if ((p=hdr((char *)"X-Body-Start",msg))) { datasize += strlen(p); charwrite(p, ofp); } while (!(needsplit=(!forbidsplit) && (((splitpart && (datasize > (CFG.new_split * 1024))) || (!splitpart && ((datasize+hdrsize) > (CFG.new_split * 1024)))))) && (bgets(temp,4096-1,fp))) { datasize += strlen(temp); charwrite(temp, ofp); } if (needsplit) { fprintf(ofp,"\n * Message split, to be continued *\n"); splitpart++; } if ((p=hdr((char *)"X-FTN-EOT",msg)) || (eot_kludge)) fprintf(ofp,"\1EOT:\n"); if ((p=hdr((char *)"X-FTN-Tearline",msg))) { fprintf(ofp,"---"); if (strcasecmp(p," (none)\n") == 0) charwrite((char *)"\n",ofp); else charwrite(p,ofp); } else fprintf(ofp,"\n%s\n", TearLine()); if ((p = hdr((char *)"X-FTN-Origin",msg))) { if (*(q=p+strlen(p)-1) == '\n') *q='\0'; origin = xstrcpy((char *)" * Origin: "); origin = xstrcat(origin, p); } else { origin = xstrcpy((char *)" * Origin: "); if (fmsg->origin) origin = xstrcat(origin, fmsg->origin); else origin = xstrcat(origin, CFG.origin); origin = xstrcat(origin, (char *)" ("); origin = xstrcat(origin, ascfnode(fmsg->from,tinyorigin?0x0f:0x1f)); origin = xstrcat(origin, (char *)")"); } fprintf(ofp, "%s", origin); if (newsmode) { /* * Setup SEEN-BY lines, first SEEN-BY from RFC message, then all matching AKA's */ for (tmsg = msg; tmsg; tmsg = tmsg->next) if (strcasecmp(tmsg->key, "X-FTN-SEEN-BY") == 0) fill_list(&sbl, tmsg->val, NULL); for (i = 0; i < 40; i++) { if (CFG.akavalid[i] && (CFG.aka[i].point == 0) && (msgs.Aka.zone == CFG.aka[i].zone) && !((msgs.Aka.net == CFG.aka[i].net) && (msgs.Aka.node == CFG.aka[i].node))) { snprintf(sbe, 16, "%u/%u", CFG.aka[i].net, CFG.aka[i].node); fill_list(&sbl, sbe, NULL); } } if (msgs.Aka.point == 0) { snprintf(sbe, 16, "%u/%u", msgs.Aka.net, msgs.Aka.node); fill_list(&sbl, sbe, NULL); } /* * Only add SEEN-BY lines if there are any */ if (sbl != NULL) { uniq_list(&sbl); sort_list(&sbl); seenlen = MAXSEEN + 1; memset(&sbe, 0, sizeof(sbe)); /* ensure it will not match for the first entry */ oldnet = sbl->addr->net-1; for (tmpl = sbl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,16," %u",tmpl->addr->node); else snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXSEEN) { seenlen = 0; fprintf(ofp,"\nSEEN-BY:"); snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&sbl); } /* * Setup PATH lines */ for (tmp = msg; tmp; tmp = tmp->next) if (!strcasecmp(tmp->key,"X-FTN-PATH")) fill_path(&ptl,tmp->val); if (msgs.Aka.point == 0) { snprintf(sbe,16,"%u/%u",msgs.Aka.net, msgs.Aka.node); fill_path(&ptl,sbe); } /* * Only add PATH line if there is something */ if (ptl != NULL) { uniq_list(&ptl); seenlen = MAXPATH+1; /* ensure it will not match for the first entry */ oldnet = ptl->addr->net-1; for (tmpl = ptl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,16," %u",tmpl->addr->node); else snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXPATH) { seenlen = 0; fprintf(ofp,"\n\1PATH:"); snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&ptl); } } /* if (newsmode) */ /* * Add newline and message is ready. */ fprintf(ofp,"\n"); fflush(ofp); rewind(ofp); Syslog('m', "========== Fido start"); while (fgets(temp, 4096, ofp) != NULL) { /* * Only log kludges, skip the body */ if ((temp[0] == '\001') || !strncmp(temp, "AREA:", 5) || !strncmp(temp, "SEEN-BY", 7)) { Striplf(temp); Syslogp('m', printable(temp, 0)); } } Syslog('m', "========== Fido end"); if (!Msg_Open(msgs.Base)) { WriteError("Failed to open msgbase \"%s\"", msgs.Base); } else { if (!Msg_Lock(30L)) { WriteError("Can't lock %s", msgs.Base); } else { Msg_New(); strcpy(Msg.From, fmsg->from->name); strcpy(Msg.To, fmsg->to->name); strcpy(Msg.FromAddress, ascfnode(fmsg->from,0x1f)); strcpy(Msg.Subject, fmsg->subj); Msg.Written = Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); Msg.Local = TRUE; rewind(ofp); while (fgets(temp, 4096, ofp) != NULL) { Striplf(temp); MsgText_Add2(temp); } Msg_AddMsg(); Msg_UnLock(); Syslog('+', "Msg (%ld) to \"%s\", \"%s\"", Msg.Id, Msg.To, Msg.Subject); do_mailout = TRUE; /* * Create fast scan index */ snprintf(temp, PATH_MAX, "%s/tmp/echomail.jam", getenv("MBSE_ROOT")); if ((qfp = fopen(temp, "a")) != NULL) { fprintf(qfp, "%s %u\n", msgs.Base, Msg.Id); fclose(qfp); } /* * Link messages */ rc = Msg_Link(msgs.Base, TRUE, CFG.slow_util); if (rc != -1) Syslog('+', "Linked %d message%s", rc, (rc != 1) ? "s":""); else Syslog('+', "Could not link messages"); /* * Update statistical counters */ Now = time(NULL); l_date = localtime(&Now); msgs.LastPosted = time(NULL); msgs.Posted.total++; msgs.Posted.tweek++; msgs.Posted.tdow[l_date->tm_wday]++; msgs.Posted.month[l_date->tm_mon]++; mgroup.LastDate = time(NULL); mgroup.MsgsSent.total++; mgroup.MsgsSent.tweek++; mgroup.MsgsSent.tdow[l_date->tm_wday]++; mgroup.MsgsSent.month[l_date->tm_mon]++; UpdateMsgs(); snprintf(temp, PATH_MAX, "%s/etc/users.data", getenv("MBSE_ROOT")); if ((qfp = fopen(temp, "r+"))) { fread(&usrconfighdr, sizeof(usrconfighdr), 1, qfp); fseek(qfp, usrconfighdr.hdrsize + (grecno * usrconfighdr.recsize), SEEK_SET); if (fread(&usrconfig, usrconfighdr.recsize, 1, qfp) == 1) { usrconfig.iPosted++; fseek(qfp, usrconfighdr.hdrsize + (grecno * usrconfighdr.recsize), SEEK_SET); fwrite(&usrconfig, usrconfighdr.recsize, 1, qfp); } fclose(qfp); } } Msg_Close(); } free(origin); fclose(ofp); } while (needsplit); free(temp); if (charset) free(charset); chartran_close(); tidyrfc(msg); tidy_ftnmsg(fmsg); UpdateMsgs(); return 0; }
char *route(char *adr0) { FILE *f1; char *a1; int i=0; char adr1[100]; char *adr2=adr1; char *adrp; char *routeadr; tfaddr=parsefaddr(adr0); adr2=ascfnode(tfaddr, 0x6); if (strcmp(adr2, my_addr) == 0) return(adr0); f1=fopen(ROUTE_CFG,"r"); while(fgets(adr[i],100,f1) != NULL) { a[i]=adr[i]; i++; } if(i==0) i++; a[i]=NULL; /* i=0; while(a[i]!=NULL) printf("%s",a[i++]); */ fclose(f1); /* printf("\n%s\n", adr2);*/ if ((adrp=strchr(adr2, '.')) != NULL) *adrp='\0'; if ((routeadr=routea(adr2)) == NULL) { adrp=(strchr(adr2, '/')); *(adrp+1)='*'; *(adrp+2)='\0'; if ((routeadr=routea(adr2)) == NULL) { strcpy(adr2, "*/*"); if ((routeadr=routea(adr2)) == NULL) { printf("\nerror in route table\n"); } } } if (routeadr != NULL) { strcpy(adr1, routeadr); tfaddr=parsefnode(adr1); routeadr=adr1; routeadr=ascinode(tfaddr, 0x6); } /* printf("\nrouteaddr = %s\n", routeadr);*/ return(routeadr); }
file_list *create_filelist(fa_list *al, char *fl, int create) { file_list *st = NULL, *tmpf; fa_list *tmpa; char flavor, *tmpfl, *nm, *temp, tmpreq[13], digit[6], *temp2; struct stat stbuf; int packets = 0; FILE *fp; unsigned char buffer[2]; faddr *fa; DIR *dp = NULL; struct dirent *de; struct stat sb; Syslog('o', "Create_filelist(%s,\"%s\",%d)", al?ascfnode(al->addr,0x1f):"<none>", MBSE_SS(fl), create); made_request = 0; for (tmpa = al; tmpa; tmpa = tmpa->next) { Syslog('o', "Check address %s", ascfnode(tmpa->addr, 0x1f)); /* * For the main aka, check the outbox. */ if ((tmpa->addr) && Loaded && strlen(nodes.OutBox) && (tmpa->addr->zone == nodes.Aka[0].zone) && (tmpa->addr->net == nodes.Aka[0].net) && (tmpa->addr->node == nodes.Aka[0].node) && (tmpa->addr->point == nodes.Aka[0].point)) { check_filebox(nodes.OutBox, &st); } /* * Check spool files, these are more or less useless but they * create a filelist of files to send which are never send. * It gives the transfer protocols something "to do". */ if (strchr(fl, 'o')) { nm = splname(tmpa->addr); if ((fp = fopen(nm, "w"))) fclose(fp); if ((nm != NULL) && (stat(nm, &stbuf) == 0)) add_list(&st, nm, NULL, DSF, 0L, NULL, 1); } /* * Check .pol files */ nm = polname(tmpa->addr); if ((nm != NULL) && (stat(nm,&stbuf) == 0)) add_list(&st,nm,NULL,DSF,0L,NULL,1); /* * Check other files, all flavors */ tmpfl = fl; while ((flavor = *tmpfl++)) { Syslog('o', "Check flavor %c", flavor); /* * Check normal mail packets */ nm = pktname(tmpa->addr,flavor); if ((nm != NULL) && (stat(nm,&stbuf) == 0)) { Syslog('o', "found %s", nm); packets++; add_list(&st, nm, tmpkname(), KFS, 0L, NULL, 1); } /* * Check .flo files for file attaches */ nm = floname(tmpa->addr,flavor); check_flo(&st, nm); } if ((session_flags & SESSION_WAZOO) && ((session_flags & SESSION_HYDRA) == 0) && (master || ((session_flags & SESSION_IFNA) == 0))) { /* * we don't distinguish flavoured reqs */ nm = reqname(tmpa->addr); if ((nm != NULL) && (stat(nm, &stbuf) == 0)) { snprintf(tmpreq, 13, "%04X%04X.REQ", tmpa->addr->net, tmpa->addr->node); add_list(&st, nm, tmpreq, DSF, 0L, NULL, 1); made_request = 1; } } } /* * Check T-Mail style fileboxes */ temp = calloc(PATH_MAX, sizeof(char)); if (strlen(CFG.tmailshort) && (dp = opendir(CFG.tmailshort))) { Syslog('o', "Checking T-Mail short box \"%s\"", CFG.tmailshort); while ((de = readdir(dp))) { if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { snprintf(temp, PATH_MAX -1, "%s/%s", CFG.tmailshort, de->d_name); if (stat(temp, &sb) == 0) { Syslog('o' ,"checking \"%s\"", de->d_name); if (S_ISDIR(sb.st_mode)) { int i; char b=0; for (i=0; (i<8) && (!b); ++i) { char c = tolower(de->d_name[i]); if ( (c<'0') || (c>'v') || ((c>'9') && (c<'a')) ) b=1; } if (de->d_name[8]!='.') b=1; for (i=9; (i<11) && (!b); ++i) { char c = tolower(de->d_name[i]); if ( (c<'0') || (c>'v') || ((c>'9') && (c<'a')) ) b=1; } if (b) continue; if (de->d_name[11]==0) flavor='o'; else if ((tolower(de->d_name[11])=='h') && (de->d_name[12]==0)) flavor='h'; else continue; fa = (faddr*)malloc(sizeof(faddr)); fa->name = NULL; fa->domain = NULL; memset(&digit, 0, sizeof(digit)); digit[0] = de->d_name[0]; digit[1] = de->d_name[1]; fa->zone = strtol(digit, NULL, 32); memset(&digit, 0, sizeof(digit)); digit[0] = de->d_name[2]; digit[1] = de->d_name[3]; digit[2] = de->d_name[4]; fa->net = strtol(digit, NULL, 32); memset(&digit, 0, sizeof(digit)); digit[0] = de->d_name[5]; digit[1] = de->d_name[6]; digit[2] = de->d_name[7]; fa->node = strtol(digit, NULL, 32); memset(&digit, 0, sizeof(digit)); digit[0] = de->d_name[9]; digit[1] = de->d_name[10]; fa->point = strtol(digit, NULL, 32); for (tmpa = al; tmpa; tmpa = tmpa->next) { if ((fa->zone==tmpa->addr->zone) && (fa->net==tmpa->addr->net) && (fa->node==tmpa->addr->node) && (fa->point==tmpa->addr->point) && strchr(fl, flavor)) if (SearchFidonet(tmpa->addr->zone)) check_filebox(temp, &st); } tidy_faddr(fa); } } } } closedir(dp); } if (strlen(CFG.tmaillong) && (dp = opendir(CFG.tmaillong))) { temp2 = calloc(PATH_MAX, sizeof(char)); Syslog('o', "Checking T-Mail long box \"%s\"", CFG.tmaillong); while ((de = readdir(dp))) { if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { snprintf(temp, PATH_MAX -1, "%s/%s", CFG.tmaillong, de->d_name); if (stat(temp, &sb) == 0) { Syslog('o' ,"checking \"%s\"", de->d_name); if (S_ISDIR(sb.st_mode)) { char c, d; int n; snprintf(temp2, PATH_MAX -1, "%s", de->d_name); fa = (faddr*)malloc(sizeof(faddr)); fa->name = NULL; fa->domain = NULL; n = sscanf(temp2, "%u.%u.%u.%u.%c%c", &(fa->zone), &(fa->net), &(fa->node), &(fa->point), &c, &d); if ((n==4) || ((n==5) && (tolower(c)=='h'))) { if (n==4) flavor = 'o'; else flavor = 'h'; for (tmpa = al; tmpa; tmpa = tmpa->next) { if ((fa->zone==tmpa->addr->zone) && (fa->net==tmpa->addr->net) && (fa->node==tmpa->addr->node) && (fa->point==tmpa->addr->point) && strchr(fl, flavor)) if (SearchFidonet(tmpa->addr->zone)) check_filebox(temp, &st); } } tidy_faddr(fa); } } } } closedir(dp); free(temp2); } free(temp); /* * For FTS-0001 we need to create at least one packet. */ if (((st == NULL) && (create > 1)) || ((st != NULL) && (packets == 0) && (create > 0))) { Syslog('o', "Create packet for %s", ascfnode(al->addr,0x1f)); if ((fp = openpkt(NULL, al->addr, 'o', TRUE))) { memset(&buffer, 0, sizeof(buffer)); fwrite(buffer, 1, 2, fp); fclose(fp); } add_list(&st, pktname(al->addr,'o'), tmpkname(), KFS, 0L, NULL, 0); } for (tmpf = st; tmpf; tmpf = tmpf->next) Syslog('o',"flist: \"%s\" -> \"%s\" dsp:%d flofp:%p floff:%p", MBSE_SS(tmpf->local), MBSE_SS(tmpf->remote), tmpf->disposition, tmpf->flofp, tmpf->floff); return st; }
/* * Input a RFC message. */ int rfc2ftn(FILE *fp, faddr *recipient) { char sbe[128], *p, *q, *temp, *origin, newsubj[4 * (MAXSUBJ+1)], *oldsubj, *acup_a = NULL, *charset = NULL; int i, rc, newsmode, seenlen, oldnet, chars_in = FTNC_NONE, chars_out = FTNC_NONE; rfcmsg *msg = NULL, *tmsg, *tmp; ftnmsg *fmsg = NULL; FILE *ofp; fa_list *sbl = NULL, *ptl = NULL, *tmpl; faddr *ta, *fta; unsigned int acup_n = 0; int sot_kludge = FALSE, eot_kludge = FALSE, tinyorigin = FALSE; int needsplit, hdrsize, datasize, splitpart, forbidsplit, rfcheaders; time_t Now; temp = calloc(MAXHDRSIZE +1, sizeof(char)); Syslog('m', "Entering rfc2ftn"); if (recipient) Syslog('m', "Recipient: %s", ascfnode(recipient, 0xff)); rewind(fp); msg = parsrfc(fp); newsmode = hdr((char *)"Newsgroups", msg) ?TRUE:FALSE; Syslog('m', "RFC message is %s", newsmode ? "news article":"e-mail message"); if (newsmode) { news_in++; snprintf(currentgroup, 81, "%s", msgs.Newsgroup); } else email_in++; if (!CFG.allowcontrol) { if (hdr((char *)"Control",msg)) { Syslog('+', "Rfc2ftn: Control message skipped"); tidyrfc(msg); return 1; } } if ((fmsg = mkftnhdr(msg, newsmode, recipient)) == NULL) { WriteError("Rfc2ftn: unable to create FTN headers from RFC ones, aborting"); tidyrfc(msg); return 1; } if (newsmode) fmsg->area = xstrcpy(msgs.Tag); if ((p = hdr((char *)"Message-ID",msg))) { ftnmsgid(p, &fmsg->msgid_a, &fmsg->msgid_n, fmsg->area); hash_update_s(&fmsg->msgid_n, fmsg->area); } if ((p = hdr((char *)"References",msg))) { p = strrchr(p,' '); ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } else if ((p = hdr((char *)"In-Reply-To",msg))) { ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } chkftnmsgid(hdr((char *)"Message-ID",msg)); // ?? removemime = FALSE; removemsgid = FALSE; removeref = FALSE; removeinreply = FALSE; removereplyto = TRUE; removereturnto = TRUE; ftnorigin = fmsg->ftnorigin; q = hdr((char *)"Content-Transfer-Encoding",msg); if (q) while (*q && isspace(*q)) q++; if (!(q)) q = (char *)"8bit"; if ((p = hdr((char *)"Content-Type",msg))) { while (*p && isspace(*p)) p++; /* * Check for mime to remove. */ if ((strncasecmp(p, "text/plain", 10) == 0) && ((q == NULL) || (strncasecmp(q,"7bit",4) == 0) || (strncasecmp(q,"8bit",4) == 0))) { removemime = TRUE; /* no need in MIME headers */ } q = strtok(p, " \n\0"); q = strtok(NULL, "; \n\0"); if (q) { while (*q && isspace(*q)) q++; Syslog('m', "charset part: %s", printable(q, 0)); if (q && (strncasecmp(q, "charset=", 8) == 0)) { /* * google.com quotes the charset name */ if (strchr(q, '"')) { charset = xstrcpy(q + 9); charset[strlen(charset)-1] = '\0'; } else { charset = xstrcpy(q + 8); } Syslog('m', "Charset \"%s\"", printable(charset, 0)); } } } if (charset == NULL) { charset = xstrcpy((char *)"ISO-8859-1"); Syslog('m', "No charset, setting default to ISO-8859-1"); } if ((p = hdr((char *)"Message-ID",msg))) { if (!removemsgid) removemsgid = chkftnmsgid(p); } if ((!removeref) && (p = hdr((char *)"References",msg))) { p = xstrcpy(p); q = strtok(p," \t\n"); if ((q) && (strtok(NULL," \t\n") == NULL)) removeref = chkftnmsgid(q); free(p); } if ((p = hdr((char *)"Reply-To",msg))) { removereplyto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while(*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereplyto = TRUE; } } if ((p = hdr((char *)"Return-Receipt-To",msg))) { removereturnto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while (*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereturnto = TRUE; } } Syslog('m', "removemime=%s removemsgid=%s removeref=%s removeinreply=%s removereplyto=%s removereturnto=%s", removemime ?"TRUE ":"FALSE", removemsgid ?"TRUE ":"FALSE", removeref ?"TRUE ":"FALSE", removeinreply ?"TRUE ":"FALSE", removereplyto ?"TRUE ":"FALSE", removereturnto ?"TRUE ":"FALSE"); p = ascfnode(fmsg->from,0x1f); i = 79-11-3-strlen(p); if (ftnorigin && fmsg->origin && (strlen(fmsg->origin) > i)) { /* This is a kludge... I don't like it too much. But well, if this is a message of FTN origin, the original origin (:) line MUST have been short enough to fit in 79 chars... So we give it a try. Probably it would be better to keep the information about the address format from the origin line in a special X-FTN-... header, but this seems even less elegant. Any _good_ ideas, anyone? */ /* OK, I am keeping this, though if should never be used al long as X-FTN-Origin is used now */ p = ascfnode(fmsg->from,0x0f); Syslog('m', "checkorigin 3"); i = 79-11-3-strlen(p); tinyorigin = TRUE; } if (tinyorigin) Syslog('m', "tinyorigin = %s", tinyorigin ? "True":"False"); if ((fmsg->origin) && (strlen(fmsg->origin) > i)) fmsg->origin[i]='\0'; forbidsplit = (ftnorigin || ((p = hdr((char *)"X-FTN-Split",msg)) && (strcasecmp(p," already\n") == 0))); needsplit = 0; splitpart = 0; hdrsize = 20; hdrsize += (fmsg->subj)?strlen(fmsg->subj):0; if (fmsg->from) hdrsize += (fmsg->from->name)?strlen(fmsg->from->name):0; if (fmsg->to) hdrsize += (fmsg->to->name)?strlen(fmsg->to->name):0; chars_in = find_rfc_charset(charset); chars_out = msgs.Charset; if (chars_in == FTNC_ERROR) { /* * Not in standard tables, go ahead with the uppercase name * and see if iconv will take it. It doesn't really matter if * we support the incoming rfc charset, */ tu(charset); Syslog('m', "rfc2ftn: charset in: %s charset out: %s", charset, get_ic_ftn(chars_out)); chartran_init(charset, get_ic_ftn(chars_out), 'm'); } else { Syslog('m', "rfc2ftn: charset in: %s charset out: %s", get_ic_rfc(chars_in), get_ic_ftn(chars_out)); chartran_init(get_ic_rfc(chars_in), get_ic_ftn(chars_out), 'm'); } do { Syslog('m', "rfc2ftn: split loop, splitpart = %d", splitpart); datasize = 0; if (splitpart) { snprintf(newsubj,4 * MAXSUBJ,"[part %d] ",splitpart+1); strncat(newsubj,fmsg->subj,MAXSUBJ-strlen(newsubj)); Syslog('+', "Rfc2ftn: split message part %d", splitpart); } else { strncpy(newsubj,fmsg->subj,MAXSUBJ); } newsubj[MAXSUBJ]='\0'; if (splitpart) { hash_update_n(&fmsg->msgid_n,splitpart); } oldsubj = fmsg->subj; fmsg->subj = newsubj; /* * Create a new temp message in FTN style format */ if ((ofp = tmpfile()) == NULL) { WriteError("$Rfc2ftn: Can't open second tmpfile"); tidyrfc(msg); return 1; } if (newsmode) { fprintf(ofp, "AREA:%s\n", msgs.Tag); } else { if (fmsg->to->point != 0) fprintf(ofp, "\001TOPT %d\n", fmsg->to->point); if (fmsg->from->point != 0) fprintf(ofp, "\001FMPT %d\n", fmsg->from->point); fprintf(ofp, "\001INTL %d:%d/%d %d:%d/%d\n", fmsg->to->zone, fmsg->to->net, fmsg->to->node, fmsg->from->zone, fmsg->from->net, fmsg->from->node); } if ((fmsg->msgid_a == NULL) || (fmsg->msgid_n == 0)) { Syslog('!', "Rfc2ftn: warning, no MSGID %s %08lx", MBSE_SS(fmsg->msgid_a), fmsg->msgid_n); } fprintf(ofp, "\001MSGID: %s %08x\n", MBSE_SS(fmsg->msgid_a),fmsg->msgid_n); if (fmsg->reply_s) fprintf(ofp, "\1REPLY: %s\n", fmsg->reply_s); else if (fmsg->reply_a) fprintf(ofp, "\1REPLY: %s %08x\n", fmsg->reply_a, fmsg->reply_n); Now = time(NULL) - (gmt_offset((time_t)0) * 60); fprintf(ofp, "\001TZUTC: %s\n", gmtoffset(Now)); fprintf(ofp, "\001CHRS: %s\n", getftnchrs(msgs.Charset)); fmsg->subj = oldsubj; if ((p = hdr((char *)"X-FTN-REPLYADDR",msg))) { hdrsize += 10+strlen(p); fprintf(ofp,"\1REPLYADDR:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 10+strlen(replyaddr); fprintf(ofp,"\1REPLYADDR: "); kludgewrite(replyaddr,ofp); } if ((p = hdr((char *)"X-FTN-REPLYTO",msg))) { hdrsize += 8+strlen(p); fprintf(ofp,"\1REPLYTO:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 15; if (newsmode) fprintf(ofp,"\1REPLYTO: %s UUCP\n", aka2str(msgs.Aka)); else { fta = bestaka_s(fmsg->to); fprintf(ofp,"\1REPLYTO: %s UUCP\n", ascfnode(fta, 0x1f)); tidy_faddr(fta); } } else if ((p = hdr((char *)"Reply-To",msg))) { if ((ta = parsefaddr(p))) { if ((q = hdr((char *)"From",msg))) { if (!strcasestr(q,p)) { fprintf(ofp,"\1REPLYTO: %s %s\n", ascfnode(ta,0x1f), ta->name); } } tidy_faddr(ta); } } if ((p=strip_flags(hdr((char *)"X-FTN-FLAGS",msg)))) { hdrsize += 15; fprintf(ofp,"\1FLAGS:%s\n",p); free(p); } if (!hdr((char *)"X-FTN-PID", msg)) { p = hdr((char *)"User-Agent", msg); if (p == NULL) p = hdr((char *)"X-Newsreader", msg); if (p == NULL) p = hdr((char *)"X-Mailer", msg); if (p) { hdrsize += 4 + strlen(p); fprintf(ofp, "\1PID:"); kludgewrite(p, ofp); } else { fprintf(ofp, "\001PID: MBSE-FIDO %s (%s-%s)\n", VERSION, OsName(), OsCPU()); } } if (CFG.allowcontrol && (!hdr((char *)"X-FTN-ACUPDATE",msg)) && (p=hdr((char *)"Control",msg))) { if (strstr(p,"cancel")) { ftnmsgid(p,&acup_a,&acup_n,fmsg->area); if (acup_a) { hash_update_s(&acup_n,fmsg->area); hdrsize += 26 + strlen(acup_a); fprintf(ofp,"\1ACUPDATE: DELETE %s %08x\n", acup_a,acup_n); } } } if ((!hdr((char *)"X-FTN-ACUPDATE",msg)) && (p=hdr((char *)"Supersedes",msg))) { ftnmsgid(p,&acup_a,&acup_n,fmsg->area); if (acup_a) { hash_update_s(&acup_n,fmsg->area); hdrsize += 26 + strlen(acup_a); fprintf(ofp,"\1ACUPDATE: MODIFY %s %08x\n", acup_a,acup_n); } } if (!(hdr((char *)"X-FTN-Tearline", msg)) && !(hdr((char *)"X-FTN-TID", msg))) { snprintf(temp, MAXHDRSIZE, " MBSE-FIDO %s (%s-%s)", VERSION, OsName(), OsCPU()); hdrsize += 4 + strlen(temp); fprintf(ofp, "\1TID:"); kludgewrite(temp, ofp); } if ((splitpart == 0) || (hdrsize < MAXHDRSIZE)) { for (tmp = msg; tmp; tmp = tmp->next) { if ((!strncmp(tmp->key,"X-Fsc-",6)) || (!strncmp(tmp->key,"X-FTN-",6) && strcasecmp(tmp->key,"X-FTN-Tearline") && strcasecmp(tmp->key,"X-FTN-Origin") && strcasecmp(tmp->key,"X-FTN-Sender") && strcasecmp(tmp->key,"X-FTN-Split") && strcasecmp(tmp->key,"X-FTN-FLAGS") && strcasecmp(tmp->key,"X-FTN-AREA") && strcasecmp(tmp->key,"X-FTN-MSGID") && strcasecmp(tmp->key,"X-FTN-REPLY") && strcasecmp(tmp->key,"X-FTN-SEEN-BY") && strcasecmp(tmp->key,"X-FTN-PATH") && strcasecmp(tmp->key,"X-FTN-REPLYADDR") && strcasecmp(tmp->key,"X-FTN-REPLYTO") && strcasecmp(tmp->key,"X-FTN-To") && strcasecmp(tmp->key,"X-FTN-From") && strcasecmp(tmp->key,"X-FTN-CHARSET") && strcasecmp(tmp->key,"X-FTN-CHRS") && strcasecmp(tmp->key,"X-FTN-CODEPAGE") && strcasecmp(tmp->key,"X-FTN-ORIGCHRS") && strcasecmp(tmp->key,"X-FTN-SOT") && strcasecmp(tmp->key,"X-FTN-EOT") && strcasecmp(tmp->key,"X-FTN-Via"))) { if ((strcasecmp(tmp->key,"X-FTN-KLUDGE") == 0)) { if (!strcasecmp(tmp->val," SOT:\n")) sot_kludge = TRUE; else if (!strcasecmp(tmp->val," EOT:\n")) eot_kludge = TRUE; else { hdrsize += strlen(tmp->val); fprintf(ofp,"\1"); /* we should have restored the original string here... */ kludgewrite((tmp->val)+1,ofp); } } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+6); kludgewrite(tmp->val,ofp); } } } /* ZConnect are X-ZC-*: in usenet, \1ZC-*: in FTN */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,"X-ZC-",5))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+2); kludgewrite(tmp->val,ofp); } /* mondo.org gateway uses ".MSGID: ..." in usenet */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,".",1)) && (strcasecmp(tmp->key,".MSGID"))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+1); kludgewrite(tmp->val,ofp); } /* * Add the Received: header from this system to the mesage. */ if (!newsmode) { Now = time(NULL); fprintf(ofp, "\1RFC-Received: by %s (mbfido) via RFC2FTN; %s\n", CFG.sysdomain, rfcdate(Now)); hdrsize += 72+strlen(CFG.sysdomain); } for (tmp = msg; tmp; tmp = tmp->next) { if ((needputrfc(tmp, newsmode) == 1)) { if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"\1RFC-Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1RFC-%s:",tmp->key); } kludgewrite(tmp->val, ofp); } } rfcheaders=0; for (tmp=msg;tmp;tmp=tmp->next) { if ((needputrfc(tmp, newsmode) > 1)) { rfcheaders++; if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"%s:",tmp->key); } charwrite(tmp->val, ofp); } } if (rfcheaders) charwrite((char *)"\n",ofp); if ((hdr((char *)"X-FTN-SOT",msg)) || (sot_kludge)) fprintf(ofp,"\1SOT:\n"); } if (replyaddr) { replyaddr = NULL; } if (needsplit) { fprintf(ofp," * Continuation %d of a split message *\n\n", splitpart); needsplit = FALSE; } else if ((p=hdr((char *)"X-Body-Start",msg))) { datasize += strlen(p); charwrite(p, ofp); } while (!(needsplit=(!forbidsplit) && (((splitpart && (datasize > (CFG.new_split * 1024))) || (!splitpart && ((datasize+hdrsize) > (CFG.new_split * 1024)))))) && (bgets(temp,4096-1,fp))) { datasize += strlen(temp); charwrite(temp, ofp); } if (needsplit) { fprintf(ofp,"\n * Message split, to be continued *\n"); splitpart++; } if ((p=hdr((char *)"X-FTN-EOT",msg)) || (eot_kludge)) fprintf(ofp,"\1EOT:\n"); if ((p=hdr((char *)"X-FTN-Tearline",msg))) { fprintf(ofp,"---"); if (strcasecmp(p," (none)\n") == 0) charwrite((char *)"\n",ofp); else charwrite(p,ofp); } else fprintf(ofp,"\n%s\n", TearLine()); if ((p = hdr((char *)"X-FTN-Origin",msg))) { if (*(q=p+strlen(p)-1) == '\n') *q='\0'; origin = xstrcpy((char *)" * Origin: "); origin = xstrcat(origin, p); } else { origin = xstrcpy((char *)" * Origin: "); if (fmsg->origin) origin = xstrcat(origin, fmsg->origin); else origin = xstrcat(origin, CFG.origin); origin = xstrcat(origin, (char *)" ("); origin = xstrcat(origin, ascfnode(fmsg->from,tinyorigin?0x0f:0x1f)); origin = xstrcat(origin, (char *)")"); } fprintf(ofp, "%s", origin); if (newsmode) { /* * Setup SEEN-BY lines, first SEEN-BY from RFC message, then all matching AKA's */ for (tmsg = msg; tmsg; tmsg = tmsg->next) if (strcasecmp(tmsg->key, "X-FTN-SEEN-BY") == 0) fill_list(&sbl, tmsg->val, NULL); for (i = 0; i < 40; i++) { if (CFG.akavalid[i] && (CFG.aka[i].point == 0) && (msgs.Aka.zone == CFG.aka[i].zone) && !((msgs.Aka.net == CFG.aka[i].net) && (msgs.Aka.node == CFG.aka[i].node))) { snprintf(sbe, 128, "%u/%u", CFG.aka[i].net, CFG.aka[i].node); fill_list(&sbl, sbe, NULL); } } if (msgs.Aka.point == 0) { snprintf(sbe, 128, "%u/%u", msgs.Aka.net, msgs.Aka.node); fill_list(&sbl, sbe, NULL); } /* * Only add SEEN-BY lines if there are any */ if (sbl != NULL) { uniq_list(&sbl); sort_list(&sbl); seenlen = MAXSEEN + 1; memset(&sbe, 0, sizeof(sbe)); /* ensure it will not match for the first entry */ oldnet = sbl->addr->net-1; for (tmpl = sbl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,128," %u",tmpl->addr->node); else snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXSEEN) { seenlen = 0; fprintf(ofp,"\nSEEN-BY:"); snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&sbl); } /* * Setup PATH lines */ for (tmp = msg; tmp; tmp = tmp->next) if (!strcasecmp(tmp->key,"X-FTN-PATH")) fill_path(&ptl,tmp->val); if (msgs.Aka.point == 0) { snprintf(sbe,128,"%u/%u",msgs.Aka.net, msgs.Aka.node); fill_path(&ptl,sbe); } /* * Only add PATH line if there is something */ if (ptl != NULL) { uniq_list(&ptl); seenlen = MAXPATH+1; /* ensure it will not match for the first entry */ oldnet = ptl->addr->net-1; for (tmpl = ptl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,128," %u",tmpl->addr->node); else snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXPATH) { seenlen = 0; fprintf(ofp,"\n\1PATH:"); snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&ptl); } } /* if (newsmode) */ /* * Add newline and message is ready. */ fprintf(ofp,"\n"); fflush(ofp); rewind(ofp); Syslog('m', "========== Fido start"); while (fgets(temp, 4096, ofp) != NULL) { /* * Only log kludges, skip the body */ if ((temp[0] == '\001') || !strncmp(temp, "AREA:", 5) || !strncmp(temp, "SEEN-BY", 7)) { Striplf(temp); Syslogp('m', printable(temp, 0)); } } Syslog('m', "========== Fido end"); if (newsmode) rc = postecho(NULL, fmsg->from, fmsg->to, origin, fmsg->subj, fmsg->date, fmsg->flags, 0, ofp, FALSE, 0); else rc = postnetmail(ofp, fmsg->from, fmsg->to, origin, fmsg->subj, fmsg->date, fmsg->flags, FALSE, fmsg->from->zone, fmsg->to->zone); Syslog('m', "rfc2ftn: message posted rc=%d", rc); free(origin); fclose(ofp); } while (needsplit); Syslog('m', "rfc2ftn: out of splitloop"); chartran_close(); free(temp); if (charset) free(charset); tidyrfc(msg); tidy_ftnmsg(fmsg); Syslog('m', "rfc2ftn: memory freed"); UpdateMsgs(); return 0; }
void ForwardFile(fidoaddr Node, fa_list *sbl) { char *subject = NULL, *fwdfile = NULL, *queuedir, *listfile, *ticfile = NULL, *ticname, flavor; FILE *fp, *fi, *fl, *net; faddr *dest, *routeto, *Fa, *Temp, *ba; int i, z, n; time_t now, ftime; fa_list *tmp; if (!SearchNode(Node)) { WriteError("TIC forward in %s, node %s not in setup but defined in area setup", TIC.TicIn.Area, aka2str(Node)); return; } Syslog('+', "Forward file to %s %s netmail", aka2str(Node), nodes.Message?"with":"without"); fwdfile = calloc(PATH_MAX, sizeof(char)); queuedir = calloc(PATH_MAX, sizeof(char)); listfile = calloc(PATH_MAX, sizeof(char)); snprintf(queuedir, PATH_MAX, "%s/%d.%d.%d.%d", CFG.out_queue, Node.zone, Node.net, Node.node, Node.point); snprintf(listfile, PATH_MAX, "%s/.filelist", queuedir); mkdirs(listfile, 0750); if ((fl = fopen(listfile, "a+")) == NULL) { WriteError("$Can't open %s", listfile); free(fwdfile); free(listfile); free(queuedir); return; } /* * Create the full filename */ if (TIC.PassThru || TIC.SendOrg) { snprintf(fwdfile, PATH_MAX, "%s/%s", TIC.Inbound, TIC.TicIn.File); subject = xstrcpy(TIC.TicIn.File); } else { /* * Make sure the file attach is the 8.3 filename */ snprintf(fwdfile, PATH_MAX, "%s/%s", TIC.BBSpath, TIC.NewFile); subject = xstrcpy(TIC.NewFile); } flavor = 'f'; if (nodes.Crash) flavor = 'c'; if (nodes.Hold) flavor = 'h'; fprintf(fl, "%c LEAVE FDN %s\n", flavor, fwdfile); if (nodes.RouteVia.zone) routeto = fido2faddr(nodes.RouteVia); else routeto = fido2faddr(Node); dest = fido2faddr(Node); ticfile = calloc(PATH_MAX, sizeof(char)); ticname = calloc(15, sizeof(char)); if (nodes.Tic) { snprintf(ticname, 15, "%08x.tic", sequencer()); subject = xstrcat(subject, (char *)" "); subject = xstrcat(subject, ticname); snprintf(ticfile, PATH_MAX, "%s/%s", CFG.ticout, ticname); } free(ticname); /* * Send netmail message if the node has it turned on. */ if (nodes.Message) { Temp = fido2faddr(Node); if ((net = SendMgrMail(Temp, CFG.ct_KeepMgr, TRUE, (char *)"Filemgr", subject, NULL)) != NULL) { if ((fi = OpenMacro("forward.tic", nodes.Language, FALSE)) != NULL) { ftime = TIC.FileDate; MacroVars("a", "s", TIC.TicIn.Area); MacroVars("b", "s", tic.Comment); MacroVars("c", "d", TIC.FileCost); MacroVars("d", "s", fgroup.Comment); if (TIC.PassThru || TIC.SendOrg) MacroVars("f", "s", TIC.TicIn.FullName); else MacroVars("f", "s", TIC.NewFullName); MacroVars("g", "d", TIC.FileSize); MacroVars("h", "d", (TIC.FileSize / 1024)); MacroVars("i", "s", TIC.TicIn.Crc); MacroVars("j", "s", TIC.TicIn.Origin); MacroVars("m", "s", rfcdate(ftime)); MacroVars("n", "s", TIC.TicIn.Desc); MacroVars("s", "s", nodes.Sysop); if (TIC.PassThru || TIC.SendOrg) MacroVars("e", "s", TIC.TicIn.File); else MacroVars("e", "s", TIC.NewFile); if (strlen(TIC.TicIn.Magic)) MacroVars("k", "s", TIC.TicIn.Magic); if (strlen(TIC.TicIn.Replace)) MacroVars("l", "s", TIC.TicIn.Replace); MacroRead(fi, net); fprintf(net, "%s\r", TearLine()); CloseMail(net, Temp); } } else { WriteError("Can't create netmail"); } tidy_faddr(Temp); } free(subject); /* * If we need a .TIC file, start creating it. */ if (nodes.Tic) { mkdirs(ticfile, 0770); if ((fp = fopen(ticfile, "a+")) != NULL) { fprintf(fp, "Area %s\r\n", TIC.TicIn.Area); fprintf(fp, "Origin %s\r\n", TIC.TicIn.Origin); Fa = fido2faddr(tic.Aka); fprintf(fp, "From %s\r\n", ascfnode(Fa, 0x0f)); free(Fa); if (strlen(TIC.TicIn.Replace)) fprintf(fp, "Replaces %s\r\n", TIC.TicIn.Replace); if (strlen(TIC.TicIn.Magic)) fprintf(fp, "Magic %s\r\n", TIC.TicIn.Magic); if ((TIC.PassThru) || (TIC.SendOrg)) { fprintf(fp, "File %s\r\n", TIC.TicIn.File); if (strlen(TIC.TicIn.FullName)) fprintf(fp, "Lfile %s\r\n", TIC.TicIn.FullName); } else { fprintf(fp, "File %s\r\n", TIC.NewFile); if (strlen(TIC.NewFullName)) fprintf(fp, "Lfile %s\r\n", TIC.NewFullName); } fprintf(fp, "Size %d\r\n", (int)(TIC.FileSize)); fprintf(fp, "Desc %s\r\n", TIC.TicIn.Desc); fprintf(fp, "Crc %s\r\n", TIC.TicIn.Crc); if (nodes.TIC_To) { fprintf(fp, "To %s, %s\r\n", nodes.Sysop, ascfnode(dest, 0x1f)); } if (nodes.AdvTic) { fprintf(fp, "Areadesc %s\r\n", tic.Comment); fprintf(fp, "Fdn %s\r\n", fgroup.Comment); if (TIC.TicIn.TotLDesc) for (i = 0; i < TIC.TicIn.TotLDesc; i++) fprintf(fp, "LDesc %s\r\n", TIC.TicIn.LDesc[i]); } fprintf(fp, "Created by MBSE BBS %s %s\r\n", VERSION, SHORTRIGHT); if (TIC.TicIn.TotPath) for (i = 0; i < TIC.TicIn.TotPath; i++) fprintf(fp, "Path %s\r\n", TIC.TicIn.Path[i]); /* * Add our system to the path */ now = time(NULL); subject = ctime(&now); Striplf(subject); ba = bestaka_s(dest); fprintf(fp, "Path %s %u %s %s\r\n", ascfnode(ba, 0x1f), (int)mktime(localtime(&now)), subject, tzname[0]); tidy_faddr(ba); if (nodes.TIC_AdvSB) { /* * In advanced TIC mode we send multiple seenby * addresses on one line in stead of one line * per system. */ z = 0; n = 0; subject = xstrcpy((char *)"Seenby"); for (tmp = sbl; tmp; tmp = tmp->next) { if (strlen(subject) > 70) { fprintf(fp, "%s\r\n", subject); z = 0; n = 0; free(subject); subject = xstrcpy((char *)"Seenby "); } else { subject = xstrcat(subject, (char *)" "); } if (z != tmp->addr->zone) { if (nodes.Tic4d) subject = xstrcat(subject, ascfnode(tmp->addr, 0x0f)); else subject = xstrcat(subject, ascfnode(tmp->addr, 0x0e)); z = tmp->addr->zone; } else { if (n != tmp->addr->net) { if (nodes.Tic4d) subject = xstrcat(subject, ascfnode(tmp->addr, 0x07)); else subject = xstrcat(subject, ascfnode(tmp->addr, 0x06)); n = tmp->addr->net; } else { if (nodes.Tic4d) subject = xstrcat(subject, ascfnode(tmp->addr, 0x03)); else subject = xstrcat(subject, ascfnode(tmp->addr, 0x02)); } } } if (strlen(subject) > 7) { fprintf(fp, "%s\r\n", subject); free(subject); } } else { /* * Old style seenby lines */ for (tmp = sbl; tmp; tmp = tmp->next) { fprintf(fp, "Seenby %s\r\n", ascfnode(tmp->addr, 0x0f)); } } /* * Now append all passthru ticlines */ if (TIC.TicIn.Unknowns) for (i = 0; i < TIC.TicIn.Unknowns; i++) fprintf(fp, "%s\r\n", TIC.TicIn.Unknown[i]); fprintf(fp, "Pw %s\r\n", nodes.Fpasswd); fclose(fp); fprintf(fl, "%c KFS NOR %s\n", flavor, ticfile); } else { WriteError("$Can't create %s", ticfile); } } fsync(fileno(fl)); fclose(fl); /* * Update the nodes statistic counters */ StatAdd(&nodes.FilesSent, 1L); StatAdd(&nodes.F_KbSent, T_File.SizeKb); UpdateNode(); SearchNode(Node); free(ticfile); free(fwdfile); free(queuedir); free(listfile); tidy_faddr(routeto); }
void flush_dir(char *ndir) { struct dirent *de; DIR *dp; FILE *fp, *inf, *ouf; faddr noden, *bestaka; fidoaddr nodenr; int flavor, mode, Attach, fage, first, bread, rc; int fsize; char *p, *temp, *fname, *arcfile, *pktfile, *ext, maxnr, nr, oldnr, *buf; time_t Now; struct tm *ptm; struct stat sbuf; fd_list *fdl = NULL; temp = calloc(PATH_MAX, sizeof(char)); snprintf(temp, PATH_MAX, "%s/%s", CFG.out_queue, ndir); if (chdir(temp) == -1) { WriteError("$Error chdir to %s", temp); free(temp); return; } /* * Get the nodenumber from the filename */ noden.domain = NULL; noden.name = NULL; noden.zone = atoi(strtok(ndir, ".")); noden.net = atoi(strtok(NULL, ".")); noden.node = atoi(strtok(NULL, ".")); noden.point = atoi(strtok(NULL, "\0")); if (SearchFidonet(noden.zone)) noden.domain = xstrcpy(fidonet.domain); memset(&nodenr, 0, sizeof(nodenr)); nodenr.zone = noden.zone; nodenr.net = noden.net; nodenr.node = noden.node; nodenr.point = noden.point; snprintf(nodenr.domain, 13, "%s", noden.domain); if (!SearchNode(nodenr)) { /* * Node not in setup, blank noderecord and fill in some details * so that we are able to send mail crash or immediate. */ Syslog('+', "Node %s not in setup, using default settings", aka2str(nodenr)); memset(&nodes, 0, sizeof(nodes)); nodes.Aka[0].zone = noden.zone; nodes.Aka[0].net = noden.net; nodes.Aka[0].node = noden.node; nodes.Aka[0].point = noden.point; snprintf(nodes.Archiver, 6, (char *)"ZIP"); } /* * If we route via another aka, change everything. */ if (nodes.RouteVia.zone) { p = xstrcpy(aka2str(nodenr)); Syslog('+', "Route to %s via %s", p, aka2str(nodes.RouteVia)); free(p); noden.zone = nodes.RouteVia.zone; noden.net = nodes.RouteVia.net; noden.node = nodes.RouteVia.node; noden.point = nodes.RouteVia.point; if (noden.domain) free(noden.domain); noden.domain = xstrcpy(nodes.RouteVia.domain); /* * Load routevia noderecord to get the correct flavor. * If there is no noderecord, reload the old one. */ if (!SearchNode(nodes.RouteVia)) SearchNode(nodenr); } /* * At this point we are ready to add everything to the real outbound. * Lock the node, if this fails because the node is busy we abort * and try to add at a later time. */ if (nodes.Session_out == S_DIR) { if (islocked(nodes.Dir_out_clock, nodes.Dir_out_chklck, nodes.Dir_out_waitclr, 'p')) { Syslog('+', "Mail and files stay in queue, will be added later"); if (noden.domain) free(noden.domain); free(temp); return; } else { if (! setlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p')) { Syslog('+', "Mail and files stay in queue, will be added later"); if (noden.domain) free(noden.domain); free(temp); return; } } } else { if (nodelock(&noden, mypid)) { Syslog('+', "Mail and files stay in queue, will be added later"); if (noden.domain) free(noden.domain); free(temp); return; } } /* * Create arcmail filename for this node. */ Now = time(NULL); arcfile = calloc(PATH_MAX, sizeof(char)); if (nodes.Session_out == S_DIR) { ptm = localtime(&Now); ext = dow[ptm->tm_wday]; if (!nodes.ARCmailCompat && (nodes.Aka[0].zone != noden.zone)) { /* * Generate ARCfile name from the CRC of the ASCII string of the node address. */ snprintf(arcfile, PATH_MAX, "%s/%08x.%s0", nodes.Dir_out_path, StringCRC32(ascfnode(&noden, 0x1f)), ext); } else { bestaka = bestaka_s(&noden); if (noden.point) { snprintf(arcfile, PATH_MAX, "%s/%04x%04x.%s0", nodes.Dir_out_path, ((bestaka->net) - (noden.net)) & 0xffff, ((bestaka->node) - (noden.node) + (noden.point)) & 0xffff, ext); } else if (bestaka->point) { /* * Inserted the next code for if we are a point, * I hope this is ARCmail 0.60 compliant. 21-May-1999 */ snprintf(arcfile, PATH_MAX, "%s/%04x%04x.%s0", nodes.Dir_out_path, ((bestaka->net) - (noden.net)) & 0xffff, ((bestaka->node) - (noden.node) - (bestaka->point)) & 0xffff, ext); } else { snprintf(arcfile, PATH_MAX, "%s/%04x%04x.%s0", nodes.Dir_out_path, ((bestaka->net) - (noden.net)) & 0xffff, ((bestaka->node) - (noden.node)) &0xffff, ext); } } } else { snprintf(arcfile, PATH_MAX, "%s", arcname(&noden, nodes.Aka[0].zone, nodes.ARCmailCompat)); } /* * If there is a mailpkt.qqq file, close it and rename it. */ pktfile = calloc(PATH_MAX, sizeof(char)); fname = calloc(PATH_MAX, sizeof(char)); snprintf(fname, PATH_MAX, "%s/mailpkt.qqq", temp); if (access(fname, W_OK) == 0) { snprintf(pktfile, PATH_MAX, "%s/%08x.pkt", temp, sequencer()); if (rename(fname, pktfile)) { WriteError("$Can't rename %s to %s", fname, pktfile); } else { /* * Add zero word to end of .pkt file */ if ((fp = fopen(pktfile, "a+")) == NULL) { WriteError("$Can't open %s", pktfile); } putc('\0', fp); putc('\0', fp); fsync(fileno(fp)); fclose(fp); } } free(fname); /* * Now all mail pkts are ready to archive */ if ((dp = opendir(temp)) == NULL) { WriteError("$Can't open %s", temp); free(temp); free(arcfile); if (nodes.Session_out == S_DIR) remlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p'); else nodeulock(&noden, mypid); if (noden.domain) free(noden.domain); return; } /* * Read all .pkt filenames, get the timestamp and add them * to the memory array for later sort on filedate. */ while ((de = readdir(dp))) if ((strlen(de->d_name) == 12) && (strncasecmp(de->d_name+8,".pkt",4) == 0)) { stat(de->d_name, &sbuf); Syslog('p', "Adding %s to filelist", de->d_name); fill_fdlist(&fdl, de->d_name, sbuf.st_mtime); } closedir(dp); sort_fdlist(&fdl); if (getarchiver(nodes.Archiver)) { flavor = 'f'; if (nodes.Crash) flavor = 'c'; if (nodes.Hold) flavor = 'h'; } else { WriteError("Archiver %s not found", nodes.Archiver); if (noden.domain) free(noden.domain); free(temp); free(arcfile); return; } first = TRUE; while ((fname = pull_fdlist(&fdl)) != NULL) { /* * Check the size of the existing archive if there is a size limit. * Change to new archive names if the existing is too large. * If the archive size is zero, it's an already sent archive, the * number will be bumped also. * If the archive is older then 6 days, the name is also bumped. * Do this until we find a new name or if the last digit is a '9' or 'z'. * Purge archives older then toss_days. */ nr = oldnr = '0'; if (nodes.ARCmailAlpha) maxnr = 'z'; else maxnr = '9'; Attach = FALSE; for (;;) { fsize = file_size(arcfile); fage = (int)((Now - file_time(arcfile)) / 86400); if (fsize == -1L) { Attach = TRUE; break; } if (fsize == 0L) { if ((fage > 6) && (nr < maxnr)) { /* * Remove truncated ARCmail files older then 6 days. */ unlink(arcfile); fsize = -1L; Attach = TRUE; break; } /* * Increase filename extension if there is a truncated file of today. */ if (nr < maxnr) { nr++; if (nr == ('9' +1)) nr = 'a'; arcfile[strlen(arcfile) -1] = nr; } else { Syslog('!', "Warning: archive filename extensions exhausted for today"); break; } } else if (CFG.maxarcsize && (fsize > (CFG.maxarcsize * 1024)) && (nr < maxnr)) { /* * Use a new ARCmail file if the last one is too big. */ nr++; if (nr == ('9' +1)) nr = 'a'; arcfile[strlen(arcfile) -1] = nr; } fsize = file_size(arcfile); fage = (int)((Now - file_time(arcfile)) / 86400); if ((fsize > 0L) && (fage > 6) && (nr < maxnr)) { /* * If there is ARCmail of a week old or older, add mail * to a new ARCmail bundle. */ nr++; if (nr == ('9' +1)) nr = 'a'; arcfile[strlen(arcfile) -1] = nr; } if (oldnr == nr) break; else oldnr = nr; } fsize = file_size(arcfile); /* * If arcfile names were exhausted then the file ending on a z could still * be in the outbound but truncated if it has been sent. Since we are * reusing that filename (not a good solution) we must erase it or the * archiver program will complain. */ if (fsize == 0L) { unlink(arcfile); Attach = TRUE; } if (first) { Syslog('+', "Pack ARCmail for %s via %s with %s", aka2str(nodenr), ascfnode(&noden, 0x1f), nodes.Archiver); if (!do_quiet) { printf("\rAdding ARCmail for %s ", ascfnode(&noden, 0x1f)); fflush(stdout); } first = FALSE; flushed = TRUE; } if (execute_str(archiver.marc, arcfile, fname, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null") == 0) { unlink(fname); } else { WriteError("Can't add %s to ARCmail archive", fname); Attach = FALSE; } /* * Change filemode so downlink has rights to the file. */ if (nodes.Session_out == S_DIR) chmod(arcfile, 0660); /* * Attach file to .flo, not for FTP or Directory sessions. */ if (Attach && nodes.Session_out == S_DIRECT) attach(noden, arcfile, TFS, flavor); } /* * Open directory again. */ if ((dp = opendir(temp)) == NULL) { WriteError("$Can't open %s", temp); free(temp); free(arcfile); if (nodes.Session_out == S_DIR) remlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p'); else nodeulock(&noden, mypid); if (noden.domain) free(noden.domain); return; } /* * Read all other mail filenames, get the timestamp and add them * to the memory array for later sort on filedate. */ while ((de = readdir(dp))) if ((strlen(de->d_name) == 11) && (strncasecmp(de->d_name,"mailpkt.",8) == 0)) { stat(de->d_name, &sbuf); Syslog('p', "Adding %s to filelist", de->d_name); fill_fdlist(&fdl, de->d_name, sbuf.st_mtime); } closedir(dp); sort_fdlist(&fdl); first = TRUE; while ((fname = pull_fdlist(&fdl)) != NULL) { if (first) { Syslog('+', "Pack unpacked mail for %s via %s", aka2str(nodenr), ascfnode(&noden, 0x1f)); if (!do_quiet) { printf("\rAdding netmail for %s ", ascfnode(&noden, 0x1f)); fflush(stdout); } first = FALSE; flushed = TRUE; } snprintf(pktfile, PATH_MAX, "%s/%s", temp, fname); if (strstr(fname, ".ddd")) flavor = 'd'; else if (strstr(fname, ".ccc")) flavor = 'c'; else if (strstr(fname, ".hhh")) flavor = 'h'; else flavor = 'o'; if (nodes.Session_out == S_DIR) { snprintf(arcfile, PATH_MAX, "%s/%08x.pkt", nodes.Dir_out_path, sequencer()); } else { snprintf(arcfile, PATH_MAX, "%s", pktname(&noden, flavor)); } /* * Now we must see if there is already mail in the outbound. * If that's the case, we must skip the .pkt header from the queue * because there is already a .pkt header also, append to the * outbound 2 bytes before the end of file, this is the zero word. */ if ((inf = fopen(pktfile, "r")) != NULL) { if (access(arcfile, R_OK) == -1) { ouf = fopen(arcfile, "w"); /* create new */ Syslog('p', "Create new %s", arcfile); } else { ouf = fopen(arcfile, "r+"); /* open R/W */ fseek(ouf, -2, SEEK_END); /* b4 0 word */ fseek(inf, 58, SEEK_SET); /* skip header */ Syslog('p', "Append to %s", arcfile); } if (ouf != NULL) { buf = malloc(16384); do { bread = fread(buf, 1, 16384, inf); fwrite(buf, 1, bread, ouf); } while (bread); free(buf); putc('\0', ouf); putc('\0', ouf); fsync(fileno(ouf)); fclose(ouf); fclose(inf); unlink(pktfile); } else { WriteError("$Can't open %s", arcfile); fclose(inf); } } /* * Change filemode so downlink has rights to the file. */ if (nodes.Session_out == S_DIR) chmod(arcfile, 0660); } /* * Now add the files for the node, information is in the .filelist * file, this tells the location of the file and what to do with * it after it is sent. */ snprintf(pktfile, PATH_MAX, "%s/.filelist", temp); if ((fp = fopen(pktfile, "r")) != NULL) { Syslog('+', "Adding files for %s via %s", aka2str(nodenr), ascfnode(&noden, 0x1f)); if (!do_quiet) { printf("\rAdding files for %s ", ascfnode(&noden, 0x1f)); fflush(stdout); flushed = TRUE; } buf = calloc(PATH_MAX + 1, sizeof(char)); while (fgets(buf, PATH_MAX, fp)) { Striplf(buf); Syslog('p', ".filelist: %s", buf); flavor = buf[0]; p = strchr(buf, ' '); p++; if (strncmp(p, "LEAVE ", 6) == 0) mode = LEAVE; else if (strncmp(p, "KFS ", 4) == 0) mode = KFS; else if (strncmp(p, "TFS ", 4) == 0) mode = TFS; else { WriteError("Syntax error in filelist \"%s\"", buf); mode = LEAVE; } p = strchr(p, ' '); p++; // Here is a extra now unused keyword. p = strchr(p, ' '); p++; Syslog('p', "File attach %s to %s", p, ascfnode(&noden, 0x1f)); if (nodes.Session_out == S_DIRECT) { attach(noden, p, mode, flavor); } else if (nodes.Session_out == S_DIR) { snprintf(arcfile, PATH_MAX, "%s/%s", nodes.Dir_out_path, Basename(p)); if (mode == LEAVE) { /* * LEAVE file, so we copy this one. */ rc = file_cp(p, arcfile); Syslog('p', "file_cp(%s, %s) rc=%d", p, arcfile, rc); } else { /* * KFS or TFS, move file to node directory */ rc = file_mv(p, arcfile); Syslog('p', "file_mv(%s, %s) rc=%d", p, arcfile, rc); } chmod(arcfile, 0660); } } free(buf); fclose(fp); unlink(pktfile); } /* * We are done, the queue is flushed, unlock the node. */ if (nodes.Session_out == S_DIR) remlock(nodes.Dir_out_mlock, nodes.Dir_out_mklck, 'p'); else nodeulock(&noden, mypid); if (noden.domain) free(noden.domain); free(temp); free(arcfile); free(pktfile); return; }