Commit 92bcd45e authored by Rob Swindell's avatar Rob Swindell 💬
Browse files

Decompose some library files to enable reuse by SVDM (virtual DOS modem)

I just wanted to reuse findstr() in vdmodem.c and I fell down this hole :-)

findstr.* is new (findstr() related functions moved from str_util)
getctrl.* is now finally the real home of get_ctrl_dir(), moved from str_util
trashcan* functions moved from str_util to scfglib
other scfg_t dependent functions moved from str_util to scfglib

net_addr() appears to be a function that was never created/used (?)

This will definitely break the *nix build, for now.
parent 2283ec95
Pipeline #3074 failed with stage
in 8 minutes and 21 seconds
......@@ -153,6 +153,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="getctrl.c" />
<ClCompile Include="nopen.c">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
......
/* Synchronet find string routines */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program 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 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "genwrap.h"
#include "findstr.h"
/****************************************************************************/
/* Pattern matching string search of 'insearchof' in 'pattern'. */
/* pattern matching is case-insensitive */
/* patterns beginning with ';' are comments (never match) */
/* patterns beginning with '!' are reverse-matched (returns FALSE if match) */
/* patterns ending in '~' will match string anywhere (sub-string search) */
/* patterns ending in '^' will match left string fragment only */
/* patterns including '*' must match both left and right string fragments */
/* all other patterns are exact-match checking */
/****************************************************************************/
BOOL findstr_in_string(const char* search, const char* pattern)
{
char buf[256];
char* p;
char* last;
const char* splat;
size_t len;
BOOL found = FALSE;
if(pattern == NULL || search == NULL)
return FALSE;
SAFECOPY(buf, pattern);
p = buf;
if(*p == ';') /* comment */
return FALSE;
if(*p == '!') { /* reverse-match */
found = TRUE;
p++;
}
truncsp(p);
len = strlen(p);
if(len > 0) {
last = p + len - 1;
if(*last == '~') {
*last = '\0';
if(strcasestr(search, p) != NULL)
found = !found;
}
else if(*last == '^') {
if(strnicmp(p, search, len - 1) == 0)
found = !found;
}
else if((splat = strchr(p, '*')) != NULL) {
int left = splat - p;
int right = len - (left + 1);
int slen = strlen(search);
if(slen < left + right)
return found;
if(strnicmp(search, p, left) == 0
&& strnicmp(p + left + 1, search + (slen - right), right) == 0)
found = !found;
}
else if(stricmp(p, search) == 0)
found = !found;
}
return found;
}
static uint32_t encode_ipv4_address(unsigned int byte[])
{
if(byte[0] > 0xff || byte[1] > 0xff || byte[2] > 0xff || byte[3] > 0xff)
return 0;
return (byte[0]<<24) | (byte[1]<<16) | (byte[2]<<8) | byte[3];
}
static uint32_t parse_ipv4_address(const char* str)
{
unsigned int byte[4];
if(sscanf(str, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]) != 4)
return 0;
return encode_ipv4_address(byte);
}
static uint32_t parse_cidr(const char* p, unsigned* subnet)
{
unsigned int byte[4];
if(*p == '!')
p++;
*subnet = 0;
if(sscanf(p, "%u.%u.%u.%u/%u", &byte[0], &byte[1], &byte[2], &byte[3], subnet) != 5 || *subnet > 32)
return 0;
return encode_ipv4_address(byte);
}
static BOOL is_cidr_match(const char *p, uint32_t ip_addr, uint32_t cidr, unsigned subnet)
{
BOOL match = FALSE;
if(*p == '!')
match = TRUE;
if(((ip_addr ^ cidr) >> (32-subnet)) == 0)
match = !match;
return match;
}
/****************************************************************************/
/* Pattern matching string search of 'insearchof' in 'list'. */
/****************************************************************************/
BOOL findstr_in_list(const char* insearchof, str_list_t list)
{
size_t index;
BOOL found=FALSE;
char* p;
uint32_t ip_addr, cidr;
unsigned subnet;
if(list==NULL || insearchof==NULL)
return FALSE;
ip_addr = parse_ipv4_address(insearchof);
for(index=0; list[index]!=NULL; index++) {
p=list[index];
// SKIP_WHITESPACE(p);
if(ip_addr != 0 && (cidr = parse_cidr(p, &subnet)) != 0)
found = is_cidr_match(p, ip_addr, cidr, subnet);
else
found = findstr_in_string(insearchof,p);
if(found != (*p=='!'))
break;
}
return found;
}
/****************************************************************************/
/* Pattern matching string search of 'insearchof' in 'fname'. */
/****************************************************************************/
BOOL findstr(const char* insearchof, const char* fname)
{
char str[256];
BOOL found=FALSE;
FILE* fp;
uint32_t ip_addr, cidr;
unsigned subnet;
if(insearchof==NULL || fname==NULL || *fname == '\0')
return FALSE;
if((fp=fopen(fname,"r"))==NULL)
return FALSE;
ip_addr = parse_ipv4_address(insearchof);
while(!feof(fp) && !ferror(fp) && !found) {
if(!fgets(str,sizeof(str),fp))
break;
char* p = str;
SKIP_WHITESPACE(p);
c_unescape_str(p);
if(ip_addr !=0 && (cidr = parse_cidr(p, &subnet)) != 0)
found = is_cidr_match(p, ip_addr, cidr, subnet);
else
found = findstr_in_string(insearchof, p);
}
fclose(fp);
return found;
}
static char* process_findstr_item(size_t index, char *str, void* cbdata)
{
SKIP_WHITESPACE(str);
return c_unescape_str(str);
}
/****************************************************************************/
str_list_t findstr_list(const char* fname)
{
FILE* fp;
str_list_t list;
if((fp=fopen(fname,"r"))==NULL)
return NULL;
list=strListReadFile(fp, NULL, /* Max line length: */255);
strListModifyEach(list, process_findstr_item, /* cbdata: */NULL);
fclose(fp);
return list;
}
/* Synchronet find string functions */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program 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 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#ifndef _FINDSTR_H_
#define _FINDSTR_H_
#include "str_list.h"
#include "dllexport.h"
#ifdef __cplusplus
extern "C" {
#endif
DLLEXPORT BOOL findstr(const char *insearch, const char *fname);
DLLEXPORT BOOL findstr_in_string(const char* insearchof, const char* pattern);
DLLEXPORT BOOL findstr_in_list(const char* insearchof, str_list_t list);
DLLEXPORT str_list_t findstr_list(const char* fname);
#ifdef __cplusplus
}
#endif
#endif /* Don't add anything after this line */
#include <gen_defs.h>
#include <dirwrap.h>
/* Synchronet get "control" directory function */
char *get_ctrl_dir(char *path, size_t pathsz)
{
#ifdef PREFIX
char ini_file[MAX_PATH];
#endif
char *p;
p=getenv("SBBSCTRL");
if(p!=NULL) {
strncpy(path, p, pathsz);
if(pathsz > 0)
path[pathsz-1]=0;
return path;
}
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program 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 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#ifdef PREFIX
strncpy(path, PREFIX"/etc", pathsz);
if(pathsz > 0)
path[pathsz-1]=0;
iniFileName(ini_file, sizeof(ini_file)-1, PREFIX"/etc", "sbbs.ini");
if(fexistcase(ini_file)) {
FILE* fini;
char* str;
#include <stdio.h>
#include "getctrl.h"
#include "sbbsdefs.h"
fini=iniOpenFile(ini_file, FALSE);
if(fini==NULL)
return NULL;
str = iniReadExistingString(fini, "Global", "CtrlDirectory", NULL, ini_file);
iniCloseFile(fini);
return str;
const char* get_ctrl_dir(BOOL warn)
{
char* p = getenv("SBBSCTRL");
if(p == NULL || *p == '\0') {
if(warn)
fprintf(stderr, "!SBBSCTRL environment variable not set, using default value: " SBBSCTRL_DEFAULT "\n\n");
p = SBBSCTRL_DEFAULT;
}
#endif
return NULL;
return p;
}
#ifndef GETCTRL_H
#define GETCTRL_H
/* Synchronet get "control" directory function */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program 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 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#ifndef GETCTRL_H_
#define GETCTRL_H_
#include "gen_defs.h"
#if defined(__cplusplus)
extern "C"
extern "C"
#endif
char *get_ctrl_dir(char *path, size_t pathsz)
const char* get_ctrl_dir(BOOL warn);
#endif
......@@ -157,6 +157,7 @@
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="getctrl.c" />
<ClCompile Include="jsdebug.c" />
<ClCompile Include="js_conio.c">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
......
......@@ -101,6 +101,8 @@
<ItemGroup>
<ClCompile Include="..\encode\utf8.c" />
<ClCompile Include="ars.c" />
<ClCompile Include="findstr.c" />
<ClCompile Include="getctrl.c" />
<ClCompile Include="load_cfg.c" />
<ClCompile Include="nopen.c" />
<ClCompile Include="readtext.c" />
......
......@@ -148,6 +148,7 @@
</Bscmake>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="getctrl.c" />
<ClCompile Include="ntsvcs.c">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
......
......@@ -289,6 +289,7 @@ extern int thread_suid_broken; /* NPTL is no longer broken */
#include "nopen.h"
#include "text.h"
#include "str_util.h"
#include "findstr.h"
#include "date_str.h"
#include "load_cfg.h"
#include "getstats.h"
......
......@@ -328,6 +328,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="findstr.c" />
<ClCompile Include="getkey.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
......
......@@ -147,6 +147,7 @@
</Bscmake>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="getctrl.c" />
<ClCompile Include="sbbs_ini.c">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
......
......@@ -46,6 +46,7 @@
#include "link_list.h"
#include "str_list.h"
#include "str_util.h"
#include "findstr.h"
#include "datewrap.h"
#include "nopen.h"
#include "crc32.h"
......
......@@ -72,6 +72,14 @@ DLLEXPORT BOOL is_valid_libnum(scfg_t*, int);
DLLEXPORT BOOL is_valid_subnum(scfg_t*, int);
DLLEXPORT BOOL is_valid_grpnum(scfg_t*, int);
DLLEXPORT BOOL trashcan(scfg_t* cfg, const char *insearch, const char *name);
DLLEXPORT char * trashcan_fname(scfg_t* cfg, const char *name, char* fname, size_t);
DLLEXPORT str_list_t trashcan_list(scfg_t* cfg, const char* name);
DLLEXPORT char * sub_newsgroup_name(scfg_t*, sub_t*, char*, size_t);
DLLEXPORT char * sub_area_tag(scfg_t*, sub_t*, char*, size_t);
DLLEXPORT char * dir_area_tag(scfg_t*, dir_t*, char*, size_t);
faddr_t* nearest_sysfaddr(scfg_t*, faddr_t*);
#ifdef __cplusplus
......
......@@ -23,6 +23,7 @@
#include "load_cfg.h"
#include "nopen.h"
#include "ars_defs.h"
#include "findstr.h"
BOOL allocerr(FILE* fp, char* error, size_t maxerrlen, long offset, const char *fname, size_t size)
{
......@@ -874,3 +875,96 @@ faddr_t* nearest_sysfaddr(scfg_t* cfg, faddr_t* addr)
return &cfg->faddr[i];
return &cfg->faddr[0];
}
/****************************************************************************/
/* Searches the file <name>.can in the TEXT directory for matches */
/* Returns TRUE if found in list, FALSE if not. */
/****************************************************************************/
BOOL trashcan(scfg_t* cfg, const char* insearchof, const char* name)
{
char fname[MAX_PATH+1];
return(findstr(insearchof,trashcan_fname(cfg,name,fname,sizeof(fname))));
}
/****************************************************************************/
char* trashcan_fname(scfg_t* cfg, const char* name, char* fname, size_t maxlen)
{
safe_snprintf(fname,maxlen,"%s%s.can",cfg->text_dir,name);
return fname;
}
/****************************************************************************/
str_list_t trashcan_list(scfg_t* cfg, const char* name)
{
char fname[MAX_PATH+1];
return findstr_list(trashcan_fname(cfg, name, fname, sizeof(fname)));
}
char* sub_newsgroup_name(scfg_t* cfg, sub_t* sub, char* str, size_t size)
{
memset(str, 0, size);
if(sub->newsgroup[0])
strncpy(str, sub->newsgroup, size - 1);
else {
snprintf(str, size - 1, "%s.%s", cfg->grp[sub->grp]->sname, sub->sname);
/*
* From RFC5536:
* newsgroup-name = component *( "." component )
* component = 1*component-char
* component-char = ALPHA / DIGIT / "+" / "-" / "_"
*/
if (str[0] == '.')
str[0] = '_';
size_t c;
for(c = 0; str[c] != 0; c++) {
/* Legal characters */
if ((str[c] >= 'A' && str[c] <= 'Z')
|| (str[c] >= 'a' && str[c] <= 'z')
|| (str[c] >= '0' && str[c] <= '9')
|| str[c] == '+'
|| str[c] == '-'
|| str[c] == '_'
|| str[c] == '.')
continue;
str[c] = '_';
}
c--;
if (str[c] == '.')
str[c] = '_';
}
return str;
}
char* sub_area_tag(scfg_t* cfg, sub_t* sub, char* str, size_t size)
{
char* p;
memset(str, 0, size);
if(sub->area_tag[0])
strncpy(str, sub->area_tag, size - 1);
else if(sub->newsgroup[0])
strncpy(str, sub->newsgroup, size - 1);
else {
strncpy(str, sub->sname, size - 1);
REPLACE_CHARS(str, ' ', '_', p);
}
strupr(str);
return str;
}
char* dir_area_tag(scfg_t* cfg, dir_t* dir, char* str, size_t size)
{
char* p;
memset(str, 0, size);
if(dir->area_tag[0])
strncpy(str, dir->area_tag, size - 1);
else {
strncpy(str, dir->sname, size - 1);
REPLACE_CHARS(str, ' ', '_', p);
}
strupr(str);
return str;
}
......@@ -19,6 +19,8 @@
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "genwrap.h"
#include "dirwrap.h"
#include "str_util.h"
#include "utf8.h"
#include "unicode.h"
......@@ -257,223 +259,6 @@ char* strip_char(const char* str, char* dest, char ch)
return retval;
}
/****************************************************************************/
/* Pattern matching string search of 'insearchof' in 'pattern'. */
/* pattern matching is case-insensitive */
/* patterns beginning with ';' are comments (never match) */
/* patterns beginning with '!' are reverse-matched (returns FALSE if match) */
/* patterns ending in '~' will match string anywhere (sub-string search) */
/* patterns ending in '^' will match left string fragment only */
/* patterns including '*' must match both left and right string fragments */
/* all other patterns are exact-match checking */
/****************************************************************************/
BOOL findstr_in_string(const char* search, const char* pattern)
{
char buf[256];
char* p;
char* last;
const char* splat;
size_t len;
BOOL found = FALSE;
if(pattern == NULL || search == NULL)
return FALSE;
SAFECOPY(buf, pattern);
p = buf;
if(*p == ';') /* comment */
return FALSE;
if(*p == '!') { /* reverse-match */
found = TRUE;
p++;
}
truncsp(p);
len = strlen(p);
if(len > 0) {
last = p + len - 1;
if(*last == '~') {
*last = '\0';
if(strcasestr(search, p) != NULL)
found = !found;
}
else if(*last == '^') {