/***************************************************************************** * * $Id$ * Purpose ...............: AreaMgr * ***************************************************************************** * Copyright (C) 1997-2004 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * MBSE BBS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MBSE BBS; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "../config.h" #include "../lib/mbselib.h" #include "../lib/users.h" #include "../lib/msg.h" #include "../lib/msgtext.h" #include "../lib/mbsedb.h" #include "../lib/diesel.h" #include "sendmail.h" #include "mgrutil.h" #include "scan.h" #include "createm.h" #include "areamgr.h" /* * External declarations */ extern int do_quiet; /* * Global variables */ extern int net_bad; /* Bad netmails (tracking errors */ int areamgr = 0; /* Nr of AreaMgr messages */ int a_help = FALSE; /* Send AreaMgr help */ int a_list = FALSE; /* Send AreaMgr list */ int a_query = FALSE; /* Send AreaMgr query */ int a_stat = FALSE; /* Send AreaMgr status */ int a_unlnk = FALSE; /* Send AreaMgr unlinked */ int a_flow = FALSE; /* Send AreaMgr flow */ unsigned long a_msgs = 0; /* Messages to rescan */ void A_Help(faddr *, char *); void A_Help(faddr *t, char *replyid) { FILE *fp, *fi; char *subject; faddr *ta; Mgrlog("AreaMgr: Help"); subject = calloc(255, sizeof(char)); sprintf(subject,"AreaMgr Help"); GetRpSubject("areamgr.help",subject); if ((fp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject , replyid)) != NULL) { if ((fi = OpenMacro("areamgr.help", nodes.Language, FALSE)) != NULL ) { ta = bestaka_s(t); MacroVars("s", "s", nodes.Sysop); MacroVars("A", "s", (char *)"Areamgr"); MacroVars("Y", "s", ascfnode(ta, 0xff)); MacroVars("P", "s", nodes.Apasswd); tidy_faddr(ta); MacroRead(fi, fp); fclose(fi); } fprintf(fp, "%s\r", TearLine()); CloseMail(fp, t); } else { WriteError("Can't create netmail"); } free(subject); MacroClear(); } void A_Query(faddr *, char *); void A_Query(faddr *t, char *replyid) { A_List(t, replyid, LIST_QUERY); } void A_List(faddr *t, char *replyid, int Notify) { FILE *qp, *gp, *mp, *fi = NULL; char *temp, *Group, *subject; int i, First = TRUE, SubTot, Total = 0, Cons; char Stat[5]; faddr *f, *g, *Temp; sysconnect System; long msgptr; fpos_t fileptr,fileptr1,fileptr2; subject = calloc(255, sizeof(char)); f = bestaka_s(t); MacroVars("s", "s", nodes.Sysop); MacroVars("K", "d", Notify); MacroVars("y", "s", ascfnode(t, 0xff)); MacroVars("Y", "s", ascfnode(f, 0xff)); switch (Notify) { case LIST_NOTIFY: Mgrlog("AreaMgr: Notify to %s", ascfnode(t, 0xff)); sprintf(subject,"AreaMgr Notify"); GetRpSubject("areamgr.notify.list",subject); fi = OpenMacro("areamgr.notify.list", nodes.Language, FALSE); break; case LIST_LIST: Mgrlog("AreaMgr: List"); sprintf(subject,"AreaMgr list"); GetRpSubject("areamgr.list",subject); fi = OpenMacro("areamgr.list", nodes.Language, FALSE); break; case LIST_QUERY: Mgrlog("AreaMgr: Query"); sprintf(subject,"AreaMgr Query"); GetRpSubject("areamgr.query",subject); fi = OpenMacro("areamgr.query", nodes.Language, FALSE); break; case LIST_UNLINK: Mgrlog("AreaMgr: Unlinked"); sprintf(subject,"AreaMgr: Unlinked areas"); GetRpSubject("areamgr.unlink",subject); fi = OpenMacro("areamgr.unlink", nodes.Language, FALSE); break; } if (fi == NULL) { MacroClear(); free(subject); return; } if ((qp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid)) != NULL) { /* * Mark begin of message in .pkt */ msgptr = ftell(qp); if ((Notify == LIST_LIST) || (Notify == LIST_NOTIFY)) WriteMailGroups(qp, f); MacroRead(fi, qp); fgetpos(fi,&fileptr); temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT")); if ((mp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); free(temp); free(subject); MacroClear(); fclose(fi); return; } fread(&msgshdr, sizeof(msgshdr), 1, mp); Cons = msgshdr.syssize / sizeof(System); sprintf(temp, "%s/etc/mgroups.data", getenv("MBSE_ROOT")); if ((gp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); free(temp); free(subject); MacroClear(); fclose(mp); fclose(fi); return; } fread(&mgrouphdr, sizeof(mgrouphdr), 1, gp); free(temp); while (TRUE) { Group = GetNodeMailGrp(First); if (Group == NULL) break; First = FALSE; fseek(gp, mgrouphdr.hdrsize, SEEK_SET); while (fread(&mgroup, mgrouphdr.recsize, 1, gp) == 1) { Temp = fido2faddr(mgroup.UseAka); g = bestaka_s(Temp); tidy_faddr(Temp); if ((!strcmp(mgroup.Name, Group)) && (g->zone == f->zone) && (g->net == f->net) && (g->node == f->node) && (g->point == f->point)) { SubTot = 0; MacroVars("G", "s", mgroup.Name); MacroVars("J", "s", mgroup.Comment); MacroVars("I", "s", aka2str(mgroup.UseAka) ); fsetpos(fi,&fileptr); MacroRead(fi, qp); fgetpos(fi,&fileptr1); fseek(mp, msgshdr.hdrsize, SEEK_SET); while (fread(&msgs, msgshdr.recsize, 1, mp) == 1) { if (!strcmp(Group, msgs.Group) && msgs.Active && Access(nodes.Security, msgs.LinkSec)) { memset(&Stat, ' ', sizeof(Stat)); Stat[sizeof(Stat)-1] = '\0'; /* * Now check if this node is connected, if so, set the Stat bits */ for (i = 0; i < Cons; i++) { fread(&System, sizeof(System), 1, mp); if ((t->zone == System.aka.zone) && (t->net == System.aka.net) && (t->node == System.aka.node) && (t->point == System.aka.point)) { if (System.receivefrom) Stat[0] = 'S'; if (System.sendto) Stat[1] = 'R'; if (System.pause) Stat[2] = 'P'; if (System.cutoff) Stat[3] = 'C'; } } if ( (Notify == LIST_LIST) || (Notify == LIST_NOTIFY) || ((Notify == LIST_QUERY) && ((Stat[0]=='S') || (Stat[1]=='R'))) || ((Notify >= LIST_UNLINK) && ((Stat[0]!='S') && (Stat[1]!='R')))){ MacroVars("X", "s", Stat); MacroVars("D", "s", msgs.Tag); MacroVars("E", "s", msgs.Name); MacroVars("s", "d", (Stat[0] == 'S')); MacroVars("r", "d", (Stat[1] == 'R')); MacroVars("p", "d", (Stat[2] == 'P')); MacroVars("c", "d", (Stat[3] == 'C')); fsetpos(fi,&fileptr1); MacroRead(fi, qp); fgetpos(fi,&fileptr2); SubTot++; Total++; /* * Panic message split */ if (((ftell(qp) - msgptr) / 1024) >= CFG.new_force) { MacroVars("Z","d",1); Syslog('-', " Forced splitting message at %ld bytes", ftell(qp) - msgptr); CloseMail(qp, t); qp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid); msgptr = ftell(qp); } } } else fseek(mp, msgshdr.syssize, SEEK_CUR); } MacroVars("ZC", "dd", (int) 0 , SubTot ); fsetpos(fi,&fileptr2); if (((ftell(qp) - msgptr) / 1024) >= CFG.new_split) { MacroVars("Z","d",1); Syslog('-', " Splitting message at %ld bytes", ftell(qp) - msgptr); CloseMail(qp, t); qp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid); msgptr = ftell(qp); } MacroRead(fi, qp); } } } MacroVars("B", "d", Total ); MacroRead(fi, qp); MacroClear(); fclose(fi); fclose(mp); fclose(gp); fprintf(qp, "%s\r", TearLine()); CloseMail(qp, t); } else WriteError("Can't create netmail"); free(subject); MacroClear(); } void A_Flow(faddr *t, char *replyid, int Notify) { FILE *qp, *gp, *mp, *fi = NULL; char *temp, *Group, *subject; int i, First = TRUE, Cons; char Stat[2]; faddr *f, *g, *Temp; sysconnect System; time_t Now; struct tm *tt; int lmonth; long rlw, rlm, rlt, plw, plm, plt; long msgptr; fpos_t fileptr, fileptr1, fileptr2; Now = time(NULL); tt = localtime(&Now); lmonth = tt->tm_mon; if (lmonth) lmonth--; else lmonth = 11; subject = calloc(255, sizeof(char)); f = bestaka_s(t); MacroVars("s", "s", nodes.Sysop); MacroVars("K", "d", Notify); MacroVars("y", "s", ascfnode(t, 0xff)); MacroVars("Y", "s", ascfnode(f, 0xff)); if (Notify) { Mgrlog("AreaMgr: Flow report to %s", ascfnode(t, 0xff)); sprintf(subject,"AreaMgr Notify Flow Report"); GetRpSubject("areamgr.notify.flow",subject); fi = OpenMacro("areamgr.notify.flow", nodes.Language, FALSE); } else { Mgrlog("AreaMgr: Flow report"); sprintf(subject,"AreaMgr Flow Report"); GetRpSubject("areamgr.flow",subject); fi = OpenMacro("areamgr.flow", nodes.Language, FALSE); } if (fi == 0) { free(subject); MacroClear(); return; } if ((qp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid)) != NULL) { /* * Mark begin of message in .pkt */ msgptr = ftell(qp); temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT")); if ((mp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); free(temp); free(subject); fclose(fi); MacroClear(); return; } fread(&msgshdr, sizeof(msgshdr), 1, mp); Cons = msgshdr.syssize / sizeof(System); sprintf(temp, "%s/etc/mgroups.data", getenv("MBSE_ROOT")); if ((gp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); free(temp); free(subject); fclose(mp); fclose(fi); MacroClear(); return; } fread(&mgrouphdr, sizeof(mgrouphdr), 1, gp); free(temp); MacroRead(fi, qp); fgetpos(fi,&fileptr); while (TRUE) { Group = GetNodeMailGrp(First); if (Group == NULL) break; First = FALSE; plm = plw = plt = rlm = rlw = rlt = 0; fseek(gp, mgrouphdr.hdrsize, SEEK_SET); while (fread(&mgroup, mgrouphdr.recsize, 1, gp) == 1) { Temp = fido2faddr(mgroup.UseAka); g = bestaka_s(Temp); tidy_faddr(Temp); if ((!strcmp(mgroup.Name, Group)) && (g->zone == f->zone) && (g->net == f->net) && (g->node == f->node) && (g->point == f->point)) { MacroVars("G", "s", mgroup.Name); MacroVars("J", "s", mgroup.Comment); MacroVars("I", "s", aka2str(mgroup.UseAka)); fsetpos(fi,&fileptr); MacroRead(fi, qp); fgetpos(fi,&fileptr1); fseek(mp, msgshdr.hdrsize, SEEK_SET); while (fread(&msgs, msgshdr.recsize, 1, mp) == 1) { if (!strcmp(Group, msgs.Group) && msgs.Active && Access(nodes.Security, msgs.LinkSec)) { memset(&Stat, ' ', sizeof(Stat)); Stat[sizeof(Stat)-1] = '\0'; /* * Now check if this node is connected, if so, set the Stat bits */ for (i = 0; i < Cons; i++) { fread(&System, sizeof(System), 1, mp); if ((t->zone == System.aka.zone) && (t->net == System.aka.net) && (t->node == System.aka.node) && (t->point == System.aka.point)) { if ((System.receivefrom || System.sendto) && (!System.pause) && (!System.cutoff)) Stat[0] = 'C'; } } MacroVars("X", "c", Stat[0]); MacroVars("A", "s", msgs.Tag); MacroVars("P", "d", msgs.Received.lweek); MacroVars("Q", "d", msgs.Received.month[lmonth]); MacroVars("R", "d", msgs.Received.total); MacroVars("p", "d", msgs.Posted.lweek); MacroVars("q", "d", msgs.Posted.month[lmonth]); MacroVars("r", "d", msgs.Posted.total); MacroVars("x", "d", (Stat[0] == 'C')); fsetpos(fi,&fileptr1); MacroRead(fi, qp); fgetpos(fi,&fileptr2); rlm += msgs.Received.month[lmonth]; rlw += msgs.Received.lweek; rlt += msgs.Received.total; plm += msgs.Posted.month[lmonth]; plw += msgs.Posted.lweek; plt += msgs.Posted.total; if (((ftell(qp) - msgptr) / 1024) >= CFG.new_force) { MacroVars("Z","d",1); Syslog('-', " Forced splitting message at %ld bytes", ftell(qp) - msgptr); CloseMail(qp, t); qp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid); msgptr = ftell(qp); } } else fseek(mp, msgshdr.syssize, SEEK_CUR); } MacroVars("ZBCDbcd", "ddddddd", (int) 0 , rlw, rlm, rlt, plw, plm, plt); fsetpos(fi,&fileptr2); if (((ftell(qp) - msgptr) / 1024) >= CFG.new_split) { MacroVars("Z","d",1); Syslog('-', " Splitting message at %ld bytes", ftell(qp) - msgptr); CloseMail(qp, t); qp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid); msgptr = ftell(qp); } MacroRead(fi, qp); } } } MacroRead(fi, qp); MacroClear(); fclose(fi); CloseMail(qp, t); fclose(mp); fclose(gp); } else WriteError("Can't create netmail"); free(subject); } void A_Status(faddr *, char *); void A_Status(faddr *t, char *replyid) { FILE *fp, *fi; int i; char *subject; faddr *ta; subject = calloc(255, sizeof(char)); sprintf(subject,"AreaMgr Status"); Mgrlog("AreaMgr: Status"); if (Miy == 0) i = 11; else i = Miy - 1; MacroVars("D", "d", nodes.Direct); MacroVars("C", "d", nodes.Crash); MacroVars("E", "d", nodes.Hold); MacroVars("f", "d", nodes.Notify); MacroVars("G", "c", nodes.Language); MacroVars("v", "s", aka2str(nodes.RouteVia)); MacroVars("P", "d", nodes.MailSent.lweek); MacroVars("Q", "d", nodes.MailSent.month[i]); MacroVars("R", "d", nodes.MailSent.total); MacroVars("p", "d", nodes.MailRcvd.lweek); MacroVars("q", "d", nodes.MailRcvd.month[i]); MacroVars("r", "d", nodes.MailRcvd.total); MacroVars("s", "s", nodes.Sysop); MacroVars("Y", "s", ascfnode(t, 0xff)); ta = bestaka_s(t); MacroVars("y", "s", ascfnode(ta, 0xf)); tidy_faddr(ta); GetRpSubject("areamgr.status",subject); if ((fi = OpenMacro("areamgr.status", nodes.Language, FALSE)) == NULL ){ MacroClear(); free(subject); return; } if ((fp = SendMgrMail(t, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid)) != NULL) { MacroRead(fi, fp); fclose(fi); fprintf(fp, "%s\r", TearLine()); CloseMail(fp, t); } else WriteError("Can't create netmail"); MacroClear(); free(subject); } void A_Unlinked(faddr *, char *); void A_Unlinked(faddr *t, char *replyid) { A_List(t, replyid, LIST_UNLINK); } void A_Disconnect(faddr *, char *, FILE *); void A_Disconnect(faddr *t, char *Area, FILE *tmp) { int i, First; char *Group; faddr *b, *Temp; sysconnect Sys; Mgrlog("AreaMgr: disconnect \"%s\"", Area); ShiftBuf(Area, 1); for (i=0; i < strlen(Area); i++ ) Area[i]=toupper(Area[i]); if (!SearchMsgs(Area)) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop, "Areamgr"); MacroVars("RABCDE", "ssssss","ERR_DISC_NOTFOUND",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" Area not found"); MacroClear(); return; } Syslog('m', " Found %s group %s", msgs.Tag, mgroup.Name); First = TRUE; while ((Group = GetNodeMailGrp(First)) != NULL) { First = FALSE; if (strcmp(Group, mgroup.Name) == 0) break; } if (Group == NULL) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop, "Areamgr"); MacroVars("RABCDE", "ssssss","ERR_DISC_NOTGROUP",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" Group %s not available for %s", mgroup.Name, ascfnode(t, 0x1f)); MacroClear(); return; } b = bestaka_s(t); Temp = fido2faddr(msgs.Aka); i = metric(b, Temp); tidy_faddr(Temp); Syslog('m', "Aka match level is %d", i); if (i >= METRIC_NET) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop, "Areamgr"); MacroVars("RABCDE", "ssssss","ERR_DISC_BADADD",Area,ascfnode(t, 0x1f),"","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" %s may not disconnect from group %s", ascfnode(t, 0x1f), mgroup.Name); MacroClear(); return; } memset(&Sys, 0, sizeof(Sys)); memcpy(&Sys.aka, faddr2fido(t), sizeof(fidoaddr)); Sys.sendto = FALSE; Sys.receivefrom = FALSE; if (!MsgSystemConnected(Sys)) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","ERR_DISC_NC",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" %s is not connected to %s", ascfnode(t, 0x1f), Area); MacroClear(); return; } if (MsgSystemConnect(&Sys, FALSE)) { /* * Make sure to write an overview afterwards. */ a_list = TRUE; Mgrlog("Disconnected echo area %s", Area); MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","OK_DISC",Area,"","","",""); MsgResult("areamgr.responses",tmp); MacroClear(); return; } MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","ERR_DISC_NOTAVAIL",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog("Didn't disconnect %s from mandatory or cutoff echo area %s", ascfnode(t, 0x1f), Area); MacroClear(); } void A_Connect(faddr *, char *, FILE *); void A_Connect(faddr *t, char *Area, FILE *tmp) { int i, First; char *Group, *temp; faddr *b, *Temp; sysconnect Sys; FILE *gp; Mgrlog("AreaMgr: connect \"%s\"", printable(Area, 0)); if (Area[0] == '+') ShiftBuf(Area, 1); for (i=0; i < strlen(Area); i++ ) Area[i]=toupper(Area[i]); if (!SearchMsgs(Area)) { /* * Close noderecord, autocreate will destroy it. */ UpdateNode(); Syslog('m', " Area not found, trying to create"); temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s/etc/mgroups.data", getenv("MBSE_ROOT")); if ((gp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); free(temp); return; } fread(&mgrouphdr, sizeof(mgrouphdr), 1, gp); fseek(gp, mgrouphdr.hdrsize, SEEK_SET); while ((fread(&mgroup, mgrouphdr.recsize, 1, gp)) == 1) { if ((mgroup.UseAka.zone == t->zone) && (mgroup.UseAka.net == t->net) && mgroup.UpLink.zone && strlen(mgroup.AreaFile) && mgroup.Active && mgroup.UserChange) { if (CheckEchoGroup(Area, mgroup.UpLink.zone, t) == 0) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","ERR_CONN_FORWARD",Area,aka2str(mgroup.UpLink),"","",""); MsgResult("areamgr.responses",tmp); break; } } } fclose(gp); free(temp); /* * Restore noderecord and try to load the area again */ SearchNodeFaddr(t); if (!SearchMsgs(Area)) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop, "Areamgr"); MacroVars("RABCDE", "ssssss","ERR_CONN_NOTFOUND",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog("Area %s not found", Area); MacroClear(); return; } } Syslog('m', " Found %s group %s", msgs.Tag, mgroup.Name); First = TRUE; while ((Group = GetNodeMailGrp(First)) != NULL) { First = FALSE; if (strcmp(Group, mgroup.Name) == 0) break; } if (Group == NULL) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop, "Areamgr"); MacroVars("RABCDE", "ssssss","ERR_CONN_NOTGROUP",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" Group %s not available for node %s", mgroup.Name, ascfnode(t, 0x1f)); MacroClear(); return; } b = bestaka_s(t); Temp = fido2faddr(msgs.Aka); i = metric(b, Temp); tidy_faddr(Temp); Syslog('m', "Aka match level is %d", i); if (i >= METRIC_NET) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","ERR_CONN_BADADD",Area,ascfnode(t, 0x1f),"","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" %s may not connect to group %s", ascfnode(t, 0x1f), mgroup.Name); MacroClear(); return; } if (! Access(nodes.Security, msgs.LinkSec)) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); /* * If node has no access by flags, we lie and say "Area not found" */ MacroVars("RABCDE", "ssssss","ERR_CONN_NOTFOUND",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" %s has no access to %s", ascfnode(t, 0x1f), Area); MacroClear(); return; } memset(&Sys, 0, sizeof(Sys)); memcpy(&Sys.aka, faddr2fido(t), sizeof(fidoaddr)); Sys.sendto = TRUE; Sys.receivefrom = TRUE; if (MsgSystemConnected(Sys)) { MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","ERR_CONN_ALREADY",Area,"","","",""); MsgResult("areamgr.responses",tmp); Mgrlog(" %s is already connected to %s", ascfnode(t, 0x1f), Area); MacroClear(); return; } if (MsgSystemConnect(&Sys, TRUE)) { /* * Make sure to write an overview afterwards. */ a_list = TRUE; Mgrlog("Connected echo area %s", Area); MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","OK_CONN",Area,aka2str(msgs.Aka),"","",""); MsgResult("areamgr.responses",tmp); MacroClear(); return; } MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","ERR_CONN_NOTAVAIL",Area,"","","",""); MsgResult("areamgr.responses",tmp); WriteError("Can't connect node %s to echo area %s", ascfnode(t, 0x1f), Area); MacroClear(); } void A_All(faddr *, int, FILE *, char *); void A_All(faddr *t, int Connect, FILE *tmp, char *Grp) { FILE *mp, *gp; char *Group, *temp; faddr *f, *Temp; int i, Link, First = TRUE, Cons; sysconnect Sys; long Pos; if (Grp == NULL) { if (Connect) Mgrlog("AreaMgr: Connect All"); else Mgrlog("AreaMgr: Disconnect All"); } else { if (Connect) Mgrlog("AreaMgr: Connect group %s", Grp); else Mgrlog("AreaMgr: Disconnect group %s", Grp); } f = bestaka_s(t); temp = xstrcpy(ascfnode(t, 0x1f)); Syslog('m', "Bestaka for %s is %s", temp, ascfnode(f, 0x1f)); free(temp); temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT")); if ((mp = fopen(temp, "r+")) == NULL) { WriteError("$Can't open %s", temp); free(temp); return; } fread(&msgshdr, sizeof(msgshdr), 1, mp); Cons = msgshdr.syssize / sizeof(Sys); sprintf(temp, "%s/etc/mgroups.data", getenv("MBSE_ROOT")); if ((gp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); free(temp); fclose(mp); return; } fread(&mgrouphdr, sizeof(mgrouphdr), 1, gp); free(temp); while (TRUE) { Group = GetNodeMailGrp(First); if (Group == NULL) break; First = FALSE; fseek(gp, mgrouphdr.hdrsize, SEEK_SET); while (fread(&mgroup, mgrouphdr.recsize, 1, gp) == 1) { if ((!strcmp(mgroup.Name, Group)) && ((Grp == NULL) || (!strcmp(Group, Grp)))) { fseek(mp, msgshdr.hdrsize, SEEK_SET); while (fread(&msgs, msgshdr.recsize, 1, mp) == 1) { Temp = fido2faddr(msgs.Aka); if ((!strcmp(Group, msgs.Group)) && (msgs.Active) && (!msgs.Mandatory) && strlen(msgs.Tag) && ((msgs.Type == ECHOMAIL) || (msgs.Type == NEWS) || (msgs.Type == LIST)) && (metric(Temp, f) < METRIC_NET) && Access(nodes.Security, msgs.LinkSec)) { if (Connect) { Link = FALSE; for (i = 0; i < Cons; i++) { fread(&Sys, sizeof(Sys), 1, mp); tidy_faddr(Temp); Temp = fido2faddr(Sys.aka); if (metric(Temp, t) == METRIC_EQUAL) Link = TRUE; } if (!Link) { Pos = ftell(mp); fseek(mp, - msgshdr.syssize, SEEK_CUR); for (i = 0; i < Cons; i++) { fread(&Sys, sizeof(Sys), 1, mp); if (!Sys.aka.zone) { memset(&Sys, 0, sizeof(Sys)); memcpy(&Sys.aka, faddr2fido(t), sizeof(fidoaddr)); Sys.sendto = TRUE; Sys.receivefrom = TRUE; fseek(mp, - sizeof(Sys), SEEK_CUR); fwrite(&Sys, sizeof(Sys), 1, mp); Mgrlog("AreaMgr: Connected %s", msgs.Tag); MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","OK_CONN",msgs.Tag,aka2str(msgs.Aka),"","",""); MsgResult("areamgr.responses",tmp); MacroClear(); a_list = TRUE; break; } } fseek(mp, Pos, SEEK_SET); } } else { for (i = 0; i < Cons; i++) { fread(&Sys, sizeof(Sys), 1, mp); tidy_faddr(Temp); Temp = fido2faddr(Sys.aka); if ((metric(Temp, t) == METRIC_EQUAL) && (!Sys.cutoff)) { memset(&Sys, 0, sizeof(Sys)); fseek(mp, - sizeof(Sys), SEEK_CUR); fwrite(&Sys, sizeof(Sys), 1, mp); Mgrlog("AreaMgr: Disconnected %s", msgs.Tag); MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","OK_DISC",msgs.Tag,"","","",""); MsgResult("areamgr.responses",tmp); MacroClear(); a_list = TRUE; } } } } else fseek(mp, msgshdr.syssize, SEEK_CUR); tidy_faddr(Temp); } } } } fclose(gp); fclose(mp); } void A_Group(faddr *, char *, int, FILE *); void A_Group(faddr *t, char *Area, int Connect, FILE *tmp) { int i; ShiftBuf(Area, 2); CleanBuf(Area); for (i = 0; i < strlen(Area); i++ ) Area[i] = toupper(Area[i]); A_All(t, Connect, tmp, Area); } void A_Pause(faddr *, int, FILE *); void A_Pause(faddr *t, int Pause, FILE *tmp) { FILE *mp; faddr *f, *Temp; int i, Cons; sysconnect Sys; char *temp; if (Pause) Mgrlog("AreaMgr: Pause"); else Mgrlog("AreaMgr: Resume"); f = bestaka_s(t); Syslog('m', "Bestaka for %s is %s", ascfnode(t, 0x1f), ascfnode(f, 0x1f)); temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT")); if ((mp = fopen(temp, "r+")) == NULL) { WriteError("$Can't open %s", temp); free(temp); return; } free(temp); fread(&msgshdr, sizeof(msgshdr), 1, mp); Cons = msgshdr.syssize / sizeof(Sys); while (fread(&msgs, msgshdr.recsize, 1, mp) == 1) { if (msgs.Active) { for (i = 0; i < Cons; i++) { fread(&Sys, sizeof(Sys), 1, mp); Temp = fido2faddr(Sys.aka); if ((metric(Temp, t) == METRIC_EQUAL) && (!Sys.cutoff)) { Sys.pause = Pause; fseek(mp, - sizeof(Sys), SEEK_CUR); fwrite(&Sys, sizeof(Sys), 1, mp); Mgrlog("AreaMgr: %s area %s", Pause?"Pause":"Resume", msgs.Tag); MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssdsss","OK_PAUSE",msgs.Tag,Pause,"","",""); MsgResult("areamgr.responses",tmp); a_list = TRUE; } tidy_faddr(Temp); } } else { fseek(mp, msgshdr.syssize, SEEK_CUR); } } fclose(mp); } void A_Rescan(faddr *, char *, FILE *); void A_Rescan(faddr *t, char *Area, FILE *tmp) { int i,result; /* * First strip leading garbage */ ShiftBuf(Area, 7); CleanBuf(Area); for (i = 0; i < strlen(Area); i++ ) Area[i] = toupper(Area[i]); Mgrlog("AreaMgr: Rescan %s, MSGS=%lu", Area, a_msgs); result = RescanOne(t, Area, a_msgs); MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); if (result == 0){ MacroVars("RABCDE", "ssdsss","OK_RESCAN",Area,a_msgs,"","",""); MsgResult("areamgr.responses",tmp); } else if (result == 1) { MacroVars("RABCDE", "ssssss","ERR_RESCAN_UNK",Area,"","","",""); MsgResult("areamgr.responses",tmp); } else if (result == 2) { MacroVars("RABCDE", "ssssss","ERR_RESCAN_NOTAVAIL",Area,ascfnode(t, 0x1f),"","",""); MsgResult("areamgr.responses",tmp); } else { MacroVars("RABCDE", "ssssss","ERR_RESCAN_FATAL",Area,ascfnode(t, 0x1f),"","",""); MsgResult("areamgr.responses",tmp); } MacroClear(); } void A_Msgs(char *, int); void A_Msgs(char *Buf, int skip) { /* * First strip leading garbage */ ShiftBuf(Buf, skip); CleanBuf(Buf); a_msgs = strtoul( Buf, (char **)NULL, 10 ); Mgrlog("AreaMgr: msgs %s ", Buf ); } int AreaMgr(faddr *f, faddr *t, char *replyid, char *subj, time_t mdate, int flags, FILE *fp) { int i, rc = 0, spaces; char *Buf, *subject; FILE *tmp, *np; a_help = a_stat = a_unlnk = a_list = a_query = FALSE; areamgr++; if (SearchFidonet(f->zone)) f->domain = xstrcpy(fidonet.domain); Mgrlog("AreaMgr request from %s start", ascfnode(f, 0xff)); /* * If the password failed, we return silently and don't respond. */ if ((!strlen(subj)) || (strcasecmp(subj, nodes.Apasswd))) { WriteError("AreaMgr: password expected \"%s\", got \"%s\"", nodes.Apasswd, subj); Mgrlog("AreaMgr request from %s finished", ascfnode(f, 0xff)); net_bad++; return FALSE; } if ((tmp = tmpfile()) == NULL) { WriteError("$AreaMgr: Can't open tmpfile()"); net_bad++; return FALSE; } Buf = calloc(MAX_LINE_LENGTH +1, sizeof(char)); rewind(fp); while ((fgets(Buf, MAX_LINE_LENGTH, fp)) != NULL) { /* * Make sure we have the nodes record loaded */ SearchNodeFaddr(f); spaces = 0; for (i = 0; i < strlen(Buf); i++) { if (*(Buf + i) == ' ') spaces++; if (*(Buf + i) == '\t') spaces++; if (*(Buf + i) == '\0') break; if (*(Buf + i) == '\n') *(Buf + i) = '\0'; if (*(Buf + i) == '\r') *(Buf + i) = '\0'; } if (!strncmp(Buf, "---", 3)) break; if (strlen(Buf) && (*(Buf) != '\001') && (spaces <= 1)) { if (!strncasecmp(Buf, "%help", 5)) a_help = TRUE; else if (!strncasecmp(Buf, "%query", 6)) a_query = TRUE; else if (!strncasecmp(Buf, "%linked", 7)) a_query = TRUE; else if (!strncasecmp(Buf, "%list", 5)) a_list = TRUE; else if (!strncasecmp(Buf, "%status", 7)) a_stat = TRUE; else if (!strncasecmp(Buf, "%unlinked", 9)) a_unlnk = TRUE; else if (!strncasecmp(Buf, "%flow", 5)) a_flow = TRUE; else if (!strncasecmp(Buf, "%msgs", 5)) A_Msgs(Buf, 5); else if (!strncasecmp(Buf, "%rescan", 7)) A_Rescan(f, Buf, tmp); else if (!strncasecmp(Buf, "%+all", 5) && CFG.ca_PlusAll) A_All(f, TRUE, tmp, NULL); else if (!strncasecmp(Buf, "%-all", 5) && CFG.ca_PlusAll) A_All(f, FALSE, tmp, NULL); else if (!strncasecmp(Buf, "%+*", 3) && CFG.ca_PlusAll) A_All(f, TRUE, tmp, NULL); else if (!strncasecmp(Buf, "%-*", 3) && CFG.ca_PlusAll) A_All(f, FALSE, tmp, NULL); else if (!strncasecmp(Buf, "%+", 2)) A_Group(f, Buf, TRUE, tmp); else if (!strncasecmp(Buf, "%-", 2)) A_Group(f, Buf, FALSE, tmp); else if (!strncasecmp(Buf, "%pause", 6) && CFG.ca_Pause) A_Pause(f, TRUE, tmp); else if (!strncasecmp(Buf, "%resume", 7) && CFG.ca_Pause) A_Pause(f, FALSE, tmp); else if (!strncasecmp(Buf, "%passive", 8) && CFG.ca_Pause) A_Pause(f, TRUE, tmp); else if (!strncasecmp(Buf, "%active", 7) && CFG.ca_Pause) A_Pause(f, FALSE, tmp); else if (!strncasecmp(Buf, "%password", 9) && CFG.ca_Passwd) MgrPasswd(f, Buf, tmp, 9, 0); else if (!strncasecmp(Buf, "%pwd", 4) && CFG.ca_Passwd) MgrPasswd(f, Buf, tmp, 4, 0); else if (!strncasecmp(Buf, "%notify", 7) && CFG.ca_Notify) MgrNotify(f, Buf, tmp, 0); else if (*(Buf) == '-') A_Disconnect(f, Buf, tmp); else A_Connect(f, Buf, tmp); } } /* * If the temporary response file isn't empty, * create a response netmail about what we did. */ if (ftell(tmp)) { subject=calloc(256,sizeof(char)); MacroVars("SsP", "sss", CFG.sysop_name, nodes.Sysop,"Areamgr"); MacroVars("RABCDE", "ssssss","","","","","",""); sprintf(subject,"Your AreaMgr request"); GetRpSubject("areamgr.responses",subject); if ((np = SendMgrMail(f, CFG.ct_KeepMgr, FALSE, (char *)"Areamgr", subject, replyid)) != NULL) { MacroVars("RABCDE", "ssssss","WELLCOME","","","","",""); MsgResult("areamgr.responses",np); fprintf(np, "\r"); fseek(tmp, 0, SEEK_SET); while ((fgets(Buf, MAX_LINE_LENGTH, tmp)) != NULL) { while ((Buf[strlen(Buf) - 1]=='\n') || (Buf[strlen(Buf) - 1]=='\r')) { Buf[strlen(Buf) - 1] = '\0'; } fprintf(np, "%s\r", Buf); } fprintf(np, "\r"); MacroVars("RABCDE", "ssssss","GOODBYE","","","","",""); MsgResult("areamgr.responses",np); fprintf(np, "\r%s\r", TearLine()); CloseMail(np, t); } else WriteError("Can't create netmail"); free(subject); } MacroClear(); free(Buf); fclose(tmp); if (a_stat) A_Status(f, replyid); if (a_query) A_Query(f, replyid); if (a_list) A_List(f, replyid, LIST_LIST); if (a_flow) A_Flow(f, replyid, FALSE); if (a_unlnk) A_Unlinked(f, replyid); if (a_help) A_Help(f, replyid); Mgrlog("AreaMgr request from %s finished", ascfnode(f, 0xff)); return rc; }