diff --git a/ChangeLog b/ChangeLog index 14650e6c..f1500d2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4388,6 +4388,9 @@ v0.33.19 26-Oct-2001 are present. When the internet connection status changes, the outbound is rescanned. + Implemented Txx nodelist flags, FSC-0062. + Added code to see which nodes could be called depending on + outbound status, nodelist flags etc. Experimental. mbmon: Changed the lastcaller screen to display the External Door diff --git a/mbtask/Makefile b/mbtask/Makefile index 3c94691d..f063cd8d 100644 --- a/mbtask/Makefile +++ b/mbtask/Makefile @@ -79,9 +79,9 @@ nodelist.o: libs.h ../lib/structs.h taskutil.h nodelist.h scanout.o: libs.h ../lib/structs.h taskutil.h scanout.h taskcomm.o: libs.h taskstat.h taskregs.h taskdisk.h taskinfo.h taskutil.h taskcomm.h taskinfo.o: libs.h ../lib/structs.h taskinfo.h -taskstat.o: libs.h ../lib/structs.h taskstat.h outstat.h taskutil.h -mbtask.o: libs.h ../lib/structs.h signame.h taskstat.h taskutil.h taskregs.h taskcomm.h outstat.h nodelist.h mbtask.h -outstat.o: libs.h ../lib/structs.h taskutil.h scanout.h nodelist.h callstat.h outstat.h +taskstat.o: libs.h ../lib/structs.h taskstat.h callstat.h outstat.h taskutil.h +mbtask.o: libs.h ../lib/structs.h signame.h taskstat.h taskutil.h taskregs.h taskcomm.h callstat.h outstat.h nodelist.h mbtask.h +outstat.o: libs.h ../lib/structs.h taskutil.h taskstat.h scanout.h nodelist.h callstat.h outstat.h signame.o: signame.h taskdisk.o: libs.h taskdisk.h taskutil.h taskregs.o: libs.h taskstat.h taskregs.h taskutil.h diff --git a/mbtask/mbtask.c b/mbtask/mbtask.c index 77723025..14ddfcb1 100644 --- a/mbtask/mbtask.c +++ b/mbtask/mbtask.c @@ -35,6 +35,7 @@ #include "taskutil.h" #include "taskregs.h" #include "taskcomm.h" +#include "callstat.h" #include "outstat.h" #include "nodelist.h" #include "mbtask.h" @@ -79,8 +80,10 @@ struct _fidonethdr fidonethdr; /* Fidonet header rec. */ struct _fidonet fidonet; /* Fidonet data record */ time_t tcfg_time; /* Config record time */ time_t cfg_time; /* Config record time */ +time_t tty_time; /* TTY config time */ char tcfgfn[PATH_MAX]; /* Config file name */ char cfgfn[PATH_MAX]; /* Config file name */ +char ttyfn[PATH_MAX]; /* TTY file name */ int ping_isocket; /* Ping socket */ int icmp_errs = 0; /* ICMP error counter */ int internet = FALSE; /* Internet is down */ @@ -103,6 +106,8 @@ char pingaddress[41]; /* Ping current address */ int masterinit = FALSE; /* Master init needed */ int ptimer = PAUSETIME; /* Pause timer */ int tflags = FALSE; /* if nodes with Txx */ +extern int nxt_hour; /* Next event hour */ +extern int nxt_min; /* Next event minute */ @@ -1049,7 +1054,7 @@ void scheduler(void) char *cmd = NULL; static char doing[32], buf[2048]; time_t now; - struct tm *tm; + struct tm *tm, *utm; FILE *fp; float lavg1, lavg2, lavg3; struct pollfd pfd; @@ -1189,23 +1194,33 @@ void scheduler(void) */ now = time(NULL); tm = localtime(&now); + utm = gmtime(&now); if (tm->tm_min != olddo) { olddo = tm->tm_min; TouchSema((char *)"mbtask.last"); if (file_time(tcfgfn) != tcfg_time) { tasklog('+', "Task configuration changed, reloading"); load_taskcfg(); + sem_set((char *)"scanout", TRUE); } if (file_time(cfgfn) != cfg_time) { tasklog('+', "Main configuration changed, reloading"); load_maincfg(); - } - /* - * If there is mail or files in the outbound for nodes with - * the Txx flag, then scan the outbound each half hour. - */ - if (tflags && ((tm->tm_min == 0) || (tm->tm_min == 30))) sem_set((char *)"scanout", TRUE); + } + if (file_time(ttyfn) != tty_time) { + tasklog('+', "Ports configuration changed, reloading"); + load_ports(); + sem_set((char *)"scanout", TRUE); + } + + /* + * If the next event time is reached, rescan the outbound + */ + if ((utm->tm_hour == nxt_hour) && (utm->tm_min == nxt_min)) { + tasklog('o', "Next event time reached %02d:%02d %02d:%02d", tm->tm_hour, tm->tm_min, utm->tm_hour, utm->tm_min); + sem_set((char *)"scanout", TRUE); + } } if (s_bbsopen && !UPSalarm && !LOADhi) { @@ -1462,6 +1477,9 @@ int main(int argc, char **argv) memset(®info, 0, sizeof(reginfo)); sprintf(spath, "%s/tmp/mbtask", getenv("MBSE_ROOT")); + sprintf(ttyfn, "%s/etc/ttyinfo.data", getenv("MBSE_ROOT")); + load_ports(); + /* * Now that init is complete and this program is locked, it is * safe to remove a stale socket if it is there after a crash. diff --git a/mbtask/outstat.c b/mbtask/outstat.c index 27ac82b9..d52b50b1 100644 --- a/mbtask/outstat.c +++ b/mbtask/outstat.c @@ -31,6 +31,7 @@ #include "libs.h" #include "../lib/structs.h" #include "taskutil.h" +#include "taskstat.h" #include "scanout.h" #include "nodelist.h" #include "callstat.h" @@ -38,27 +39,20 @@ extern int do_quiet; -extern struct sysconfig CFG; +extern int internet; /* Internet status */ +extern struct sysconfig CFG; /* Main configuration */ +extern struct taskrec TCFG; /* Task configuration */ +extern char ttyfn[]; /* TTY file name */ +extern time_t tty_time; /* TTY update time */ +int nxt_hour, nxt_min; /* Time of next event */ +int inet_calls; /* Internet calls to make */ +int isdn_calls; /* ISDN calls to make */ +int pots_calls; /* POTS calls to make */ +pp_list *pl = NULL; /* Portlist */ +_alist_l *alist = NULL; /* Nodes to call list */ -static struct _alist -{ - struct _alist *next; /* Next entry */ - faddr addr; /* Node address */ - int flavors; /* ORed flavors of mail/files */ - time_t time; /* Date/time of mail/files */ - off_t size; /* Total size of mail/files */ - callstat cst; /* Last call status */ - unsigned long olflags; /* Nodelist online flags */ - unsigned long moflags; /* Nodelist modem flags */ - unsigned long diflags; /* Nodelist ISDN flags */ - unsigned long ipflags; /* Nodelist TCP/IP flags */ - int t1; /* First Txx flag */ - int t2; /* Second Txx flag */ -} *alist = NULL; - - #define F_NORMAL 0x0001 #define F_CRASH 0x0002 #define F_IMM 0x0004 @@ -67,16 +61,93 @@ static struct _alist #define F_POLL 0x0020 #define F_ISFLO 0x0040 #define F_ISPKT 0x0080 +#define F_CALL 0x0100 + + +void set_next(int, int); +void set_next(int hour, int min) +{ + time_t now; + struct tm *etm; + int uhour, umin; + + now = time(NULL); + etm = gmtime(&now); + uhour = etm->tm_hour; /* For some reason, these intermediate integers are needed */ + umin = etm->tm_min; + + if ((hour > uhour) || ((hour == uhour) && (min > umin))) { + if (hour < nxt_hour) { + nxt_hour = hour; + nxt_min = min; + tasklog('o', "set_next(%02d:%02d), next event setting %02d:%02d", hour, min, nxt_hour, nxt_min); + } else if ((hour == nxt_hour) && (min < nxt_min)) { + nxt_hour = hour; + nxt_min = min; + tasklog('o', "set_next(%02d:%02d), next event setting %02d:%02d", hour, min, nxt_hour, nxt_min); + } + } +} + + + +char *callstatus(int); +char *callstatus(int status) +{ + switch (status) { + case 0: return (char *)"Ok "; + case 1: return (char *)"tty err"; + case 2: return (char *)"No conn"; + case 3: return (char *)"Mdm err"; + case 4: return (char *)"Locked "; + case 5: return (char *)"unknown"; + case 6: return (char *)"Unlist "; + case 7: return (char *)"error 7"; + case 8: return (char *)"error 8"; + case 9: return (char *)"No tty "; + case 10: return (char *)"No ZMH "; + case 30: return (char *)"Badsess"; + default: return (char *)"ERROR "; + } +} + + + +char *callmode(int mode) +{ + switch (mode) { + case CM_NONE: return (char *)"None"; + case CM_INET: return (char *)"Inet"; + case CM_ISDN: return (char *)"ISDN"; + case CM_POTS: return (char *)"POTS"; + default: return (char *)"None"; + } +} + int outstat() { - int rc, first = TRUE; + int rc, first = TRUE, T_window, iszmh = FALSE, pass_midnight; struct _alist *tmp, *old; char flstr[13]; char temp[81]; + char as[6], be[6], utc[6]; + time_t now; + struct tm *tm; + int uhour, umin, thour, tmin; + pp_list *tpl; + + now = time(NULL); + tm = gmtime(&now); /* UTC time */ + uhour = tm->tm_hour; + umin = tm->tm_min; + sprintf(utc, "%02d:%02d", uhour, umin); + tasklog('+', "Scanning outbound at %s UTC.", utc); + nxt_hour = 24; + nxt_min = 0; + inet_calls = isdn_calls = pots_calls = 0; - tasklog('+', "Scanning outbound"); /* * Clear current table */ @@ -92,30 +163,208 @@ int outstat() return rc; } + /* + * During processing the outbound list, determine when the next event will occur, + * ie. the time when the callout status of a node changes because of starting a + * ZMH, or changeing the time window for Txx flags. + */ for (tmp = alist; tmp; tmp = tmp->next) { if (first) { - tasklog('+', "Flavor Out Size Online Modem ISDN TCP/IP Calls Status Address"); + tasklog('+', "Flavor Out Size Online Modem ISDN TCP/IP Calls Status Mode Address"); first = FALSE; } - strcpy(flstr,"...... ... .."); - if ((tmp->flavors) & F_IMM ) flstr[0]='I'; - if ((tmp->flavors) & F_CRASH ) flstr[1]='C'; - if ((tmp->flavors) & F_NORMAL) flstr[2]='N'; - if ((tmp->flavors) & F_HOLD ) flstr[3]='H'; - if ((tmp->flavors) & F_FREQ ) flstr[4]='R'; - if ((tmp->flavors) & F_POLL ) flstr[5]='P'; - if ((tmp->flavors) & F_ISPKT ) flstr[7]='M'; - if ((tmp->flavors) & F_ISFLO ) flstr[8]='F'; - if (tmp->t1) flstr[11] = tmp->t1; - if (tmp->t2) flstr[12] = tmp->t2; - sprintf(temp, "%s %8lu %08x %08x %08x %08x %5d %6d %s", flstr, (long)tmp->size, - (unsigned int)tmp->olflags, (unsigned int)tmp->moflags, - (unsigned int)tmp->diflags, (unsigned int)tmp->ipflags, - tmp->cst.tryno, tmp->cst.trystat, ascfnode(&(tmp->addr), 0x1f)); + /* + * Zone Mail Hours, only use Fidonet Hours. + * Other nets use your default ZMH. + */ + T_window = iszmh = FALSE; + switch (tmp->addr.zone) { + case 1: if (uhour == 9) + iszmh = TRUE; + set_next(9, 0); + set_next(10, 0); + break; + case 2: if (((uhour >= 2) && (umin >= 30)) && ((uhour <= 3) && (umin < 30))) + iszmh = TRUE; + set_next(2, 30); + set_next(3, 30); + break; + case 3: if (uhour == 18) + iszmh = TRUE; + set_next(18, 0); + set_next(19, 0); + break; + case 4: if (uhour == 8) + iszmh = TRUE; + set_next(8, 0); + set_next(9, 0); + break; + case 5: if (uhour == 1) + iszmh = TRUE; + set_next(1, 0); + set_next(2, 0); + break; + case 6: if (uhour == 20) + iszmh = TRUE; + set_next(20, 0); + set_next(21, 0); + break; + default: if (get_zmh()) + iszmh = TRUE; + break; + } + + if (tmp->t1 && tmp->t2) { + /* + * Txx flags, check callwindow + */ + thour = toupper(tmp->t1) - 'A'; + if (isupper(tmp->t1)) + tmin = 0; + else + tmin = 30; + sprintf(as, "%02d:%02d", thour, tmin); + set_next(thour, tmin); + thour = toupper(tmp->t2) - 'A'; + if (isupper(tmp->t2)) + tmin = 0; + else + tmin = 30; + sprintf(be, "%02d:%02d", thour, tmin); + set_next(thour, tmin); + if (strcmp(as, be) > 0) + pass_midnight = TRUE; + else + pass_midnight = FALSE; + tasklog('o', "window %s - %s, pass midnight=%s, %d", as, be, pass_midnight?"true":"false", strcmp(as, be)); + if (pass_midnight) { + tasklog('o', "strcmp(utc, as)=%d strcmp(utc, be)=%d", strcmp(utc, as), strcmp(utc, be)); + if ((strcmp(utc, as) >= 0) || (strcmp(utc, be) < 0)) + T_window = TRUE; + } else { + tasklog('o', "strcmp(utc, as)=%d strcmp(utc, be)=%d", strcmp(utc, as), strcmp(utc, be)); + if ((strcmp(utc, as) >= 0) && (strcmp(utc, be) < 0)) + T_window = TRUE; + } + } + tasklog('o', "T_window=%s, iszmh=%s", T_window?"true":"false", iszmh?"true":"false"); + strcpy(flstr,"...... ... .."); + if ((tmp->flavors) & F_IMM ) { + flstr[0]='I'; + /* + * Immediate mail, send if node is CM. + */ + if ((tmp->olflags & OL_CM) || T_window) { + tmp->flavors |= F_CALL; + } + } + if ((tmp->flavors) & F_CRASH ) { + flstr[1]='C'; + /* + * Crash mail, send if node is CM. + */ + if ((tmp->olflags & OL_CM) || T_window) { + tmp->flavors |= F_CALL; + } + } + if ((tmp->flavors) & F_NORMAL) { + flstr[2]='N'; + /* + * Normal mail, send during ZMH or if node has a Txx window. + * Also if node has TCP/IP capability and internet is ready. + */ + if (iszmh || T_window || (internet && TCFG.max_tcp && + ((tmp->ipflags & IP_IBN) || (tmp->ipflags & IP_IFC) || (tmp->ipflags & IP_ITN)))) { + tmp->flavors |= F_CALL; + } + } + if ((tmp->flavors) & F_HOLD ) + flstr[3]='H'; + if ((tmp->flavors) & F_FREQ ) + flstr[4]='R'; + if ((tmp->flavors) & F_POLL ) { + flstr[5]='P'; + tmp->flavors |= F_CALL; + } + if ((tmp->flavors) & F_ISPKT ) + flstr[7]='M'; + if ((tmp->flavors) & F_ISFLO ) + flstr[8]='F'; + if (tmp->cst.tryno >= 30) { + /* + * Node is undialable, clear callflag + */ + tmp->flavors &= ~F_CALL; + } + if ((tmp->flavors) & F_CALL ) + flstr[9]='C'; + if (tmp->t1) + flstr[11] = tmp->t1; + if (tmp->t2) + flstr[12] = tmp->t2; + + /* + * If we must call this node, figure out how to call this node. + */ + if ((tmp->flavors) & F_CALL) { + /* + * Get options for this node + */ + + + tmp->callmode = CM_NONE; + if (internet && TCFG.max_tcp && + ((tmp->ipflags & IP_IBN) || (tmp->ipflags & IP_IFC) || (tmp->ipflags & IP_ITN))) { + inet_calls++; + tmp->callmode = CM_INET; + tasklog('o', "Call over internet"); + } + if (!TCFG.ipblocks || (TCFG.ipblocks && !internet)) { + /* + * If TCP/IP blocks other trafic, (you only have one dialup line), + * then don't add normal dial trafic. If not blocking, add lines. + */ + if ((tmp->callmode == CM_NONE) && TCFG.max_isdn) { + /* + * Dialup node, check available dialout ports + */ + for (tpl = pl; tpl; tpl = tpl->next) { + if (tpl->dflags & tmp->diflags) { + isdn_calls++; + tmp->callmode = CM_ISDN; + break; + } + } + } + if ((tmp->callmode == CM_NONE) && TCFG.max_pots) { + for (tpl = pl; tpl; tpl = tpl->next) { + if (tpl->mflags & tmp->moflags) { + pots_calls++; + tmp->callmode = CM_POTS; + break; + } + } + } + } + } + sprintf(temp, "%s %8lu %08x %08x %08x %08x %5d %s %s %s", flstr, (long)tmp->size, + (unsigned int)tmp->olflags, (unsigned int)tmp->moflags, + (unsigned int)tmp->diflags, (unsigned int)tmp->ipflags, + tmp->cst.tryno, callstatus(tmp->cst.trystat), callmode(tmp->callmode), ascfnode(&(tmp->addr), 0x1f)); tasklog('+', "%s", temp); } + + if (nxt_hour == 24) { + /* + * 24:00 hours doesn't exist + */ + nxt_hour = 0; + nxt_min = 0; + } + tasklog('o', "Call inet=%d, isdn=%d, pots=%d", inet_calls, isdn_calls, pots_calls); + tasklog('+', "Next event at %02d:%02d UTC", nxt_hour, nxt_min); return 0; } @@ -259,3 +508,99 @@ int each(faddr *addr, char flavor, int isflo, char *fname) } + +/* + * Tidy the portlist + */ +void tidy_portlist(pp_list **); +void tidy_portlist(pp_list ** fdp) +{ + pp_list *tmp, *old; + + tasklog('p', "tidy_portlist"); + for (tmp = *fdp; tmp; tmp = old) { + old = tmp->next; + free(tmp); + } + *fdp = NULL; +} + + + +/* + * Add a port to the portlist + */ +void fill_portlist(pp_list **, pp_list *); +void fill_portlist(pp_list **fdp, pp_list *new) +{ + pp_list *tmp, *ta; + + tmp = (pp_list *)malloc(sizeof(pp_list)); + tmp->next = NULL; + strncpy(tmp->tty, new->tty, 6); + tmp->mflags = new->mflags; + tmp->dflags = new->dflags; + + if (*fdp == NULL) { + *fdp = tmp; + } else { + for (ta = *fdp; ta; ta = ta->next) + if (ta->next == NULL) { + ta->next = (pp_list *)tmp; + break; + } + } +} + + + +/* + * Build a list of available dialout ports. + */ +void load_ports() +{ + FILE *fp; + pp_list new; + int count = 0, j, stdflag; + char *p, *q; + + tidy_portlist(&pl); + if ((fp = fopen(ttyfn, "r")) == NULL) { + tasklog('?', "$Can't open %s", ttyfn); + return; + } + fread(&ttyinfohdr, sizeof(ttyinfohdr), 1, fp); + + tasklog('p', "Building portlist..."); + while (fread(&ttyinfo, ttyinfohdr.recsize, 1, fp) == 1) { + if (((ttyinfo.type == POTS) || (ttyinfo.type == ISDN)) && (ttyinfo.available) && (ttyinfo.callout)) { + memset(&new, 0, sizeof(new)); + strncpy(new.tty, ttyinfo.tty, 6); + + stdflag = TRUE; + q = xstrcpy(ttyinfo.flags); + for (p = q; p; p = q) { + if ((q = strchr(p, ','))) + *q++ = '\0'; + if ((strncasecmp(p, "U", 1) == 0) && (strlen(p) == 1)) { + stdflag = FALSE; + } else { + for (j = 0; fkey[j].key; j++) + if (strcasecmp(p, fkey[j].key) == 0) + new.mflags |= fkey[j].flag; + for (j = 0; dkey[j].key; j++) + if (strcasecmp(p, dkey[j].key) == 0) + new.dflags |= dkey[j].flag; + } + } + tasklog('p', "port %s modem %08lx ISDN %08lx", new.tty, new.mflags, new.dflags); + fill_portlist(&pl, &new); + count++; + } + } + fclose(fp); + tty_time = file_time(ttyfn); + tasklog('p', "make_portlist %d ports", count); +} + + diff --git a/mbtask/outstat.h b/mbtask/outstat.h index e1aadd6b..74832fb6 100644 --- a/mbtask/outstat.h +++ b/mbtask/outstat.h @@ -1,10 +1,53 @@ +/* $Id$ */ + #ifndef _OUTSTAT_H #define _OUTSTAT_H +typedef enum {CM_NONE, CM_INET, CM_ISDN, CM_POTS} CMODE; -int each(faddr *, char, int, char *); -int outstat(void); +/* + * Linked list of nodes with mail in the outbound. + * Updated after each scan. + */ +typedef struct _alist +{ + struct _alist *next; /* Next entry */ + faddr addr; /* Node address */ + int flavors; /* ORed flavors of mail/files */ + time_t time; /* Date/time of mail/files */ + off_t size; /* Total size of mail/files */ + callstat cst; /* Last call status */ + unsigned long olflags; /* Nodelist online flags */ + unsigned long moflags; /* Nodelist modem flags */ + unsigned long diflags; /* Nodelist ISDN flags */ + unsigned long ipflags; /* Nodelist TCP/IP flags */ + int t1; /* First Txx flag */ + int t2; /* Second Txx flag */ + int callmode; /* Call method */ +} _alist_l; + + +/* + * Linked list of available dialout ports. + */ +typedef struct _pp_list { + struct _pp_list *next; + char tty[7]; /* tty name of the port */ + unsigned long mflags; /* Analogue modem flags */ + unsigned long dflags; /* ISDN flags */ + int locked; /* If port is locked */ +} pp_list; + + +struct _ttyinfohdr ttyinfohdr; /* TTY lines */ +struct _ttyinfo ttyinfo; + + +int each(faddr *, char, int, char *); +char *callmode(int); +int outstat(void); +void load_ports(void); #endif diff --git a/mbtask/taskstat.c b/mbtask/taskstat.c index dcffb0aa..d78d9cec 100644 --- a/mbtask/taskstat.c +++ b/mbtask/taskstat.c @@ -31,6 +31,7 @@ #include "libs.h" #include "../lib/structs.h" #include "taskstat.h" +#include "callstat.h" #include "outstat.h" #include "taskutil.h" @@ -207,14 +208,12 @@ int get_zmh() if ((strncmp(sstime, TCFG.zmh_start, 5) >= 0) && (strncmp(sstime, TCFG.zmh_end, 5) < 0)) { if (!ZMH) { CreateSema((char *)"zmh"); - sem_set((char *)"scanout", TRUE); tasklog('!', "Start of Zone Mail Hour"); ZMH = TRUE; } } else { if (ZMH) { RemoveSema((char *)"zmh"); - sem_set((char *)"scanout", TRUE); tasklog('!', "End of Zone Mail Hour"); ZMH = FALSE; }