/******************************************************************************
* FIDOCONFIG --- library for fidonet configs
******************************************************************************
* afixcmd.c : common areafix commands
*
* Compiled from hpt/areafix hpt/toss hpt/pkt
* by Max Chernogor <mihz@mail.ru>, 2:464/108@fidonet
*
* This file is part of FIDOCONFIG library (part of the Husky FIDOnet
* software project)
*
* This 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.
*
* FIDOCONFIG library 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 FIDOCONFIG library; see the file COPYING. If not, write
* to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA
*
* See also http://www.gnu.org
*****************************************************************************
* $Id: afixcmd.c,v 1.24.2.1 2004/12/08 22:18:42 d_sergienko Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <smapi/compiler.h>
#ifdef HAS_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAS_IO_H
# include <io.h>
#endif
#include <smapi/progprot.h>
#include "afixcmd.h"
#include "common.h"
#include "log.h"
#include "xstr.h"
char* expandCfgLine(char* cfgline)
{
cfgline = trimLine(cfgline);
cfgline = stripComment(cfgline);
cfgline = shell_expand(cfgline);
cfgline = vars_expand(cfgline);
return cfgline;
}
int FindTokenPos4Link(char **confName, char* ftoken, s_link *link, long* start, long*end)
{
char* cfgline, *line, *token, *linkConfName;
long linkstart=0;
*start=0; *end=0;
if (init_conf(*confName))
return 0;
while ((cfgline = configline()) != NULL) {
cfgline = expandCfgLine(cfgline);
line = cfgline;
token = strseparate(&line, " \t");
if (!token || strcasecmp(token, "link")) {
nfree(cfgline);
continue;
}
linkliner:
nfree(cfgline);
for (;;) {
if ((cfgline = configline()) == NULL) {
close_conf();
return 0;
}
cfgline = expandCfgLine(cfgline);
if (!*cfgline) {
nfree(cfgline);
continue;
}
line = cfgline;
token = strseparate(&line, " \t");
if (!token) {
nfree(cfgline);
continue;
}
if (stricmp(token, "link") == 0)
goto linkliner;
if (stricmp(token, "aka") == 0) break;
nfree(cfgline);
}
token = strseparate(&line, " \t");
if (!token || testAddr(token, link->hisAka) == 0) {
nfree(cfgline);
continue;
}
nfree(cfgline);
linkstart = get_hcfgPos();
linkConfName = sstrdup(getCurConfName());
for (;;) {
if ((cfgline = configline()) == NULL) {
*start = *end = linkstart;
*confName = linkConfName;
close_conf();
return 0;
}
cfgline = expandCfgLine(cfgline);
if (!*cfgline) {
nfree(cfgline);
continue;
}
line = cfgline;
token = strseparate(&line, " \t");
if (token && stricmp(token, "link") == 0)
{
*start = *end = linkstart;
*confName = linkConfName;
close_conf();
return 0;
}
if (token && stricmp(token, ftoken) == 0) break;
nfree(cfgline);
}
/* remove line */
nfree(cfgline);
*start = getCurConfPos();
*end = get_hcfgPos();
*confName = sstrdup(getCurConfName());
close_conf();
return 1;
}
return 0;
}
int InsertCfgLine(char *confName, char* cfgLine, long strbeg, long strend)
{
char *line = NULL, *newname = NULL, *p;
FILE *f_conf, *f_newconf;
long endpos,curpos,cfglen;
int openro = 0;
f_conf = f_newconf = NULL;
if ((strbeg == 0 && strend == 0) || confName == NULL)
return 0;
if ((f_conf = fopen(confName, "r+b")) == NULL) {
if ((f_conf = fopen(confName, "rb")) == NULL) {
w_log(LL_ERR, "Cannot open config file %s: %s\n", confName, strerror(errno));
return 0;
}
openro = 1;
}
fseek(f_conf, 0L, SEEK_END);
endpos = ftell(f_conf);
curpos = strend;
cfglen = endpos - curpos;
newname = (char *)smalloc(strlen(confName) + 5);
strcpy(newname, confName);
p=strrchr(newname, '.');
if (p==NULL || strchr(p, PATH_DELIM))
strcat(newname, ".tmp");
else
strcpy(p, ".tmp");
if ( (f_newconf = fopen(newname, "wb")) == NULL ) {
/* we have no write access to this directory? */
/* change config "in place" */
if (openro) {
w_log(LL_ERR, "Cannot open temp file %s: %s\n", newname, strerror(errno));
nfree(newname);
fclose(f_conf);
return 0;
}
nfree(newname);
line = (char*) smalloc((size_t) cfglen);
fseek(f_conf, curpos, SEEK_SET);
if (fread(line, sizeof(char), cfglen, f_conf) != (size_t)cfglen) {
w_log(LL_ERR, "Cannot read config file %s: %s\n", confName, strerror(errno));
nfree(line);
fclose(f_conf);
return 0;
}
fseek(f_conf, strbeg, SEEK_SET);
setfsize( fileno(f_conf), strbeg );
if (cfgLine) /* line not deleted */
{
if (fprintf(f_conf, "%s%s", cfgLine, cfgEol()) != (int)(strlen(cfgLine)+strlen(cfgEol())))
w_log(LL_ERR, "Cannot write config file %s: %s\n", confName, strerror(errno));
}
if (fwrite(line, sizeof(char), cfglen, f_conf) != (size_t)cfglen ||
fflush(f_conf) != 0)
{
w_log(LL_ERR, "Cannot write config file %s: %s\n", confName, strerror(errno));
}
fclose(f_conf);
nfree(line);
} else {
/* make new config-file and rename it */
#ifdef __UNIX__
struct stat st;
if (fstat(fileno(f_conf), &st) == 0)
fchmod(fileno(f_newconf), (st.st_mode & 01777) | 0400);
#endif
line = (char*) smalloc(cfglen > strbeg ? cfglen : strbeg);
fseek(f_conf, 0L, SEEK_SET);
if (fread(line, sizeof(char), strbeg, f_conf) < (size_t)strbeg) {
w_log(LL_ERR, "Cannot read config file %s: %s\n", confName, strerror(errno));
errwriteconf:
fclose(f_conf);
fclose(f_newconf);
unlink(newname);
nfree(line);
nfree(newname);
return 0;
}
if (fwrite(line, sizeof(char), strbeg, f_newconf) < (size_t)strbeg) {
w_log(LL_ERR, "Cannot write config file %s: %s\n", newname, strerror(errno));
goto errwriteconf;
}
if (cfgLine) {
if (fprintf(f_newconf, "%s%s", cfgLine, cfgEol()) != (int)(strlen(cfgLine)+strlen(cfgEol())))
{
w_log(LL_ERR, "Cannot write config file %s: %s\n", newname, strerror(errno));
goto errwriteconf;
}
}
fseek(f_conf, curpos, SEEK_SET);
if (fread(line, sizeof(char), cfglen, f_conf) != (size_t)cfglen) {
w_log(LL_ERR, "Cannot read config file %s: %s\n", confName, strerror(errno));
goto errwriteconf;
}
if (fwrite(line, sizeof(char), cfglen, f_newconf) != (size_t)cfglen ||
fflush(f_newconf) != 0) {
w_log(LL_ERR, "Cannot write config file %s: %s\n", newname, strerror(errno));
goto errwriteconf;
}
fclose(f_newconf);
fclose(f_conf);
nfree(line);
/* save old config as *.bak? */
/*
#ifndef __UNIX__
unlink(confName);
#endif
*/
/* if (rename(newname, confName)) { */
if (move_file(newname, confName,1)) {
w_log(LL_ERR, "Cannot rename config file %s->%s: %s\n", newname, confName, strerror(errno));
nfree(newname);
return 0;
}
nfree(newname);
}
return 1;
}
/* opt = 0 - AreaFix */
/* opt = 1 - AutoPause */
int Changepause(char *confName, s_link *link, int opt, int type)
{
long strbeg=0;
long strend=0;
FindTokenPos4Link(&confName, "pause", link, &strbeg, &strend);
link->Pause ^= type;
if (link->Pause == NOPAUSE) {
if(InsertCfgLine(confName, "Pause off", strbeg, strend))
w_log('8', "areafix: system %s set active", aka2str(link->hisAka));
} else if(link->Pause == (EPAUSE|FPAUSE)) {
if(InsertCfgLine(confName, "Pause on", strbeg, strend))
w_log('8', "%s: system %s set passive",
opt ? "autopause" : "areafix", aka2str(link->hisAka));
} else if(link->Pause == EPAUSE) {
if(InsertCfgLine(confName, "Pause Earea", strbeg, strend))
w_log('8', "%s: system %s set passive only for echos",
opt ? "autopause" : "areafix", aka2str(link->hisAka));
} else {
if(InsertCfgLine(confName, "Pause Farea", strbeg, strend))
w_log('8', "%s: system %s set passive only for file echos",
opt ? "autopause" : "areafix", aka2str(link->hisAka));
}
nfree(confName);
return 1;
}
int testAddr(char *addr, hs_addr hisAka)
{
hs_addr aka;
string2addr(addr, &aka);
if (addrComp(aka, hisAka)==0) return 1;
return 0;
}
int DelLinkFromString(char *line, hs_addr linkAddr)
{
int rc = 1;
char *end = NULL;
char *beg = NULL;
w_log(LL_FUNC, "::DelLinkFromString() begin");
beg = strrchr(line, '"'); /* seek end comment pointer (quote char) */
if(!beg) beg = line; /* if not found then seek from begin */
beg++; /* process next token */
while(*beg) /* while not end of string */
{
while(*beg && isspace(*beg)) beg++; /* skip spaces */
if(*beg && isdigit(*beg) && testAddr(beg, linkAddr))
{
rc = 0;
break;
}
while(*beg && !isspace(*beg)) beg++; /* skip token */
}
if(rc == 0) /* beg points to begin of unsubscribed address */
{
end = beg;
while(*beg && !isspace(*beg)) beg++; /* skip token */
while(*beg && !isdigit(*beg)) beg++; /* find for next link */
if(beg && *beg)
{
strcpy(end,beg);
}
else
{
end--;
*end = '\0';
}
}
w_log(LL_FUNC, "%::DelLinkFromString() end");
return rc;
}
int IsAreaAvailable(char *areaName, char *fileName, char **desc, int retd) {
FILE *f;
char *line, *token, *running;
if (fileName==NULL || areaName==NULL) return 0;
if ((f=fopen(fileName,"r")) == NULL) {
w_log('8',"Allfix: cannot open file \"%s\"",fileName);
return 0;
}
while ((line = readLine(f)) != NULL) {
line = trimLine(line);
if (line[0] != '\0') {
running = line;
token = strseparate(&running, " \t\r\n");
if (token && areaName && stricmp(token, areaName)==0) {
/* return description if needed */
if (retd) {
*desc = NULL;
if (running) {
/* strip "" at the beginning & end */
if (running[0]=='"' && running[strlen(running)-1]=='"') {
running++; running[strlen(running)-1]='\0';
}
/* change " -> ' */
token = running;
while (*token!='\0') {
if (*token=='"') *token='\'';
token++;
}
xstrcat(&(*desc), running);
}
}
nfree(line);
fclose(f);
return 1;
}
}
nfree(line);
}
/* not found */
fclose(f);
return 0;
}
void Addlink(s_link *link, s_area *earea, s_filearea *farea) {
s_arealink *arealink;
if(farea)
{
farea->downlinks = srealloc(farea->downlinks, sizeof(s_arealink*)*(farea->downlinkCount+1));
arealink = farea->downlinks[farea->downlinkCount] = (s_arealink*) scalloc(1, sizeof(s_arealink));
arealink->link = link;
if (link->numOptGrp > 0) {
/* default set export on, import on, mandatory off, manual off */
arealink->export = 1;
arealink->import = 1;
arealink->mandatory = 0;
arealink->manual = 0;
if (grpInArray(farea->group,link->optGrp,link->numOptGrp)) {
arealink->export = link->export;
arealink->import = link->import;
arealink->mandatory = link->mandatory;
arealink->manual = link->manual;
}
} else {
arealink->export = link->export;
arealink->import = link->import;
arealink->mandatory = link->mandatory;
arealink->manual = link->manual;
}
if (farea->mandatory) arealink->mandatory = 1;
if (farea->manual) arealink->manual = 1;
if (link->level < farea->levelread) arealink->export=0;
if (link->level < farea->levelwrite) arealink->import=0;
/* paused link can't receive mail */
if ((link->Pause & FPAUSE) == FPAUSE) arealink->export = 0;
farea->downlinkCount++;
}
if(earea)
{
earea->downlinks = srealloc(earea->downlinks, sizeof(s_arealink*)*(earea->downlinkCount+1));
arealink = earea->downlinks[earea->downlinkCount] = (s_arealink*) scalloc(1, sizeof(s_arealink));
arealink->link = link;
if (link->numOptGrp > 0) {
/* default set export on, import on, mandatory off, manual off */
arealink->export = 1;
arealink->import = 1;
arealink->mandatory = 0;
arealink->manual = 0;
if (grpInArray(earea->group,link->optGrp,link->numOptGrp)) {
arealink->export = link->export;
arealink->import = link->import;
arealink->mandatory = link->mandatory;
arealink->manual = link->manual;
}
} else {
arealink->export = link->export;
arealink->import = link->import;
arealink->mandatory = link->mandatory;
arealink->manual = link->manual;
}
if (earea->mandatory) arealink->mandatory = 1;
if (earea->manual) arealink->manual = 1;
if (link->level < earea->levelread) arealink->export=0;
if (link->level < earea->levelwrite) arealink->import=0;
/* paused link can't receive mail */
if ((link->Pause & EPAUSE) == EPAUSE) arealink->export = 0;
earea->downlinkCount++;
}
}
void RemoveLink(s_link *link, s_area *earea, s_filearea *farea) {
unsigned int i;
if(earea) /* remove link from echoarea */
{
if ( (i=isAreaLink(link->hisAka, earea)) != -1) {
nfree(earea->downlinks[i]);
earea->downlinks[i] = earea->downlinks[earea->downlinkCount-1];
earea->downlinkCount--;
}
}
if(farea) /* remove link from fileechoarea */
{
s_link *links;
for (i=0; i < farea->downlinkCount; i++) {
links = farea->downlinks[i]->link;
if (addrComp(link->hisAka, links->hisAka)==0) break;
}
nfree(farea->downlinks[i]);
farea->downlinks[i] = farea->downlinks[farea->downlinkCount-1];
farea->downlinkCount--;
}
}
syntax highlighted by Code2HTML, v. 0.9.1