261 lines
6.3 KiB
C
261 lines
6.3 KiB
C
/*****************************************************************************
|
|
*
|
|
* $Id$
|
|
* Purpose ...............: mbtask - mode portlists
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (C) 1997-2006
|
|
*
|
|
* 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, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*****************************************************************************/
|
|
|
|
#include "../config.h"
|
|
#include "../lib/mbselib.h"
|
|
#include "taskutil.h"
|
|
#include "../lib/nodelist.h"
|
|
#include "ports.h"
|
|
|
|
|
|
#ifndef LOCKDIR
|
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
|
#define LOCKDIR "/var/spool/lock"
|
|
#else
|
|
#define LOCKDIR "/var/lock"
|
|
#endif
|
|
#endif
|
|
|
|
#define LCKPREFIX LOCKDIR"/LCK.."
|
|
#define LCKTMP LOCKDIR"/TMP."
|
|
|
|
|
|
extern char ttyfn[]; /* TTY file name */
|
|
extern time_t tty_time; /* TTY update time */
|
|
extern int rescan; /* Master rescan flag */
|
|
pp_list *pl = NULL; /* Portlist */
|
|
|
|
int pots_lines = 0; /* POTS (Modem) lines */
|
|
int isdn_lines = 0; /* ISDN lines */
|
|
int pots_free = 0; /* POTS (Modem) lines free */
|
|
int isdn_free = 0; /* ISDN lines free */
|
|
|
|
|
|
|
|
/*
|
|
* Tidy the portlist
|
|
*/
|
|
void tidy_portlist(pp_list **);
|
|
void tidy_portlist(pp_list ** fdp)
|
|
{
|
|
pp_list *tmp, *old;
|
|
|
|
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));
|
|
memset(tmp, 0, sizeof(tmp));
|
|
tmp->next = NULL;
|
|
strncpy(tmp->tty, new->tty, 6);
|
|
tmp->mflags = new->mflags;
|
|
tmp->dflags = new->dflags;
|
|
tmp->locktime = 0;
|
|
|
|
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 stdflag;
|
|
char *p, *q, *capflags;
|
|
nodelist_modem **tmpm;
|
|
|
|
tidy_portlist(&pl);
|
|
if ((fp = fopen(ttyfn, "r")) == NULL) {
|
|
Syslog('?', "$Can't open %s", ttyfn);
|
|
return;
|
|
}
|
|
fread(&ttyinfohdr, sizeof(ttyinfohdr), 1, fp);
|
|
|
|
pots_lines = isdn_lines = 0;
|
|
|
|
while (fread(&ttyinfo, ttyinfohdr.recsize, 1, fp) == 1) {
|
|
if (((ttyinfo.type == POTS) || (ttyinfo.type == ISDN)) && (ttyinfo.available) && (ttyinfo.callout)) {
|
|
|
|
if (ttyinfo.type == POTS)
|
|
pots_lines++;
|
|
if (ttyinfo.type == ISDN)
|
|
isdn_lines++;
|
|
|
|
memset(&new, 0, sizeof(new));
|
|
strncpy(new.tty, ttyinfo.tty, 6);
|
|
|
|
capflags = xstrcpy((char *)"flags:");
|
|
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 (tmpm = &nl_pots; *tmpm; tmpm=&((*tmpm)->next))
|
|
if (strcasecmp(p, (*tmpm)->name) == 0) {
|
|
new.mflags |= (*tmpm)->value;
|
|
capflags = xstrcat(capflags, (char *)" ");
|
|
capflags = xstrcat(capflags, (*tmpm)->name);
|
|
}
|
|
for (tmpm = &nl_isdn; *tmpm; tmpm=&((*tmpm)->next))
|
|
if (strcasecmp(p, (*tmpm)->name) == 0) {
|
|
new.dflags |= (*tmpm)->value;
|
|
capflags = xstrcat(capflags, (char *)" ");
|
|
capflags = xstrcat(capflags, (*tmpm)->name);
|
|
}
|
|
}
|
|
}
|
|
free(q);
|
|
|
|
Syslog('+', "Found line %s, %s", new.tty, capflags);
|
|
fill_portlist(&pl, &new);
|
|
if (capflags)
|
|
free(capflags);
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
tty_time = file_time(ttyfn);
|
|
Syslog('+', "Detected %d modem port%s and %d ISDN port%s",
|
|
pots_lines, (pots_lines == 1)?"":"s", isdn_lines, (isdn_lines == 1)?"":"s");
|
|
}
|
|
|
|
|
|
|
|
void unload_ports()
|
|
{
|
|
tidy_portlist(&pl);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Check status of all modem/ISDN ports.
|
|
* If something is changed set the master rescan flag.
|
|
*/
|
|
void check_ports(void)
|
|
{
|
|
pp_list *tpl;
|
|
char *lckname, *progname;
|
|
FILE *lf;
|
|
int tmppid, changed = FALSE;
|
|
pid_t rempid = 0;
|
|
|
|
pots_free = isdn_free = 0;
|
|
lckname = calloc(PATH_MAX, sizeof(char));
|
|
|
|
for (tpl = pl; tpl; tpl = tpl->next) {
|
|
snprintf(lckname, PATH_MAX, "%s%s", LCKPREFIX, tpl->tty);
|
|
if ((lf = fopen(lckname, "r")) == NULL) {
|
|
if (tpl->locked) {
|
|
tpl->locked = 0;
|
|
Syslog('+', "Port %s is now free after %d seconds", tpl->tty, tpl->locktime);
|
|
if (tpl->locktime > 4)
|
|
/*
|
|
* Good, set master rescan flag if longer then 4 seconds locked.
|
|
*/
|
|
changed = TRUE;
|
|
}
|
|
} else {
|
|
fscanf(lf, "%d", &tmppid);
|
|
rempid = tmppid;
|
|
fclose(lf);
|
|
if (kill(rempid, 0) && (errno == ESRCH)) {
|
|
Syslog('+', "Stale lockfile for %s, unlink", tpl->tty);
|
|
unlink(lckname);
|
|
changed = TRUE;
|
|
} else {
|
|
if (!tpl->locked) {
|
|
tpl->locked = rempid;
|
|
tpl->locktime = 0;
|
|
progname = calloc(PATH_MAX, sizeof(char));
|
|
if (pid2prog(rempid, progname, PATH_MAX) == 0)
|
|
Syslog('+', "Port %s locked, pid %d (%s)", tpl->tty, rempid, progname);
|
|
else
|
|
Syslog('+', "Port %s locked, pid %d", tpl->tty, rempid);
|
|
free(progname);
|
|
} else {
|
|
/*
|
|
* Count locktime
|
|
*/
|
|
tpl->locktime++;
|
|
if (tpl->locktime == 5) {
|
|
changed = TRUE;
|
|
Syslog('+', "Port %s locked for 5 seconds, forcing scan", tpl->tty);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now count free ports
|
|
*/
|
|
if (tpl->mflags && !tpl->locked)
|
|
pots_free++;
|
|
if (tpl->dflags && !tpl->locked)
|
|
isdn_free++;
|
|
|
|
if (changed) {
|
|
rescan = TRUE;
|
|
Syslog('p', "Free ports: pots=%d isdn=%d", pots_free, isdn_free);
|
|
}
|
|
}
|
|
free(lckname);
|
|
}
|
|
|
|
|