Converted from CVS

This commit is contained in:
Mercurial Repos
2009-05-15 22:01:56 +02:00
commit b7b0017dd9
900 changed files with 203942 additions and 0 deletions

1
lib/.cvsignore Normal file
View File

@@ -0,0 +1 @@
filelist ftscprod.c

294
lib/Diesel.doc Normal file
View File

@@ -0,0 +1,294 @@
T U R B O D I E S E L
Template-based Uncomplicated Report-Building Oriented Dumb
Interpretively Evaluated String Expression Language
This is a modified version of diesel language. Diesel is a interpreted
macro language, used in AutoCAD and released to public domain by AutoDesk.
Modified version by Redy Rodriguez, for use in mbsebbs. Original diesel
language can be found at http://www.fourmilab.ch/diesel.
This "Dumb Interpretively Executed String Expression Language" is the
kernel of a macro language you can customise by adding C code and
embedding it into your program.
It is short, written in portable C, and is readily integrated into any
program. It is useful primarily to programs which need a very rudimentary
macro expansion facility without the complexity of a full language such as
Lisp or FORTH.
DIESEL copies its input directly to the output until a macro character,
"@" or quoted string is encountered. Quoted strings may be used to
suppress evaluation of sequences of characters which would otherwise be
interpreted as macros. Quote marks may be included in quoted strings by
two adjacent quote marks. For example:
"@(if,1,True,False)="""@(if,1,True,False)""""
Status retrieval, computation, and display are performed by DIESEL
functions. The available functions are as follows. User-defined
functions are not implemented; what you see is all you've got. Naturally,
if you embed DIESEL in your application, you'll add functions that provide
access to information and actions within your own program. DIESEL's
arithmetic functions accept either floating point or integer arguments,
and perform all calculations in floating point.
TURBODIESEL facilities
----------------------
If a line begin with # then will be not evaluated, and any output is done.
If a line begin with @! any output is done, but evaluation is performed.
If a line begin with @{<expresion>} produces output only if expression is
TRUE (Any non-zero numeric value).
To easily format output, you can use one-char variable names as follow:
@A will be replaced by result of evaluate @(GETVAR,A).
@A_____ will be replaced by result of evaluate @(GETVAR,A) truncated or
padded with spaces to complete same lenght of '@A_____' (7 in that case).
You can use > or < to especify alignement rigth or left:
@A_____> @A_____<
TURBODIESEL String Functions
----------------------------
@(+,<val1>,<val2>,...<valn>)
The sum of the numbers <val1>, <val2>, ...<valn> is returned.
@(-,<val1>,<val2>,...<valn>)
The result of subtracting the numbers <val2> through <valn> from
<val1> is returned.
@(*,<val1>,<val2>,...<valn>)
The result of multiplying the numbers <val1>,<val2>,...<valn> is
returned.
@(/,<val1>,<val2>,...<valn>)
The result of dividing the number <val1> by <val2>,... <valn> is
returned.
@(=,<val1>,<val2>)
If the numbers <val1> and <val2> are equal 1 is returned,
otherwise 0 is returned.
@(<,<val1>,<val2>)
If the number <val1> is less than <val2> 1 is returned, otherwise
0 is returned.
@(>,<val1>,<val2>)
If the number <val1> is greater than <val2> 1 is returned,
otherwise 0 is returned.
@(!=,<val1>,<val2>)
If the numbers <val1> and <val2> are not equal 1 is returned,
otherwise 0 is returned.
@(<=,<val1>,<val2>)
If the number <val1> is less than or equal to <val2> 1 is
returned, otherwise 0 is returned.
@(>=,<val1>,<val2>)
If the number <val1> is greater than or equal to <val2> 1 is
returned, otherwise 0 is returned.
@(AND,<val1>,<val2>,...<valn>)
The bitwise logical AND of the integers <val1> through <valn> is
returned.
@(EQ,<val1>,<val2>)
If the strings <val1> and <val2> are identical 1 is returned,
otherwise 0.
@(EVAL,<str>)
The string <str> is passed to the DIESEL evaluator and the result
of evaluating it is returned.
@(FIX,<value>)
The real number <value> is truncated to an integer by discarding
any fractional part.
@(IF,<expr>,<dotrue>,<dofalse>)
If <expr> is nonzero, <dotrue> is evaluated and returned.
Otherwise, <dofalse> is evaluated and returned. Note that the
branch not chosen by <expr> is not evaluated.
@(INDEX,<which>,<string>)
<string> is assumed to contain one or more values delimited by the
macro argument separator character, comma. <which> selects one of
these values to be extracted, with the first item numbered zero.
* @(LOWER,<string>)
The <string> is returned converted to lower case according to the
rules of the current locale.
@(NTH,<which>,<arg0>,<arg1>,<argN>)
Evaluates and returns the argument selected by <which>. If
<which> is 0, <arg0> is returned, and so on. Note the difference
between @(NTH) and @(INDEX); @(NTH) returns one of a series of
arguments to the function while @(INDEX) extracts a value from a
comma-delimited string passed as a single argument. Arguments not
selected by <which> are not evaluated.
@(OR,<val1>,<val2>,...<valn>)
The bitwise logical OR of the integers <val1> through <valn> is
returned.
* @(STRCMP,<str1>,<str2>)
Compare strings and returns -1 if <str1> is less than <Str2>, 0 if
both are equals, or 1 if <str1> is greater than <str2> .
@(STRFILL,<string>,<ncopies>)
Returns the result of concatenating <ncopies> of <string>.
@(STRLEN,<string>)
Returns the length of <string> in characters.
* @(STRSTR,<str1>,<str2>)
Find first apparition of <str2> in <str1>, and return the position
or 0 if not found.
@(SUBSTR,<string>,<start>,<length>)
Returns the substring of <string> starting at character <start>
and extending for <length> characters. Characters in the string
are numbered from 1. If <length> is omitted, the entire remaining
length of the string is returned.
@(UPPER,<string>)
The <string> is returned converted to upper case according to the
rules of the current locale.
@(XOR,<val1>,<val2>,...<valn>)
The bitwise logical XOR of the integers <val1> through <valn> is
returned.
Variable Extensions
-------------------
The base-line DIESEL includes no user-defined variables. This allows
DIESEL to avoid allocating any local memory and renders it totally
reentrant. If you compile DIESEL with the tag VARIABLES defined, the
following additional functions are included which provide variable
definition and access. Note that these functions call malloc() and
strdup() and thus consume heap storage.
Variable names are case sensitive.
If you want easily format output you must use one-char variable names
then you can format output as @V_____, @X_____< or @k___>. See above.
@(GETVAR,varname)
Returns the value stored in <varname>. If no variable with
the name <varname> exists, a bad argument error is reported.
@(SETVAR,varname,value)
Stores the string <value> into <varname>. If no variable
called <varname> exists, a new variable is created.
* @(CLEAR)
Clear all variables.
Unix Extensions
---------------
If you compile DIESEL with the tag UNIXTENSIONS defined, the following
additional functions will be available:
@(GETENV,varname)
Returns the variable <varname> from the environment. If no such
variable is defined, returns the null string.
@(TIME)
Returns the current time in Unix fashion, as the number of seconds
elapsed since 00:00:00 GMT January 1, 1970.
@(EDTIME,<time>,<picture>)
Edit the Unix time <time> to format <picture>. If <time> is 0,
the current date and time is edited (this is just shorthand for
the equivalent "@(EDTIME,@(TIME),<picture>)".).
Assume the date is: Thursday, 2 September 1993 4:53:17
Format phrases:
D 2
DD 02
DDD Thu
DDDD Thursday
M 9
MO 09
MON Sep
MONTH September
YY 93
YYYY 1993
H 4
HH 04
MM 53
SS 17
AM/PM AM
am/pm am
A/P A
a/p a
If any of the "AM/PM" phrases appear in the picture, the "H" and
"HH" phrases will edit the time according to the 12 hour civil
clock (12:00-12:59-1:00-11:59) instead of the 24 hour clock
(00:00-23:59).
TURBODIESEL Mechanics
---------------------
Generally, if you mess something up in a DIESEL expression it's pretty
obvious what went wrong. DIESEL embeds an error indication in the
output stream depending on the nature of the error:
@? Syntax error (usually a missing right parenthesis
or runaway string).
@(<func>,??) Incorrect arguments to <func>.
@(<func>)?? Unknown function <func>.
@++ Output string too long--evaluation truncated.
Using TURBODIESEL
-----------------
You invoke TURBODIESEL within your program by calling:
int status;
char instring[<whatever>], outstring[MAXSTR + 1];
outstring = ParseMacro(instring, &status);
The output from the evaluation will be stored in outstring when
control is returned to your program. If no errors were detected
during evaluation, status will be zero. Otherwise status gives the
character position within instring at which the error was detected.
If an error occurs, TURBODIESEL will include an error diagnostic,
documented above, in outstring.
To set single-char variables you can use:
MacroVars(<string-names>,<string-types>,<value1>,...,<valueN>);
string-names -> Variable names
string-types -> Variable types
(s: string, c: char, d: integer, f: float).
Both strings must be same lenght, and the number of values must
match with lenght and types.
Sample:
MacroVars("ABCDE","sscdf","A String","Another String",'C',5,4.67);
To clear all variables you can use:
MacroClear();

181
lib/Makefile Normal file
View File

@@ -0,0 +1,181 @@
# Makefile for the library files.
# Copyright (c) 1997, 2001 by M. Broek.
# $Id: Makefile,v 1.53 2008/02/17 16:10:18 mbse Exp $
include ../Makefile.global
COMMON_SRCS = clcomm.c client.c crc.c semafore.c signame.c charset.c remask.c \
attach.c falists.c hdr.c parsedate.c rfcmsg.c unpacker.c rearc.c \
batchrd.c ftn.c pktname.c mangle.c sectest.c proglock.c magic.c \
dostran.c ftnmsg.c mbfile.c nodelock.c rawio.c strcasestr.c \
execute.c expipe.c getheader.c noderecord.c rfcaddr.c strutil.c \
faddr.c gmtoffset.c packet.c rfcdate.c term.c endian.c timers.c \
pidinfo.c tmpwork.c virscan.c
COMMON_OBJS = clcomm.o client.o crc.o semafore.o signame.o charset.o remask.o \
ftscprod.o attach.o falists.o hdr.o parsedate.o rfcmsg.o unpacker.o \
batchrd.o ftn.o pktname.o mangle.o sectest.o proglock.o rearc.o \
dostran.o ftnmsg.o mbfile.o nodelock.o rawio.o strcasestr.o magic.o \
execute.o expipe.o getheader.o noderecord.o rfcaddr.o strutil.o \
faddr.o gmtoffset.o packet.o rfcdate.o term.o endian.o timers.o \
pidinfo.o tmpwork.o virscan.o
COMMON_HDRS = mbselib.h
NODELIST_SRCS = nodelist.c
NODELIST_OBJS = nodelist.o
NODELIST_HDRS = nodelist.h
DBASE_SRCS = dbcfg.c dbdupe.c dbftn.c dbmsgs.c dbnode.c dbtic.c dbuser.c dbfdb.c
DBASE_OBJS = dbcfg.o dbdupe.o dbftn.o dbmsgs.o dbnode.o dbtic.o dbuser.o dbfdb.o
DBASE_HDRS = mbsedb.h
MSGBASE_SRCS = jammsg.c msg.c msgtext.c
MSGBASE_OBJS = jammsg.o msg.o msgtext.o
MSGBASE_HDRS = jam.h jammsg.h jamsys.h msg.h msgtext.h
MBINET_SRCS = nntp.c pop3.c smtp.c
MBINET_OBJS = nntp.o pop3.o smtp.o
MBINET_HDRS = mbinet.h
DIESEL_SRCS = diesel.c mbdiesel.c strcasestr.c
DIESEL_HDRS = diesel.h
DIESEL_OBJS = diesel.o mbdiesel.o strcasestr.o
OTHER_HDRS = bluewave.h mbse.h users.h
SRCS = ${COMMON_SRCS} ${DBASE_SRCS} ${MSGBASE_SRCS} ${MBINET_SRCS} \
${DIESEL_SRCS} ${NODELIST_SRCS} ${CHC_SRCS}
OBJS = ${COMMON_OBJS} ${DBASE_OBJS} ${MSGBASE_OBJS} ${MBINET_OBJS} \
${DIESEL_OBJS} ${NODELIST_OBJS} ${CHC_OBJS}
HDRS = ${COMMON_HDRS} ${DBASE_HDRS} ${MSGBASE_HDRS} ${MBINET_HDRS} \
${DIESEL_HDRS} ${NODELIST_HDRS} ${CHC_HDRS} ${OTHER_HDRS}
OTHER = Makefile README ftscprod.010 mkprod.awk \
README.diesel README.macro Diesel.doc nodelist.conf
TARGET = libmbse.a libdbase.a libmsgbase.a libmbinet.a libdiesel.a \
libnodelist.a
SLIBS = ../lib/libmbse.a
#############################################################################
.c.o:
${CC} ${CFLAGS} ${INCLUDES} ${DEFINES} -c $<
all: ${TARGET}
ftscprod.c: ftscprod.??? mkprod.awk
${AWK} -F, -f mkprod.awk ftscprod.??? >ftscprod.c
libmbse.a: ${COMMON_OBJS}
ar r $@ $?
${RANLIB} $@
libdbase.a: ${DBASE_OBJS}
ar r $@ $?
${RANLIB} $@
libmsgbase.a: ${MSGBASE_OBJS}
ar r $@ $?
${RANLIB} $@
libmbinet.a: ${MBINET_OBJS}
ar r $@ $?
${RANLIB} $@
libdiesel.a: ${DIESEL_OBJS}
ar r $@ $?
${RANLIB} $@
libnodelist.a: ${NODELIST_OBJS}
ar r $@ $?
${RANLIB} $@
install: all
${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0444 nodelist.conf ${ETCDIR}
clean:
rm -f ${TARGET} *.o *.h~ *.c~ ftscprod.c core filelist Makefile.bak
filelist: Makefile
BASE=`pwd`; \
BASE=`basename $${BASE}`; \
(for f in ${SRCS} ${HDRS} ${OTHER} ${MAPS} ;do echo ${PACKAGE}-${VERSION}/$${BASE}/$$f; done) >filelist
depend: ftscprod.c
@rm -f Makefile.bak; \
mv Makefile Makefile.bak; \
sed -e '/^# DO NOT DELETE/,$$d' Makefile.bak >Makefile; \
${ECHO} '# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT' >>Makefile; \
${ECHO} '# Dependencies generated by make depend' >>Makefile; \
for f in ${SRCS} ftscprod.c; \
do \
${ECHO} "Dependencies for $$f:\c"; \
${ECHO} "`basename $$f .c`.o:\c" >>Makefile; \
for h in `sed -n -e \
's/^#[ ]*include[ ]*"\([^"]*\)".*/\1/p' $$f`; \
do \
${ECHO} " $$h\c"; \
${ECHO} " $$h\c" >>Makefile; \
done; \
${ECHO} " done."; \
${ECHO} "" >>Makefile; \
done; \
${ECHO} '# End of generated dependencies' >>Makefile
# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
# Dependencies generated by make depend
clcomm.o: ../config.h mbselib.h
client.o: ../config.h mbselib.h
crc.o: ../config.h mbselib.h
semafore.o: ../config.h mbselib.h
signame.o: ../config.h mbselib.h
charset.o: ../config.h mbselib.h
remask.o: ../config.h mbselib.h
attach.o: ../config.h mbselib.h
falists.o: ../config.h mbselib.h
hdr.o: ../config.h mbselib.h
parsedate.o: ../config.h mbselib.h
rfcmsg.o: ../config.h mbselib.h
unpacker.o: ../config.h mbselib.h
rearc.o: ../config.h mbselib.h
batchrd.o: ../config.h mbselib.h
ftn.o: ../config.h mbselib.h users.h mbsedb.h
pktname.o: ../config.h mbselib.h users.h mbsedb.h
mangle.o: ../config.h mbselib.h
sectest.o: ../config.h mbselib.h
proglock.o: ../config.h mbselib.h
magic.o: ../config.h mbselib.h
dostran.o: ../config.h mbselib.h
ftnmsg.o: ../config.h mbselib.h
mbfile.o: ../config.h mbselib.h
nodelock.o: ../config.h mbselib.h
rawio.o: ../config.h mbselib.h
strcasestr.o: ../config.h mbselib.h
execute.o: ../config.h mbselib.h
expipe.o: ../config.h mbselib.h
getheader.o: ../config.h mbselib.h
noderecord.o: ../config.h mbselib.h users.h mbsedb.h
rfcaddr.o: ../config.h mbselib.h
strutil.o: ../config.h mbselib.h
faddr.o: ../config.h mbselib.h
gmtoffset.o: ../config.h mbselib.h
packet.o: ../config.h mbselib.h users.h mbsedb.h
rfcdate.o: ../config.h mbselib.h
term.o: ../config.h mbselib.h users.h
endian.o: ../config.h mbselib.h
timers.o: ../config.h mbselib.h
pidinfo.o: ../config.h mbselib.h
tmpwork.o: ../config.h mbselib.h
virscan.o: ../config.h mbselib.h
dbcfg.o: ../config.h mbselib.h mbse.h users.h mbsedb.h
dbdupe.o: ../config.h mbselib.h mbse.h users.h mbsedb.h
dbftn.o: ../config.h mbselib.h users.h mbsedb.h
dbmsgs.o: ../config.h mbselib.h users.h mbsedb.h
dbnode.o: ../config.h mbselib.h users.h mbsedb.h
dbtic.o: ../config.h mbselib.h users.h mbsedb.h
dbuser.o: ../config.h mbselib.h users.h mbsedb.h
dbfdb.o: ../config.h mbselib.h users.h mbsedb.h
jammsg.o: ../config.h mbselib.h msgtext.h msg.h jam.h jammsg.h users.h
msg.o: ../config.h mbselib.h msgtext.h msg.h jammsg.h
msgtext.o: ../config.h mbselib.h msgtext.h msg.h
nntp.o: ../config.h mbselib.h mbinet.h
pop3.o: ../config.h mbselib.h mbinet.h
smtp.o: ../config.h mbselib.h mbinet.h
diesel.o: ../config.h mbselib.h diesel.h
mbdiesel.o: ../config.h mbselib.h diesel.h
strcasestr.o: ../config.h mbselib.h
nodelist.o: ../config.h mbselib.h nodelist.h
ftscprod.o: ../config.h mbselib.h
# End of generated dependencies

35
lib/README Normal file
View File

@@ -0,0 +1,35 @@
Database structures.
Most databases have a structure with a header record. The header record
is at the beginning of the datafile and contains information about the
size of the header record and size of the database records. When a data
file is opened for reading the first thing to read the header record.
The field recsize contains the size of the datarecords and the field
hdrsize the offset to the first datarecord in the file.
If in the structure the size of the datarecords changes (grows), we can
allways read the old format in the correct way.
When a datafile is changed the datafile has to be rewritten completly.
Of course the new format is used then, and the new size must be stored in
the header.
The advantage of this technique is that updates can be performed automatic.
There is no need for free space for future use in the datarecords, the files
are thus smaller.
One other important thing, with some DOS based bbs'es, mail/tic processors
are using index files together with the data files to speed up the search in
the databases. Also some of them use internal memory cache for the data records.
I choose not to do this for two reasons, Linux like other Unices handles
file I/O very fast and when your system is not low on memory the kernel will
buffer all disk I/O in memory. Also Linux disks are very low fragmented due to
the design of the ext2fs. Whith all this in mind, using index files is only
extra overhead.
However, because of this you should not put the data files on a msdos
dos partition or on a nfs server.
The only exeption that uses index files are the nodelists.

20
lib/README.diesel Normal file
View File

@@ -0,0 +1,20 @@
If you want compile a standalone diesel executable interpreter, you can
do it writing at linux prompt:
# cc -DTESTPROG -g diesel.c -o diesel
Then you can interpret a diesel script and see output calling...
# diesel <script
or...
# cat script |diesel
If you want set some vars before interpret script you can do...
# echo '@! @(setvar,a,5) @(setvar,B,HELLO)'| cat - script |diesel
Or you can put all @(setvar...) sentences in a separated file an call...
# cat setvar.file script |diesel

52
lib/README.macro Normal file
View File

@@ -0,0 +1,52 @@
Using turbodiesel macro files in mbse. Now you can personalize response
reports from areamgr, filemgr an notify using diesel macro files.
See diesel.doc for turbodiesel syntax.
Mbfido look for macro files first in macro language phat acording defined
language in nodes setup, and then in $MBSEROT/etc/. If no macro file found
mbfido uses harcoded respose.
(Michiel check that, I prefer not change CFG struct. If you add a default
macro path, you must change function OpenMacro in mgrutil.c at line 495)
Macro files used are:
areamgr.flow -> %FLOW
areamgr.group -> group report (included in areamgr.list)
areamgr.help -> %HELP
areamgr.list -> %LIST
areamgr.notify.flow -> Flow report sent by 'mbfido notify'
areamgr.notify.list -> Area status report sent by 'mbfido notify'
areamgr.query -> %QUERY
areamgr.responses -> Multiple responses for results of areamgr.
areamgr.status -> %STATUS
areamgr.unlink -> %UNLINK
filemgr.group -> group report (included in filemgr.list)
filemgr.help -> %HELP
filemgr.list -> %LIST
filemgr.notify.list -> Area status report sent by 'mbfido notify'
filemgr.query -> %QUERY
filemgr.responses -> Multiple responses for results of filemgr.
filemgr.status -> %STATUS
filemgr.unlink -> %UNLINK
Some files are very similar, and can be a symbolic link to other including a
few conditional macros.
See coments in sample files to undestand how work.
Overview
--------
For every macro file multiple values are passed in diesel variables,
see samples to know what variables can be used for each file.
If you assign a value to 'subject' variable in a macro file, then the
message subject will be that value.
Some files have multiple sections. Sections delimiter is @| at begin of line,
you can put a comentary after @| delimiter (see areamgr.list sample).

244
lib/attach.c Normal file
View File

@@ -0,0 +1,244 @@
/*****************************************************************************
*
* $Id: attach.c,v 1.30 2005/11/19 20:22:41 mbse Exp $
* Purpose ...............: Attach files to outbound
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
/*
* Attach a file to the real outbound fo a given node.
*/
int attach(faddr noden, char *ofile, int mode, char flavor)
{
FILE *fp;
char *flofile, *thefile;
int rc;
if (ofile == NULL)
return FALSE;
if ((rc = file_exist(ofile, R_OK))) {
WriteError("attach: file %s failed, %s", ofile, strerror(rc));
return FALSE;
}
/*
* Check if we attach a file with the same name
*/
un_attach(&noden, ofile);
flofile = calloc(PATH_MAX, sizeof(char));
thefile = calloc(PATH_MAX, sizeof(char));
snprintf(flofile, PATH_MAX -1, "%s", floname(&noden, flavor));
/*
* Check if outbound directory exists and
* create if it doesn't exist.
*/
mkdirs(ofile, 0770);
/*
* Attach file to .flo
*
* Note that mbcico when connected to a node opens the file "r+",
* locks it with fcntl(F_SETLK), F_RDLCK, whence=0, start=0L, len=0L.
* It seems that this lock is released after the files in the .flo
* files are send. I don't know what will happen if we add entries
* to the .flo files, this must be tested!
*/
if ((fp = fopen(flofile, "a+")) == NULL) {
WriteError("$Can't open %s", flofile);
WriteError("May be locked by mbcico");
free(flofile);
free(thefile);
return FALSE;
}
switch (mode) {
case LEAVE:
if (strlen(CFG.dospath)) {
if (CFG.leavecase)
snprintf(thefile, PATH_MAX -1, "@%s", Unix2Dos(ofile));
else
snprintf(thefile, PATH_MAX -1, "@%s", tu(Unix2Dos(ofile)));
} else {
snprintf(thefile, PATH_MAX -1, "@%s", ofile);
}
break;
case KFS:
if (strlen(CFG.dospath)) {
if (CFG.leavecase)
snprintf(thefile, PATH_MAX -1, "^%s", Unix2Dos(ofile));
else
snprintf(thefile, PATH_MAX -1, "^%s", tu(Unix2Dos(ofile)));
} else {
snprintf(thefile, PATH_MAX -1, "^%s", ofile);
}
break;
case TFS:
if (strlen(CFG.dospath)) {
if (CFG.leavecase)
snprintf(thefile, PATH_MAX -1, "#%s", Unix2Dos(ofile));
else
snprintf(thefile, PATH_MAX -1, "#%s", tu(Unix2Dos(ofile)));
} else {
snprintf(thefile, PATH_MAX -1, "#%s", ofile);
}
break;
}
fseek(fp, 0, SEEK_END);
fprintf(fp, "%s\r\n", thefile);
fclose(fp);
free(flofile);
free(thefile);
return TRUE;
}
int is_my_tic(char *, char *);
int is_my_tic(char *filename, char *ticfile)
{
FILE *fp;
char *buf;
int Found = FALSE;
buf = calloc(81, sizeof(char));
if ((fp = fopen(ticfile, "r"))) {
while (fgets(buf, 80, fp)) {
if (strstr(buf, filename)) {
Found = TRUE;
break;
}
}
fclose(fp);
}
free(buf);
return Found;
}
/*
* The real unatach function, return 1 if a file is removed.
*/
int check_flo(faddr *, char *, char);
int check_flo(faddr *node, char *filename, char flavor)
{
char *flofile, *ticfile, *buf;
FILE *fp;
int filepos, newpos;
char tpl = '~';
int rc = 0;
buf = calloc(PATH_MAX+3, sizeof(char));
flofile = calloc(PATH_MAX, sizeof(char));
ticfile = calloc(PATH_MAX, sizeof(char));
snprintf(flofile, PATH_MAX -1, "%s", floname(node, flavor));
if ((fp = fopen(flofile, "r+"))) {
filepos = 0;
while (fgets(buf, PATH_MAX +2, fp)) {
newpos = ftell(fp);
Striplf(buf);
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\0';
if (((strcmp(buf, filename) == 0) || (strcmp(buf+1, filename) == 0)) && (buf[0] != '~')) {
fseek(fp, filepos, SEEK_SET);
fwrite(&tpl, 1, 1, fp);
fflush(fp);
fseek(fp, newpos, SEEK_SET);
filepos = newpos;
if (fgets(buf, PATH_MAX +2, fp)) {
Striplf(buf);
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\0';
if (strstr(buf, ".tic") && is_my_tic(basename(filename), buf+1)) {
unlink(buf+1);
fseek(fp, filepos, SEEK_SET);
fwrite(&tpl, 1, 1, fp);
fflush(fp);
Syslog('+', "Removed old %s and %s for %s from outbound",
basename(filename), basename(buf+1), ascfnode(node, 0x1f));
} else {
Syslog('+', "Removed old %s for %s from outbound", basename(filename), ascfnode(node, 0x1f));
}
} else {
Syslog('+', "Removed old %s for %s from outbound", basename(filename), ascfnode(node, 0x1f));
}
rc = 1;
break;
}
filepos = ftell(fp);
}
fclose(fp);
}
free(ticfile);
free(flofile);
free(buf);
return rc;
}
/*
* Remove a file from the flofile, also search for a .tic file.
*/
void un_attach(faddr *node, char *filename)
{
char *base, *allname;
Syslog('p', "un_attach: %s %s", ascfnode(node, 0x1f), filename);
allname = xstrcpy(filename);
base = basename(allname);
if ((strlen(base) == 12) && ((strncasecmp(base+8,".su",3) == 0) ||
(strncasecmp(base+8,".mo",3) == 0) || (strncasecmp(base+8,".tu",3) == 0) ||
(strncasecmp(base+8,".we",3) == 0) || (strncasecmp(base+8,".th",3) == 0) ||
(strncasecmp(base+8,".fr",3) == 0) || (strncasecmp(base+8,".sa",3) == 0) ||
(strncasecmp(base+8,".tic",4) == 0))) {
free(allname);
return;
}
free(allname);
if (check_flo(node, filename, 'h') == 0)
if (check_flo(node, filename, 'f') == 0)
check_flo(node, filename, 'c');
}

88
lib/batchrd.c Normal file
View File

@@ -0,0 +1,88 @@
/*****************************************************************************
*
* $Id: batchrd.c,v 1.6 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Batch reading
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
static int counter = 0L;
static int batchmode = -1;
int usetmp = 0;
char *bgets(char *buf, int count, FILE *fp)
{
if (usetmp) {
return fgets(buf,count,fp);
}
if ((batchmode == 1) && (counter > 0L) && (counter < (count-1)))
count=(counter+1);
if (fgets(buf,count,fp) == NULL)
return NULL;
switch (batchmode) {
case -1: if (!strncmp(buf,"#! rnews ",9) || !strncmp(buf,"#!rnews ",8)) {
batchmode=1;
sscanf(buf+8,"%d",&counter);
Syslog('m', "first chunk of input batch: %d",counter);
if (counter < (count-1))
count=(counter+1);
if (fgets(buf,count,fp) == NULL)
return NULL;
else {
counter -= strlen(buf);
return(buf);
}
} else {
batchmode=0;
return buf;
}
case 0: return buf;
case 1: if (counter <= 0L) {
while (strncmp(buf,"#! rnews ",9) && strncmp(buf,"#!rnews ",8)) {
Syslog('+', "batch out of sync: %s",buf);
if (fgets(buf,count,fp) == NULL)
return NULL;
}
sscanf(buf+8,"%d",&counter);
Syslog('m', "next chunk of input batch: %d",counter);
return NULL;
} else {
counter -= strlen(buf);
Syslog('m', "bread \"%s\", %d left of this chunk", buf,counter);
return buf;
}
}
return buf;
}

1143
lib/bluewave.h Normal file

File diff suppressed because it is too large Load Diff

459
lib/charset.c Normal file
View File

@@ -0,0 +1,459 @@
/*****************************************************************************
*
* $Id: charset.c,v 1.43 2007/09/12 18:12:58 mbse Exp $
* Purpose ...............: Characterset functions
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
int use_tran1 = FALSE; /* Translate stage 1 active */
int use_tran2 = FALSE; /* Translate stage 2 active */
int loglevel = '-'; /* Debug loglevel */
#ifdef HAVE_ICONV_H
iconv_t cd1; /* Conversion descriptor 1 */
iconv_t cd2; /* Conversion descriptor 2 */
#endif
/*
* Search table for CHRS: kludge to the current name.
* This table may include obsolete names (and we need
* them).
*/
struct _charalias charalias[] = {
{(char *)"ASCII", (char *)"CP437"},
{(char *)"VT100", (char *)"CP437"},
{(char *)"US_ASCII", (char *)"CP437"},
{(char *)"LATIN", (char *)"LATIN-1"},
{(char *)"AMIGA", (char *)"CP437"},
{(char *)"IBMPC", (char *)"CP437"},
{(char *)"PC-8", (char *)"CP437"},
{(char *)"CP850", (char *)"CP437"},
{(char *)"MACINTOSH", (char *)"MAC"},
{(char *)"ALT", (char *)"CP866"},
{(char *)"X-ALT", (char *)"CP866"},
{(char *)"X-CP866", (char *)"CP866"},
{(char *)"+7_FIDO", (char *)"CP866"},
{(char *)"KOI8-U", (char *)"KOI8-R"},
{(char *)"IBM-878", (char *)"KOI8-R"},
{(char *)"CP878", (char *)"KOI8-R"},
{(char *)"IBM-915", (char *)"ISO-8859-1"},
{(char *)"X-CP1251", (char *)"CP1251"},
{(char *)"GBK", (char *)"CP936"},
{(char *)"HZ-GB-2312", (char *)"CP936"},
{NULL, NULL}
};
/*
* Array of charset identifiers.
* ftncidx, ftnkludge, rfcname, ic_ftn, lang, desc
*/
struct _charmap charmap[] = {
{FTNC_NONE, (char *)"Undef", (char *)"Undef", (char *)"Undef", (char *)"C", (char *)"Undefined"},
{FTNC_CP437, (char *)"CP437 2", (char *)"ibm437", (char *)"CP437", (char *)"en_US", (char *)"IBM codepage 437 (Western European) (ANSI terminal)"},
{FTNC_CP850, (char *)"CP850 2", (char *)"ibm850", (char *)"CP850", (char *)"en_US", (char *)"IBM codepage 850 (Latin-1) (ANSI terminal)"},
{FTNC_CP865, (char *)"CP865 2", (char *)"ibm865", (char *)"CP865", (char *)"sv_SE", (char *)"IBM codepage 865 (Nordic)"},
{FTNC_CP866, (char *)"CP866 2", (char *)"ibm866", (char *)"CP866", (char *)"ru_RU", (char *)"IBM codepage 866 (Russian)"},
{FTNC_LATIN_1,(char *)"LATIN-1 2",(char *)"iso-8859-1", (char *)"LATIN1", (char *)"en_US", (char *)"ISO 8859-1 (Western European)"},
{FTNC_LATIN_2,(char *)"LATIN-2 2",(char *)"iso-8859-2", (char *)"LATIN2", (char *)"cs_CZ", (char *)"ISO 8859-2 (Eastern European)"},
{FTNC_LATIN_5,(char *)"LATIN-5 2",(char *)"iso-8859-5", (char *)"LATIN5", (char *)"turks", (char *)"ISO 8859-5 (Turkish)"},
{FTNC_MAC, (char *)"MAC", (char *)"Macintosh", (char *)"MACINTOSH",(char *)"en_US", (char *)"MacIntosh character set"},
{FTNC_CP852, (char *)"CP852 2", (char *)"ibm852", (char *)"CP852", (char *)"cs_CZ", (char *)"IBM codepage 852 (Czech, Latin-2)"},
{FTNC_CP895, (char *)"CP895 2", (char *)"cp895", (char *)"CP850", (char *)"cs_CZ", (char *)"IBM codepage 895 (Czech, Kamenicky)"},
{FTNC_KOI8_R, (char *)"KOI8-R 2", (char *)"koi8-r", (char *)"KOI8-R", (char *)"ru_RUi.koi8r",(char *)"Unix codepage KOI8-R (Russian)"},
{FTNC_CP936, (char *)"CP936 2", (char *)"gbk", (char *)"CP936", (char *)"zh_CN.gbk", (char *)"IBM codepage 936 (Chinese, GBK)"},
{FTNC_LATIN_9,(char *)"LATIN-9 2",(char *)"iso-8859-15",(char *)"LATIN-9", (char *)"en_US", (char *)"ISO 8859-15 (Western European EURO)"},
{FTNC_UTF8, (char *)"UTF-8 4", (char *)"utf-8", (char *)"UTF-8", (char *)"en_US.UTF-8", (char *)"Unicode UTF-8 (ISO/IEC 10646)"},
{FTNC_ERROR, NULL, NULL, NULL, NULL, (char *)"ERROR"}
};
/*
* Returns index of charset or -1 if not found.
*/
int find_ftn_charset(char *ftnkludge)
{
static int i;
int j;
char *ftn, *cmp;
ftn = calloc(81, sizeof(char));
cmp = calloc(81, sizeof(char));
snprintf(ftn, 80, "%s", ftnkludge);
for (i = 0; i < strlen(ftn); i++) {
if (ftn[i] == ' ') {
ftn[i] = '\0';
break;
}
}
for (i = 0; charalias[i].alias; i++) {
if (strcasecmp(ftn, charalias[i].alias) == 0)
break;
}
if (charalias[i].alias != NULL) {
snprintf(ftn, 80, "%s", charalias[i].ftnkludge);
}
/*
* Now search real entry. Throw away the charset level number,
* we don't care about that useless byte.
*/
for (i = 0; charmap[i].ftnkludge; i++) {
snprintf(cmp, 80, "%s", charmap[i].ftnkludge);
for (j = 0; j < strlen(cmp); j++) {
if (cmp[j] == ' ') {
cmp[j] = '\0';
break;
}
}
if (strcasecmp(ftn, cmp) == 0)
break;
}
free(ftn);
free(cmp);
if (charmap[i].ftnkludge == NULL) {
Syslog('m', "find_ftn_charset(%s) not found", ftnkludge);
return FTNC_ERROR;
}
Syslog('m', "find_ftn_charset(%s) result %s", ftnkludge, charmap[i].ftnkludge);
return i;
}
/*
* Returns index of charset or -1 if not found.
*/
int find_rfc_charset(char *rfcname)
{
static int i;
for (i = 0; charmap[i].rfcname; i++) {
if (strcasecmp(rfcname, charmap[i].rfcname) == 0)
break;
}
if (charmap[i].rfcname == NULL) {
Syslog('m', "find_rfc_charset(%s) not found", rfcname);
return FTNC_ERROR;
}
Syslog('m', "find_rfc_charset(%s) result %s", rfcname, charmap[i].rfcname);
return i;
}
char *getftnchrs(int val)
{
static char kludge[21];
if ((val >= FTNC_NONE) && (val <= FTNC_MAXCHARS)) {
Syslog('m', "getftnchrs(%d) %s", val, charmap[val].ftnkludge);
snprintf(kludge, 20, "%s", charmap[val].ftnkludge);
return kludge;
}
return (char *)"LATIN-1 2";
}
char *getrfcchrs(int val)
{
static char rfcname[21];
if ((val >= FTNC_NONE) && (val <= FTNC_MAXCHARS)) {
Syslog('m', "getrfcchrs(%d) %s", val, charmap[val].rfcname);
snprintf(rfcname, 20, "%s", charmap[val].rfcname);
return rfcname;
}
return (char *)"iso-8859-1";
}
char *get_ic_ftn(int val)
{
static char ic_ftnname[21];
if ((val >= FTNC_NONE) && (val <= FTNC_MAXCHARS)) {
Syslog('m', "get_ic_ftn(%d) %s", val, charmap[val].ic_ftn);
snprintf(ic_ftnname, 20, "%s", charmap[val].ic_ftn);
return ic_ftnname;
}
return (char *)"LATIN1";
}
char *get_ic_rfc(int val)
{
static char ic_rfcname[21];
snprintf(ic_rfcname, 20, getrfcchrs(val));
tu(ic_rfcname);
return ic_rfcname;
}
/*
* Experimental table that should translate from the user selected
* charset to a locale. This is not the right way to do, the best
* thing is to store each bbs users locale instead and then lookup
* his characterset using standard library calls.
*
* This is one of the things the bbs world never saw coming, in the
* "good" old days bbses were almost allways called local. Thanks
* to the internet bbs users are now all over the world.
*/
char *getlocale(int val)
{
int i;
static char langc[21];
for (i = 0; (charmap[i].ftncidx != FTNC_ERROR); i++) {
if (val == charmap[i].ftncidx) {
snprintf(langc, 20, "%s", charmap[i].lang);
return langc;
}
}
return (char *)"C";
}
char *getchrsdesc(int val)
{
int i;
static char desc[61];
for (i = 0; (charmap[i].ftncidx != FTNC_ERROR); i++) {
if (val == charmap[i].ftncidx) {
snprintf(desc, 60, "%s", charmap[i].desc);
return desc;
}
}
return (char *)"ERROR";
}
/*
* Initialize charset translation. Translation can be done in 2 stages
* with UTF-8 as the common centre because for example translate between
* CP438 and ISO-8859-1 doesn't work directly. If translation is needed
* with one side is UTF-8, only one stage will be used. If two the same
* charactersets are given, the translation is off.
* On success return 0, on error return -1 and write errorlog.
*/
int chartran_init(char *fromset, char *toset, int loglvl)
{
loglevel = loglvl;
#ifdef HAVE_ICONV_H
if (use_tran1 || use_tran2) {
WriteError("chartran_init() called while still open");
chartran_close();
}
Syslog(loglevel, "chartran_init(%s, %s)", fromset, toset);
if (strcmp(fromset, toset) == 0) {
Syslog(loglevel, "nothing to translate");
return 0;
}
if (strcmp(fromset, (char *)"UTF-8")) {
cd1 = iconv_open("UTF-8", fromset);
if (cd1 == (iconv_t)-1) {
WriteError("$chartran_init(%s, %s): iconv_open(UTF-8, %s) error", fromset, toset, fromset);
return -1;
}
use_tran1 = TRUE;
}
if (strcmp(toset, (char *)"UTF-8")) {
cd2 = iconv_open(toset, "UTF-8");
if (cd2 == (iconv_t)-1) {
WriteError("$chartran_init(%s, %s): iconv_open(%s, UTF-8) error", fromset, toset, toset);
if (use_tran1) {
iconv_close(cd1);
use_tran1 = FALSE;
}
return -1;
}
use_tran2 = TRUE;
}
return 0;
#else
/*
* Without iconv support we silently return an error
*/
return -1;
#endif
}
/*
* Deinit active charset translation.
*/
void chartran_close(void)
{
#ifdef HAVE_ICONV_H
Syslog(loglevel, "chartran_close()");
if (use_tran1) {
iconv_close(cd1);
use_tran1 = FALSE;
}
if (use_tran2) {
iconv_close(cd2);
use_tran2 = FALSE;
}
#endif
}
/*
* Translate a string, chartran_init must have been called to register
* the charactersets to translate between.
*/
char *chartran(char *input)
{
static char outbuf[4096];
#ifdef HAVE_ICONV_H
static char temp[4096];
size_t rc, inSize, outSize;
char *in, *out;
#endif
memset(&outbuf, 0, sizeof(outbuf));
#ifdef HAVE_ICONV_H
memset(&temp, 0, sizeof(temp));
/*
* Transparant
*/
if (!use_tran1 && !use_tran2) {
strncpy(outbuf, input, sizeof(outbuf) -1);
return outbuf;
}
/*
* Translate to UTF-8
*/
if (use_tran1 && !use_tran2) {
inSize = strlen(input);
outSize = sizeof(outbuf);
in = input;
out = outbuf;
rc = iconv(cd1, &in, &inSize, &out, &outSize);
if (rc == -1) {
WriteError("$iconv(%s) cd1", printable(input, 0));
strncpy(outbuf, input, sizeof(outbuf) -1);
}
return outbuf;
}
/*
* Translate from UTF-8
*/
if (!use_tran1 && use_tran2) {
inSize = strlen(input);
outSize = sizeof(outbuf);
in = input;
out = outbuf;
rc = iconv(cd2, &in, &inSize, &out, &outSize);
if (rc == -1) {
WriteError("$iconv(%s) cd2", printable(input, 0));
strncpy(outbuf, input, sizeof(outbuf) -1);
}
return outbuf;
}
/*
* Double translation with UTF-8 as the middleman.
*/
inSize = strlen(input);
outSize = sizeof(temp);
in = input;
out = temp;
rc = iconv(cd1, &in, &inSize, &out, &outSize);
if (rc == -1) {
WriteError("$iconv(%s) cd1", printable(input, 0));
strncpy(outbuf, input, sizeof(outbuf) -1);
return outbuf;
}
inSize = strlen(temp);
outSize = sizeof(outbuf);
in = temp;
out = outbuf;
rc = iconv(cd2, &in, &inSize, &out, &outSize);
if (rc == -1) {
WriteError("$iconv(%s) cd2", printable(temp, 0));
strncpy(outbuf, input, sizeof(outbuf) -1);
}
return outbuf;
#else
/*
* Just copy without iconv
*/
strncpy(outbuf, input, sizeof(outbuf) -1);
return outbuf;
#endif
}

636
lib/clcomm.c Normal file
View File

@@ -0,0 +1,636 @@
/*****************************************************************************
*
* $Id: clcomm.c,v 1.32 2007/03/03 14:28:39 mbse Exp $
* Purpose ...............: Client/Server communications
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
int do_quiet = FALSE; /* Quiet flag */
int show_log = FALSE; /* Show loglines on screen */
int most_debug = FALSE; /* Toggle normal/most debugging */
int tcp_regged = FALSE; /* Safety TCP registration flag */
char progname[21]; /* Program name */
char logdebug[PATH_MAX]; /* Debug logfile */
char logfile[PATH_MAX]; /* Normal logfile */
char errfile[PATH_MAX]; /* Error logfile */
char mgrfile[PATH_MAX]; /* Area/File- mgr logfile */
int loggrade; /* Logging grade */
pid_t mypid; /* Original parent pid if child */
unsigned int lcrc = 0, tcrc = 1; /* CRC value of logstring */
int lcnt = 0; /* Same message counter */
static char *pbuff = NULL;
extern char cpath[108];
extern char spath[108];
char *xmalloc(size_t size)
{
char *tmp;
tmp = malloc(size);
if (!tmp)
abort();
return tmp;
}
char *xstrcpy(char *src)
{
char *tmp;
if (src == NULL)
return(NULL);
tmp = xmalloc(strlen(src)+1);
strcpy(tmp, src);
return tmp;
}
char *xstrcat(char *src, char *add)
{
char *tmp;
size_t size = 0;
if ((add == NULL) || (strlen(add) == 0))
return src;
if (src)
size = strlen(src);
size += strlen(add);
tmp = xmalloc(size + 1);
*tmp = '\0';
if (src) {
strcpy(tmp, src);
free(src);
}
strcat(tmp, add);
return tmp;
}
void InitClient(char *user, char *myname, char *where, char *logfname, int loggr, char *err, char *mgr, char *debug)
{
if ((getenv("MBSE_ROOT")) == NULL) {
printf("Could not get the MBSE_ROOT environment variable\n");
printf("Please set the environment variable ie:\n");
printf("\"MBSE_ROOT=/opt/mbse; export MBSE_ROOT\"\n\n");
exit(MBERR_INIT_ERROR);
}
snprintf(progname, 20, "%s", myname);
snprintf(logfile, PATH_MAX -1, "%s", logfname);
snprintf(errfile, PATH_MAX -1, "%s", err);
snprintf(mgrfile, PATH_MAX -1, "%s", mgr);
snprintf(logdebug, PATH_MAX -1, "%s", debug);
loggrade = loggr;
snprintf(cpath, 107, "%s/tmp/%s%d", getenv("MBSE_ROOT"), progname, getpid());
snprintf(spath, 107, "%s/tmp/mbtask", getenv("MBSE_ROOT"));
/*
* Store my pid in case a child process is forked and wants to do
* some communications with the mbsed server.
*/
mypid = getpid();
if (socket_connect(user, myname, where) == -1) {
printf("PANIC: cannot access socket\n");
exit(MBERR_INIT_ERROR);
}
}
void ExitClient(int errcode)
{
if (socket_shutdown(mypid) == -1)
printf("PANIC: unable to shutdown socket\n");
unlink(cpath);
fflush(stdout);
fflush(stdin);
if (pbuff)
free(pbuff);
exit(errcode);
}
void SockS(const char *format, ...)
{
char *out;
va_list va_ptr;
out = calloc(SS_BUFSIZE, sizeof(char));
va_start(va_ptr, format);
vsnprintf(out, SS_BUFSIZE, format, va_ptr);
va_end(va_ptr);
if (socket_send(out) == 0)
socket_receive();
free(out);
}
char *SockR(const char *format, ...)
{
static char buf[SS_BUFSIZE];
char *out;
va_list va_ptr;
memset(&buf, 0, SS_BUFSIZE);
out = calloc(SS_BUFSIZE, sizeof(char));
va_start(va_ptr, format);
vsnprintf(out, SS_BUFSIZE, format, va_ptr);
va_end(va_ptr);
if (socket_send(out) == 0)
snprintf(buf, SS_BUFSIZE, "%s", socket_receive());
free(out);
return buf;
}
void WriteError(const char *format, ...)
{
char *outputstr, *temp;
va_list va_ptr;
int i;
outputstr = calloc(10240, sizeof(char));
va_start(va_ptr, format);
vsnprintf(outputstr, 10240, format, va_ptr);
va_end(va_ptr);
for (i = 0; i < strlen(outputstr); i++)
if (outputstr[i] == '\r' || outputstr[i] == '\n')
outputstr[i] = ' ';
if (*outputstr == '$')
snprintf(outputstr+strlen(outputstr), 10240, ": %s", strerror(errno));
if (strlen(outputstr) > (SS_BUFSIZE - 64)) {
outputstr[SS_BUFSIZE - 65] = ';';
outputstr[SS_BUFSIZE - 64] = '\0';
}
tcrc = StringCRC32(outputstr);
if (tcrc == lcrc) {
lcnt++;
free(outputstr);
return;
} else {
lcrc = tcrc;
if (lcnt) {
lcnt++;
SockS("ALOG:5,%s,%s,%d,?,Last message repeated %d times;", logdebug, progname, mypid, lcnt);
SockS("ALOG:5,%s,%s,%d,?,Last message repeated %d times;", logfile, progname, mypid, lcnt);
SockS("ALOG:5,%s,%s,%d,?,Last message repeated %d times;", errfile, progname, mypid, lcnt);
}
lcnt = 0;
}
if (*outputstr == '$') {
temp = xstrcpy(clencode(outputstr+1));
} else {
temp = xstrcpy(clencode(outputstr));
}
SockS("ALOG:5,%s,%s,%d,?,%s;", logdebug, progname, mypid, temp);
SockS("ALOG:5,%s,%s,%d,?,%s;", logfile, progname, mypid, temp);
SockS("ALOG:5,%s,%s,%d,?,%s;", errfile, progname, mypid, temp);
free(temp);
free(outputstr);
}
/*
* Standard system logging
*/
void Syslog(int level, const char *format, ...)
{
char *outstr;
va_list va_ptr;
outstr = calloc(10240, sizeof(char));
va_start(va_ptr, format);
vsnprintf(outstr, 10240, format, va_ptr);
va_end(va_ptr);
Syslogp(level, outstr);
free(outstr);
}
/*
* System logging without string formatting.
*/
void Syslogp(int level, char *outstr)
{
int mask = 0;
int i, upper, debug;
debug = isalpha(level);
upper = isupper(level);
switch(tolower(level)) {
case ' ' : mask = DLOG_ALLWAYS; break;
case '?' : mask = DLOG_ERROR; break;
case '!' : mask = DLOG_ATTENT; break;
case '+' : mask = DLOG_NORMAL; break;
case '-' : mask = DLOG_VERBOSE; break;
case 'a' : mask = DLOG_TCP; break;
case 'b' : mask = DLOG_BBS; break;
case 'c' : mask = DLOG_CHAT; break;
case 'd' : mask = DLOG_DEVIO; break;
case 'e' : mask = DLOG_EXEC; break;
case 'f' : mask = DLOG_FILEFWD; break;
case 'h' : mask = DLOG_HYDRA; break;
case 'i' : mask = DLOG_IEMSI; break;
case 'l' : mask = DLOG_LOCK; break;
case 'm' : mask = DLOG_MAIL; break;
case 'n' : mask = DLOG_NODELIST; break;
case 'o' : mask = DLOG_OUTSCAN; break;
case 'p' : mask = DLOG_PACK; break;
case 'r' : mask = DLOG_ROUTE; break;
case 's' : mask = DLOG_SESSION; break;
case 't' : mask = DLOG_TTY; break;
case 'x' : mask = DLOG_XMODEM; break;
case 'z' : mask = DLOG_ZMODEM; break;
}
if (((loggrade | DLOG_ALLWAYS | DLOG_ERROR) & mask) == 0)
return;
/*
* Don't log uppercase debug levels when most_debug is FALSE
*/
if (upper && !most_debug)
return;
for (i = 0; i < strlen(outstr); i++)
if (outstr[i] == '\r' || outstr[i] == '\n')
outstr[i] = ' ';
if (strlen(outstr) > (SS_BUFSIZE - 64))
outstr[SS_BUFSIZE - 64] = '\0';
tcrc = StringCRC32(outstr);
if (tcrc == lcrc) {
lcnt++;
return;
} else {
lcrc = tcrc;
if (lcnt) {
lcnt++;
SockS("ALOG:5,%s,%s,%d,%c,Last message repeated %d times;", logdebug, progname, mypid, level, lcnt);
if (!debug)
SockS("ALOG:5,%s,%s,%d,%c,Last message repeated %d times;", logfile, progname, mypid, level, lcnt);
}
lcnt = 0;
}
if (show_log)
printf("%c %s\n", level, outstr);
if (*outstr == '$') {
SockS("ALOG:5,%s,%s,%d,%c,%s: %s;", logdebug, progname, mypid, level, clencode(outstr+1), strerror(errno));
if (!debug)
SockS("ALOG:5,%s,%s,%d,%c,%s: %s;", logfile, progname, mypid, level, clencode(outstr+1), strerror(errno));
} else {
SockS("ALOG:5,%s,%s,%d,%c,%s;", logdebug, progname, mypid, level, clencode(outstr));
if (!debug)
SockS("ALOG:5,%s,%s,%d,%c,%s;", logfile, progname, mypid, level, clencode(outstr));
}
}
void Mgrlog(const char *format, ...)
{
char *outstr;
va_list va_ptr;
int i;
outstr = calloc(10240, sizeof(char));
va_start(va_ptr, format);
vsnprintf(outstr, 10240, format, va_ptr);
va_end(va_ptr);
for (i = 0; i < strlen(outstr); i++)
if (outstr[i] == '\r' || outstr[i] == '\n')
outstr[i] = ' ';
if (strlen(outstr) > (SS_BUFSIZE - 64))
outstr[SS_BUFSIZE - 64] = '\0';
SockS("ALOG:5,%s,%s,%d,+,%s;", mgrfile, progname, mypid, clencode(outstr));
Syslogp('+', outstr);
free(outstr);
}
void IsDoing(const char *format, ...)
{
char *outputstr;
va_list va_ptr;
outputstr = calloc(SS_BUFSIZE, sizeof(char));
va_start(va_ptr, format);
vsnprintf(outputstr, SS_BUFSIZE, format, va_ptr);
va_end(va_ptr);
SockS("ADOI:2,%d,%s;", mypid, clencode(outputstr));
free(outputstr);
}
void RegTCP(void)
{
if (!tcp_regged)
SockS("ATCP:1,%d;", mypid);
tcp_regged = TRUE;
}
void SetTTY(char *tty)
{
SockS("ATTY:2,%d,%s;", mypid, tty);
}
void UserCity(pid_t pid, char *user, char *city)
{
char *u, *c;
u = xstrcpy(clencode(user));
c = xstrcpy(clencode(city));
SockS("AUSR:3,%d,%s,%s;", pid, u, c);
free(u);
free(c);
}
void DoNop()
{
SockS("GNOP:1,%d;", mypid);
}
static time_t nop = 0;
/*
* This function can be called very often but will only send once a minute
* a NOP to the server. This is a simple solution to keep server trafic low.
*/
void Nopper(void)
{
time_t now;
now = time(NULL);
if ((now - nop) > 60) {
nop = now;
SockS("GNOP:1,%d;", mypid);
}
}
/*
* Set new alarmtime for Client/Server connection,
* if zero set the default time.
*/
void Altime(int altime)
{
if (altime)
SockS("ATIM:2,%d,%d;", mypid, altime);
else
SockS("ADEF:1,%d;", mypid);
}
unsigned int sequencer()
{
char *buf, *res;
unsigned int seq = 0;
buf = calloc(SS_BUFSIZE, sizeof(char));
snprintf(buf, SS_BUFSIZE, "SSEQ:0;");
if (socket_send(buf) == 0) {
free(buf);
buf = socket_receive();
res = strtok(buf, ",");
res = strtok(NULL, ";");
seq = atol(res);
}
return seq;
}
/*
* Check enough diskspace.
* return 0=No, 1=Yes, 2=Unknown, 3=Error
*/
int enoughspace(unsigned int needed)
{
char *buf, *res;
int rc = 3, cnt;
unsigned int avail = 0L;
buf = calloc(SS_BUFSIZE, sizeof(char));
snprintf(buf, SS_BUFSIZE, "DSPC:1,%d;", needed);
if (socket_send(buf) == 0) {
snprintf(buf, SS_BUFSIZE, "%s", socket_receive());
res = strtok(buf, ":");
cnt = atoi(strtok(NULL, ","));
if (cnt == 1) {
rc = atoi(strtok(NULL, ";"));
} else if (cnt == 2) {
rc = atoi(strtok(NULL, ","));
avail = atol(strtok(NULL, ";"));
if (rc == 0)
Syslog('+', "Only %ld MBytes diskspace, need %ld MBytes", avail, needed);
} else {
Syslog('-', "Error in enoughspace()");
}
}
free(buf);
return rc;
}
char *clencode(char *s)
{
char Base16Code[]="0123456789ABCDEF";
static char *buf;
char *p, *q;
if (buf)
free(buf);
buf = NULL;
if (s == NULL)
return NULL;
if ((buf = malloc(3 * strlen(s) + 1 * sizeof(char))) == NULL) {
Syslog('+', "clencode: out of memory:string too long:\"%s\"", s);
return s;
}
for (p = s, q = buf; *p != '\0';) {
if (( ! isascii(*p)) || (*p == '%') || (*p == ',') || (*p == ';') || (*p == '"')) {
*q++ = '\\';
*q++ = Base16Code[(*p >> 4) & 0x0f];
*q++ = Base16Code[*p & 0x0f];
p++;
} else if (*p == '\\') {
*q++ = '\\';
*q++ = *p++;
} else {
*q++ = *p++;
}
}
*q = '\0';
return buf;
}
char *cldecode(char *s)
{
char *p, *q;
int i;
if ((s == NULL) || (! strlen(s))) {
return (char *)"";
}
for (p = s, q = s; *p; p++) {
if (*p == '\\') {
if (*(p + 1) == '\\') {
*q++ = *p++;
} else {
sscanf(p + 1, "%02x", &i);
*q++ = i;
p += 2;
}
} else {
*q++ = *p;
}
}
*q = '\0';
return s;
}
char *printable(char *s, int l)
{
int len;
char *p;
unsigned char c;
if (pbuff)
free(pbuff);
pbuff=NULL;
if (s == NULL)
return (char *)"(null)";
if (l > 0)
len=l;
else if (l == 0)
len=strlen(s);
else {
len=strlen(s);
if (len > -l)
len=-l;
}
pbuff=(char*)xmalloc(len*3+1);
p=pbuff;
while (len--) {
/*
* Don't use isprint to check if a character is printable because we
* don't want some current locale to have some influence on this
* conversion. Just filter low ascii values.
*/
c = *(unsigned char*)s;
if ((c >= 32) && (c < 128))
*p++=*s;
else
switch (*s) {
case '\\': *p++='\\'; *p++='\\'; break;
case '\r': *p++='\\'; *p++='r'; break;
case '\n': *p++='\\'; *p++='n'; break;
case '\t': *p++='\\'; *p++='t'; break;
case '\b': *p++='\\'; *p++='b'; break;
default: snprintf(p, 5, "\\%02x", (*s & 0xff)); p+=3; break;
}
s++;
}
*p='\0';
return pbuff;
}
char *printablec(char c)
{
return printable(&c,1);
}

229
lib/client.c Normal file
View File

@@ -0,0 +1,229 @@
/*****************************************************************************
*
* $Id: client.c,v 1.17 2007/08/25 12:19:44 mbse Exp $
* Purpose ...............: MBSE Deamon Client
*
*****************************************************************************
* Copyright (C) 1993-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 MB 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 "mbselib.h"
static int sock = -1; /* Unix Datagram socket */
struct sockaddr_un clntaddr; /* Client socket address */
struct sockaddr_un servaddr; /* Server socket address */
struct sockaddr_un from; /* From socket address */
socklen_t fromlen;
static char *myname='\0'; /* my program name */
char spath[108]; /* Server socket path */
char cpath[108]; /* Client socket path */
/************************************************************************
*
* Connect to Unix Datagram socket, return -1 if error or socket no.
*/
int socket_connect(char *user, char *prg, char *city)
{
int s;
static char buf[SS_BUFSIZE], tty[18];
char *tmp, *u, *p, *c;
myname = prg;
/*
* Create Unix Datagram socket for the client.
*/
s = socket(AF_UNIX, SOCK_DGRAM, 0);
if (s == -1) {
perror(myname);
printf("Unable to create Unix Datagram socket\n");
return -1;
}
/*
* Client will bind to an address so the server will get
* an address in its recvfrom call and use it to send
* data back to the client.
*/
memset(&clntaddr, 0, sizeof(clntaddr));
clntaddr.sun_family = AF_UNIX;
strcpy(clntaddr.sun_path, cpath);
if (bind(s, (struct sockaddr *)&clntaddr, sizeof(clntaddr)) < 0) {
close(s);
perror(myname);
printf("Can't bind socket %s\n", cpath);
return -1;
}
/*
* If running seteuid as another user, chown to mbse.bbs
*/
if (getuid() != geteuid()) {
chown(cpath, getuid(), getgid());
} else {
chmod(cpath, 0775);
}
/*
* Setup address structure for the server socket.
*/
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, spath);
/*
* Now that we have an connection, we gather
* information to tell the server who we are.
*/
if (isatty(1) && (ttyname(1) != NULL)) {
strncpy(tty, ttyname(1), sizeof(tty)-1);
if (strchr(tty, 'p'))
memccpy(tty, index(tty, 'p'), '\0', strlen(tty));
else if (strchr(tty, 't'))
memccpy(tty, index(tty, 't'), '\0', strlen(tty));
else if (strchr(tty, 'c'))
memccpy(tty, index(tty, 'c'), '\0', strlen(tty));
} else {
strcpy(tty, "-");
}
sock = s;
/*
* Send the information to the server.
*/
u = xstrcpy(clencode(user));
p = xstrcpy(clencode(prg));
c = xstrcpy(clencode(city));
snprintf(buf, SS_BUFSIZE, "AINI:5,%d,%s,%s,%s,%s;", getpid(), tty, u, p, c);
free(c);
free(p);
free(u);
if (socket_send(buf) != 0) {
sock = -1;
return -1;
}
strcpy(buf, socket_receive());
if (strncmp(buf, "100:1,", 6) != 0) {
printf("AINI not acknowledged by the server\n");
sock = -1;
return -1;
}
/*
* Extract nodenumber from the reply.
*/
tmp = strtok(buf, ",");
tmp = strtok(NULL, ";");
iNode = atoi(tmp);
return s;
}
/*
* Send data via internet domain socket
*/
int socket_send(char *buf)
{
if (sock == -1)
return -1;
if (sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) != strlen(buf)) {
printf("Socket send failed error %d\n", errno);
if (errno == 2) {
abort();
}
return -1;
}
return 0;
}
/*
* Return an empty buffer if somthing went wrong, else the complete
* dataline is returned.
*/
char *socket_receive(void)
{
static char buf[SS_BUFSIZE];
ssize_t rlen;
memset((char *)&buf, 0, SS_BUFSIZE);
fromlen = sizeof(from);
rlen = recvfrom(sock, buf, SS_BUFSIZE, 0, (struct sockaddr *)&from, &fromlen);
if (rlen == -1) {
perror("recv");
printf("Error reading socket\n");
memset((char *)&buf, 0, SS_BUFSIZE);
return buf;
}
return buf;
}
/***************************************************************************
*
* Shutdown the socket, first send the server the close command so this
* application will be removed from the servers active clients list.
* There must be a parameter with the pid so that client applications
* where the shutdown will be done by a child process is able to give
* the parent pid as an identifier.
*/
int socket_shutdown(pid_t pid)
{
static char buf[SS_BUFSIZE];
if (sock == -1)
return 0;
snprintf(buf, SS_BUFSIZE, "ACLO:1,%d;", pid);
if (socket_send(buf) == 0) {
strcpy(buf, socket_receive());
if (strncmp(buf, "107:0;", 6) != 0) {
printf("Shutdown not acknowledged by the server\n");
printf("Got \"%s\"\n", buf);
}
}
if (shutdown(sock, 1) == -1) {
perror(myname);
printf("Cannot shutdown socket\n");
return -1;
}
sock = -1;
return 0;
}

292
lib/crc.c Normal file
View File

@@ -0,0 +1,292 @@
/*****************************************************************************
*
* $Id: crc.c,v 1.8 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Crc32 and Crc16 calculations
*
*****************************************************************************
* Copyright (C) 1993-2005
*
* 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.
*
* MB 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 MB 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 "mbselib.h"
/*
* Copyright (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
unsigned int crc32tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
unsigned short crc16xmodemtab[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
unsigned short crc16ccitttab[256] = /* CRC polynomial 0x8408 */
{
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
unsigned int crc32ccitt(char *str, int l)
{
unsigned int crc;
for (crc = 0xffffffffL; l--; str++)
crc = crc32tab[((int) crc ^ (*str)) & 0xff] ^ ((crc >> 8) & 0x00ffffffL);
return crc;
}
unsigned short crc16ccitt(char *str, int l)
{
unsigned short crc;
for (crc = 0xffff; l--; str++)
crc = crc16ccitttab[(crc ^ (*str)) & 0xff] ^ ((crc >> 8) & 0x00ff);
return crc;
}
/*
* Calculate the CRC of a string.
*/
unsigned int str_crc32(char *str)
{
unsigned int crc;
for (crc=0L; *str; str++)
crc = crc32tab[((int)crc^(*str)) & 0xff] ^ ((crc>>8) & 0x00ffffffL);
return crc;
}
unsigned int StringCRC32(char *str)
{
unsigned int crc;
for (crc = 0xffffffffL; *str; str++)
crc = crc32tab[((int)crc^(*str)) & 0xff] ^ ((crc>>8) & 0x00ffffffL);
return crc;
}
/*
* Update CRC32, first initialize crc with 0xffffffff
*/
unsigned int upd_crc32(char *buf, unsigned int crc, int len)
{
int i;
unsigned int cr;
cr = crc;
for (i = 0; i < len; i++) {
cr = (crc32tab[((int)cr ^ ((int)buf[i])) & 0xff] ^ ((((unsigned int)cr) >> 8) & 0x00ffffffL));
}
return cr;
}
/*
* return normalized CRC32 value, which means put al bytes in the
* normal (not for comms) order.
*/
unsigned int norm_crc32(unsigned int crc)
{
unsigned int L;
L = crc & 0x000000ffL;
L <<= 8;
L |= ((crc >> 8) & 0x000000ffL);
L <<= 8;
L |= ((crc >> 16) & 0x000000ffL);
L <<= 8;
L |= ((crc >> 24) & 0x000000ffL);
return L;
}
unsigned short crc16xmodem(char *str, int l)
{
unsigned short crc;
for (crc = 0; l--; str++)
crc = crc16xmodemtab[(((crc>>8)&0xff)^(*str)) & 0xff] ^ (crc<<8);
return crc;
}
unsigned char checksum(char *str, int l)
{
unsigned char cs;
for (cs=0;l--;str++)
cs += (unsigned char)(*str);
return cs;
}

92
lib/dbcfg.c Normal file
View File

@@ -0,0 +1,92 @@
/*****************************************************************************
*
* $Id: dbcfg.c,v 1.8 2005/08/28 10:30:41 mbse Exp $
* Purpose ...............: Config Database.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "mbse.h"
#include "users.h"
#include "mbsedb.h"
void InitConfig(void)
{
if ((getenv("MBSE_ROOT")) == NULL) {
printf("Could not get MBSE_ROOT environment variable\n");
printf("Please set the environment variable ie:\n");
printf("\"MBSE_ROOT=/opt/mbse;export MBSE_ROOT\"\n\n");
exit(MBERR_INIT_ERROR);
}
LoadConfig();
}
void LoadConfig(void)
{
FILE *pDataFile;
char *FileName;
FileName = calloc(PATH_MAX, sizeof(char));
snprintf(FileName, PATH_MAX -1, "%s/etc/config.data", getenv("MBSE_ROOT"));
if ((pDataFile = fopen(FileName, "r")) == NULL) {
perror("\n\nFATAL ERROR:");
printf(" Can't open %s\n", FileName);
printf("Please run mbsetup to create configuration file.\n");
printf("Or check that your MBSE_ROOT variable is set to the BBS path!\n\n");
free(FileName);
exit(MBERR_CONFIG_ERROR);
}
free(FileName);
fread(&CFG, sizeof(CFG), 1, pDataFile);
fclose(pDataFile);
}
int IsOurAka(fidoaddr taka)
{
int i;
for (i = 0; i < 40; i++) {
if ((taka.zone == CFG.aka[i].zone) &&
(taka.net == CFG.aka[i].net) &&
(taka.node == CFG.aka[i].node) &&
(taka.point == CFG.aka[i].point) &&
(CFG.akavalid[i]))
return TRUE;
}
return FALSE;
}

189
lib/dbdupe.c Normal file
View File

@@ -0,0 +1,189 @@
/*****************************************************************************
*
* $Id: dbdupe.c,v 1.14 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Dupe checking.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "mbse.h"
#include "users.h"
#include "mbsedb.h"
typedef struct _dupesrec {
unsigned int *crcs;
int loaded;
int changed;
int count;
int max;
int peak;
} dupesrec;
dupesrec dupes[3];
static char *files[] = {(char *)"echomail", (char *)"fileecho", (char *)"news"};
void CloseDdb(int);
void InitDupes()
{
int i;
Syslog('n', "Init Dupes");
memset(dupes, 0, sizeof(dupes));
for (i = 0; i < 3; i++) {
dupes[i].crcs= NULL;
dupes[i].loaded = FALSE;
dupes[i].changed = FALSE;
dupes[i].count = 0;
dupes[i].max = 0;
}
}
int CheckDupe(unsigned int crc, int idx, int max)
{
char *dfile;
FILE *fil;
unsigned int test;
int i, size = 0;
if (!dupes[idx].loaded) {
dfile = calloc(PATH_MAX, sizeof(char));
snprintf(dfile, PATH_MAX -1, "%s/etc/%s.dupe", getenv("MBSE_ROOT"), files[idx]);
if ((fil = fopen(dfile, "r+")) == NULL) {
/*
* Dupe database doesn't exist yet.
*/
if ((fil = fopen(dfile, "w")) == NULL) {
WriteError("$PANIC: dbdupe.c, can't create %s", dfile);
free(dfile);
exit(MBERR_INIT_ERROR);
}
fclose(fil);
fil = fopen(dfile, "r+");
} else {
fseek(fil, 0L, SEEK_END);
size = ftell(fil) / sizeof(unsigned int);
fseek(fil, 0L, SEEK_SET);
}
/*
* Reserve some extra memory and record howmuch.
*/
if (size > max)
dupes[idx].peak = size + 5000;
else
dupes[idx].peak = max + 5000;
dupes[idx].crcs = (unsigned int *)malloc(dupes[idx].peak * sizeof(unsigned int));
memset(dupes[idx].crcs, 0, dupes[idx].peak * sizeof(unsigned int));
/*
* Load dupe records
*/
while (fread(&test, sizeof(test), 1, fil) == 1) {
dupes[idx].crcs[dupes[idx].count] = test;
dupes[idx].count++;
}
fclose(fil);
free(dfile);
dupes[idx].loaded = TRUE;
dupes[idx].max = max;
}
for (i = 0; i < dupes[idx].count; i++) {
if (dupes[idx].crcs[i] == crc) {
return TRUE;
}
}
/*
* Not a dupe, append new crc value
*/
dupes[idx].crcs[dupes[idx].count] = crc;
dupes[idx].count++;
dupes[idx].changed = TRUE;
/*
* If we reach the high limit, flush the current dupelist.
*/
if (dupes[idx].count >= dupes[idx].peak)
CloseDdb(idx);
return FALSE;
}
void CloseDdb(int idx)
{
int j, start;
char *dfile;
FILE *fil;
dfile = calloc(PATH_MAX, sizeof(char));
if (dupes[idx].loaded) {
if (dupes[idx].changed) {
if (dupes[idx].count > dupes[idx].max)
start = dupes[idx].count - dupes[idx].max;
else
start = 0;
snprintf(dfile, PATH_MAX -1, "%s/etc/%s.dupe", getenv("MBSE_ROOT"), files[idx]);
if ((fil = fopen(dfile, "w"))) {
for (j = start; j < dupes[idx].count; j++)
fwrite(&dupes[idx].crcs[j], sizeof(unsigned int), 1, fil);
fclose(fil);
} else {
WriteError("$Can't write %s", dfile);
}
}
dupes[idx].changed = FALSE;
dupes[idx].loaded = FALSE;
dupes[idx].count = 0;
dupes[idx].max = 0;
dupes[idx].peak = 0;
free(dupes[idx].crcs);
dupes[idx].crcs = NULL;
}
free(dfile);
}
void CloseDupes()
{
int i;
for (i = 0; i < 3; i++)
CloseDdb(i);
}

557
lib/dbfdb.c Normal file
View File

@@ -0,0 +1,557 @@
/*****************************************************************************
*
* $Id: dbfdb.c,v 1.29 2007/03/03 14:28:40 mbse Exp $
* Purpose ...............: Files database functions
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
/*
* Open files database Area number. Do some checks and abort
* if they fail.
*/
struct _fdbarea *mbsedb_OpenFDB(int Area, int Timeout)
{
char *temp, *temp2;
struct _fdbarea *fdb_area = NULL;
int Tries = 0;
FILE *fp, *fp2;
temp = calloc(PATH_MAX, sizeof(char));
fdb_area = malloc(sizeof(struct _fdbarea)); /* Will be freed by CloseFDB */
snprintf(temp, PATH_MAX -1, "%s/var/fdb/file%d.data", getenv("MBSE_ROOT"), Area);
/*
* Open the file database, if it's locked, just wait.
*/
while (((fp = fopen(temp, "r+")) == NULL) && ((errno == EACCES) || (errno == EAGAIN))) {
if (++Tries >= (Timeout * 4)) {
WriteError("Can't open file area %d, timeout", Area);
free(temp);
return NULL;
}
msleep(250);
Syslog('-', "Open file area %d, try %d", Area, Tries);
}
if (fp == NULL) {
if (errno == ENOENT) {
Syslog('+', "Create empty FDB for area %d", Area);
fdbhdr.hdrsize = sizeof(fdbhdr);
fdbhdr.recsize = sizeof(fdb);
if ((fp = fopen(temp, "w+"))) {
fwrite(&fdbhdr, sizeof(fdbhdr), 1, fp);
}
}
} else {
fread(&fdbhdr, sizeof(fdbhdr), 1, fp);
}
/*
* If still not open, it's fatal.
*/
if (fp == NULL) {
WriteError("$Can't open %s", temp);
free(temp);
return NULL;
}
if ((fdbhdr.hdrsize == sizeof(fdbhdr)) && (fdbhdr.recsize == (sizeof(fdb) + 4))) {
Syslog('+', "Files area %d database 64/32 bit alignment error, fixing...", Area);
temp2 = calloc(PATH_MAX, sizeof(char));
snprintf(temp2, PATH_MAX -1, "%s/var/fdb/file%d.temp", getenv("MBSE_ROOT"), Area);
if ((fp2 = fopen(temp2, "w+"))) {
fdbhdr.recsize = (sizeof(fdb));
fwrite(&fdbhdr, sizeof(fdbhdr), 1, fp2);
fdbhdr.recsize = sizeof(fdb) + 4;
while (fread(&fdb, fdbhdr.recsize, 1, fp) == 1) {
/*
* Shift 4 bytes
*/
memmove(&fdb.Crc32, &fdb.Uploader, sizeof(fdb) - 179);
fwrite(&fdb, sizeof(fdb), 1, fp2);
}
fclose(fp2);
fclose(fp);
unlink(temp);
rename(temp2, temp);
if ((fp = fopen(temp, "r+"))) {
fread(&fdbhdr, sizeof(fdbhdr), 1, fp);
} else {
WriteError("$Can't reopen %s", temp);
}
} else {
WriteError("$Can't create %s", temp2);
}
free(temp2);
}
/*
* Fix attributes if needed
*/
chmod(temp, 0660);
free(temp);
if ((fdbhdr.hdrsize != sizeof(fdbhdr)) || (fdbhdr.recsize != sizeof(fdb))) {
WriteError("Files database header in area %d is corrupt (%d:%d) [%d:%d]", Area, fdbhdr.hdrsize, fdbhdr.recsize,
sizeof(fdbhdr), sizeof(fdb));
fclose(fp);
return NULL;
}
fseek(fp, 0, SEEK_END);
if ((ftell(fp) - fdbhdr.hdrsize) % fdbhdr.recsize) {
WriteError("Files database area %d is corrupt, unalligned records", Area);
fclose(fp);
return NULL;
}
/*
* Point to the first record
*/
fseek(fp, fdbhdr.hdrsize, SEEK_SET);
fdb_area->fp = fp;
fdb_area->locked = 0;
fdb_area->area = Area;
return fdb_area;
}
/*
* Close current open file area
*/
int mbsedb_CloseFDB(struct _fdbarea *fdb_area)
{
fclose(fdb_area->fp);
free(fdb_area);
return TRUE;
}
/*
* Lock Files DataBase
*/
int mbsedb_LockFDB(struct _fdbarea *fdb_area, int Timeout)
{
int rc, Tries = 0;
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0L;
fl.l_len = 1L;
fl.l_pid = getpid();
while ((rc = fcntl(fileno(fdb_area->fp), F_SETLK, &fl)) && ((errno == EACCES) || (errno == EAGAIN))) {
if (++Tries >= (Timeout * 4)) {
fcntl(fileno(fdb_area->fp), F_GETLK, &fl);
WriteError("FDB %d is locked by pid %d", fdb_area->area, fl.l_pid);
return FALSE;
}
msleep(250);
Syslog('-', "FDB lock attempt %d", Tries);
}
if (rc) {
WriteError("FDB %d lock error", fdb_area->area);
return FALSE;
}
fdb_area->locked = 1;
return TRUE;
}
/*
* Unlock Files DataBase
*/
int mbsedb_UnlockFDB(struct _fdbarea *fdb_area)
{
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0L;
fl.l_len = 1L;
fl.l_pid = getpid();
if (fcntl(fileno(fdb_area->fp), F_SETLK, &fl)) {
WriteError("$Can't unlock FDB area %ld", fdb_area->area);
}
fdb_area->locked = 0;
return TRUE;
}
void mbsedb_Temp2Data(unsigned int);
void mbsedb_Temp2Data(unsigned int fdb_area)
{
char *temp1, *temp2;
temp1 = calloc(PATH_MAX, sizeof(char));
temp2 = calloc(PATH_MAX, sizeof(char));
/*
* Now the trick, some might be waiting for a lock on the original file,
* we will give that a new name on disk. Then we move the temp in place.
* Finaly remove the old (still locked) original file.
*/
snprintf(temp2, PATH_MAX -1, "%s/var/fdb/file%d.data", getenv("MBSE_ROOT"), fdb_area);
snprintf(temp1, PATH_MAX -1, "%s/var/fdb/file%d.xxxx", getenv("MBSE_ROOT"), fdb_area);
rename(temp2, temp1);
snprintf(temp1, PATH_MAX -1, "%s/var/fdb/file%d.temp", getenv("MBSE_ROOT"), fdb_area);
rename(temp1, temp2);
snprintf(temp1, PATH_MAX -1, "%s/var/fdb/file%d.xxxx", getenv("MBSE_ROOT"), fdb_area);
unlink(temp1);
free(temp1);
free(temp2);
return;
}
int mbsedb_InsertFDB(struct _fdbarea *fdb_area, struct FILE_record frec, int AddAlpha)
{
char *temp;
int i, Insert, Done = FALSE, Found = FALSE;
FILE *fp;
Syslog('f', "mbsedb_InsertFDB: \"%s\", magic \"%s\"", frec.LName, frec.Magic);
if (mbsedb_LockFDB(fdb_area, 30) == FALSE)
return FALSE;
fseek(fdb_area->fp, 0, SEEK_END);
if (ftell(fdb_area->fp) == fdbhdr.hdrsize) {
/*
* No records yet, simply append this first record.
*/
fwrite(&frec, fdbhdr.recsize, 1, fdb_area->fp);
mbsedb_UnlockFDB(fdb_area);
return TRUE;
}
/*
* There are files, search the insert point.
*/
temp = calloc(PATH_MAX, sizeof(char));
snprintf(temp, PATH_MAX -1, "%s/var/fdb/file%d.temp", getenv("MBSE_ROOT"), fdb_area->area);
fseek(fdb_area->fp, fdbhdr.hdrsize, SEEK_SET);
Insert = 0;
do {
if (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) != 1)
Done = TRUE;
if (!Done) {
if (strcmp(frec.LName, fdb.LName) == 0) {
Found = TRUE;
Insert++;
} else if (strcmp(frec.LName, fdb.LName) < 0)
Found = TRUE;
else
Insert++;
}
} while ((!Found) && (!Done));
if ((fp = fopen(temp, "a+")) == NULL) {
WriteError("$Can't create %s", temp);
mbsedb_UnlockFDB(fdb_area);
free(temp);
return FALSE;
}
fwrite(&fdbhdr, sizeof(fdbhdr), 1, fp);
fseek(fdb_area->fp, fdbhdr.hdrsize, SEEK_SET);
/*
* Copy entries untill the insert point.
*/
for (i = 0; i < Insert; i++) {
fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp);
/*
* If we see a magic that is the new magic, remove the old one.
*/
if (strlen(frec.Magic) && (strcmp(fdb.Magic, frec.Magic) == 0)) {
Syslog('f', "Clear magic %s file %s", fdb.Magic, fdb.LName);
memset(&fdb.Magic, 0, sizeof(fdb.Magic));
}
/*
* Check if we are importing a file with the same
* name, if so, don't copy the original database
* record. The file is also overwritten.
*/
if (strcmp(fdb.LName, frec.LName) != 0)
fwrite(&fdb, fdbhdr.recsize, 1, fp);
}
if (AddAlpha) {
/*
* Insert new entry
*/
fwrite(&frec, fdbhdr.recsize, 1, fp);
}
/*
* Append the rest of the entries
*/
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
/*
* If we see a magic that is the new magic, remove the old one.
*/
if (strlen(frec.Magic) && (strcmp(fdb.Magic, frec.Magic) == 0)) {
Syslog('f', "Clear magic %s file %s", fdb.Magic, fdb.LName);
memset(&fdb.Magic, 0, sizeof(fdb.Magic));
}
/*
* Check if we are importing a file with the same
* name, if so, don't copy the original database
* record. The file is also overwritten.
*/
if (strcmp(fdb.LName, frec.LName) != 0)
fwrite(&fdb, fdbhdr.recsize, 1, fp);
}
if (! AddAlpha) {
/*
* Append
*/
fwrite(&frec, fdbhdr.recsize, 1, fp);
}
fclose(fdb_area->fp);
mbsedb_Temp2Data(fdb_area->area);
fdb_area->fp = fp;
fdb_area->locked = 0;
free(temp);
return TRUE;
}
/*
* Return -1 if error, else number of purged records
*/
int mbsedb_PackFDB(struct _fdbarea *fdb_area)
{
char *temp;
FILE *fp;
int count = 0;
fseek(fdb_area->fp, 0, SEEK_END);
if (ftell(fdb_area->fp) == fdbhdr.hdrsize) {
return 0;
}
if (mbsedb_LockFDB(fdb_area, 30) == FALSE)
return -1;
/*
* There are files, copy the remaining entries
*/
temp = calloc(PATH_MAX, sizeof(char));
snprintf(temp, PATH_MAX -1, "%s/var/fdb/file%d.temp", getenv("MBSE_ROOT"), fdb_area->area);
if ((fp = fopen(temp, "a+")) == NULL) {
WriteError("$Can't create %s", temp);
mbsedb_UnlockFDB(fdb_area);
free(temp);
return -1;
}
fwrite(&fdbhdr, fdbhdr.hdrsize, 1, fp);
fseek(fdb_area->fp, fdbhdr.hdrsize, SEEK_SET);
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
if ((!fdb.Deleted) && (!fdb.Double) && (strcmp(fdb.Name, "") != 0))
fwrite(&fdb, fdbhdr.recsize, 1, fp);
else
count++;
}
fclose(fdb_area->fp);
mbsedb_Temp2Data(fdb_area->area);
fdb_area->fp = fp;
fdb_area->locked = 0;
free(temp);
return count;
}
typedef struct _fdbs {
struct _fdbs *next;
struct FILE_record filrec;
} fdbs;
void fill_fdbs(struct FILE_record, fdbs **);
void fill_fdbs(struct FILE_record filrec, fdbs **fap)
{
fdbs *tmp;
tmp = (fdbs *)malloc(sizeof(fdbs));
tmp->next = *fap;
tmp->filrec = filrec;
*fap = tmp;
}
void tidy_fdbs(fdbs **);
void tidy_fdbs(fdbs **fap)
{
fdbs *tmp, *old;
for (tmp = *fap; tmp; tmp = old) {
old = tmp->next;
free(tmp);
}
*fap = NULL;
}
int comp_fdbs(fdbs **, fdbs **);
void sort_fdbs(fdbs **);
void sort_fdbs(fdbs **fap)
{
fdbs *ta, **vector;
size_t n = 0, i;
if (*fap == NULL)
return;
for (ta = *fap; ta; ta = ta->next)
n++;
vector = (fdbs **)malloc(n * sizeof(fdbs *));
i = 0;
for (ta = *fap; ta; ta = ta->next)
vector[i++] = ta;
qsort(vector, n, sizeof(fdbs *), (int(*)(const void*, const void *))comp_fdbs);
(*fap) = vector[0];
i = 1;
for (ta = *fap; ta; ta = ta->next) {
if (i < n)
ta->next = vector[i++];
else
ta->next = NULL;
}
free(vector);
return;
}
int comp_fdbs(fdbs **fap1, fdbs **fap2)
{
return strcasecmp((*fap1)->filrec.LName, (*fap2)->filrec.LName);
}
/*
* Sort a files database using the long filenames.
*/
int mbsedb_SortFDB(struct _fdbarea *fdb_area)
{
fdbs *fdx = NULL, *tmp;
char *temp;
FILE *fp;
int count = 0;
fseek(fdb_area->fp, 0, SEEK_END);
if (ftell(fdb_area->fp) <= (fdbhdr.hdrsize + fdbhdr.recsize)) {
return 0;
}
fseek(fdb_area->fp, fdbhdr.hdrsize, SEEK_SET);
while (fread(&fdb, fdbhdr.recsize, 1, fdb_area->fp) == 1) {
fill_fdbs(fdb, &fdx);
}
sort_fdbs(&fdx);
/*
* Now the most timeconsuming part is done, lock the database and
* write the new sorted version.
*/
if (mbsedb_LockFDB(fdb_area, 30) == FALSE) {
tidy_fdbs(&fdx);
return -1;
}
temp = calloc(PATH_MAX, sizeof(char));
snprintf(temp, PATH_MAX -1, "%s/var/fdb/file%d.temp", getenv("MBSE_ROOT"), fdb_area->area);
if ((fp = fopen(temp, "a+")) == NULL) {
WriteError("$Can't create %s", temp);
mbsedb_UnlockFDB(fdb_area);
tidy_fdbs(&fdx);
free(temp);
return -1;
}
fwrite(&fdbhdr, fdbhdr.hdrsize, 1, fp);
/*
* Write sorted files to temp database
*/
for (tmp = fdx; tmp; tmp = tmp->next) {
fwrite(&tmp->filrec, fdbhdr.recsize, 1, fp);
count++;
}
tidy_fdbs(&fdx);
fclose(fdb_area->fp);
mbsedb_Temp2Data(fdb_area->area);
fdb_area->fp = fp;
fdb_area->locked = 0;
free(temp);
return count;
}

113
lib/dbftn.c Normal file
View File

@@ -0,0 +1,113 @@
/*****************************************************************************
*
* $Id: dbftn.c,v 1.8 2005/08/28 10:03:17 mbse Exp $
* Purpose ...............: Fidonetrecord Access
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
int InitFidonet(void)
{
FILE *fil;
memset(&fidonet, 0, sizeof(fidonet));
LoadConfig();
snprintf(fidonet_fil, PATH_MAX -1, "%s/etc/fidonet.data", getenv("MBSE_ROOT"));
if ((fil = fopen(fidonet_fil, "r")) == NULL)
return FALSE;
fread(&fidonethdr, sizeof(fidonethdr), 1, fil);
fseek(fil, 0, SEEK_END);
fidonet_cnt = (ftell(fil) - fidonethdr.hdrsize) / fidonethdr.recsize;
fclose(fil);
return TRUE;
}
int TestFidonet(unsigned short zone)
{
int i, ftnok = FALSE;
for (i = 0; i < 6; i++) {
if (zone == fidonet.zone[i])
ftnok = TRUE;
}
return(ftnok);
}
int SearchFidonet(unsigned short zone)
{
FILE *fil;
/*
* If current record is ok, return immediatly.
*/
if (TestFidonet(zone))
return TRUE;
if ((fil = fopen(fidonet_fil, "r")) == NULL) {
return FALSE;
}
fread(&fidonethdr, sizeof(fidonethdr), 1, fil);
while (fread(&fidonet, fidonethdr.recsize, 1, fil) == 1) {
if (TestFidonet(zone)) {
fclose(fil);
return TRUE;
}
}
fclose(fil);
return FALSE;
}
char *GetFidoDomain(unsigned short zone)
{
static char domain[9];
memset(&domain, 0, sizeof(domain));
if (SearchFidonet(zone) == FALSE)
return NULL;
strncpy(domain, fidonet.domain, 8);
return domain;
}

364
lib/dbmsgs.c Normal file
View File

@@ -0,0 +1,364 @@
/*****************************************************************************
*
* $Id: dbmsgs.c,v 1.11 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Message areas record Access
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
char msgs_fil[PATH_MAX]; /* Database filename */
char mgrp_fil[PATH_MAX]; /* Group database filename */
int msgs_pos = -1; /* Current record position */
int mgrp_pos = -1; /* Current group position */
unsigned int msgs_crc = -1; /* CRC value of current record */
unsigned int mgrp_crc = -1; /* CRC value of group record */
static int sysstart, sysrecord;
int InitMsgs(void)
{
FILE *fil;
memset(&msgs, 0, sizeof(msgs));
memset(&mgroup, 0, sizeof(mgroup));
LoadConfig();
sysstart = -1;
snprintf(msgs_fil, PATH_MAX -1, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
if ((fil = fopen(msgs_fil, "r")) == NULL)
return FALSE;
fread(&msgshdr, sizeof(msgshdr), 1, fil);
fseek(fil, 0, SEEK_END);
msgs_cnt = (ftell(fil) - msgshdr.hdrsize) / (msgshdr.recsize + msgshdr.syssize);
fclose(fil);
snprintf(mgrp_fil, PATH_MAX -1, "%s/etc/mgroups.data", getenv("MBSE_ROOT"));
return TRUE;
}
int smsgarea(char *, int, int);
int smsgarea(char *what, int newsgroup, int bad)
{
FILE *fil;
if ((fil = fopen(msgs_fil, "r")) == NULL) {
return FALSE;
}
fread(&msgshdr, sizeof(msgshdr), 1, fil);
while (fread(&msgs, msgshdr.recsize, 1, fil) == 1) {
/*
* Mark the start of the connected systems records
* for later use and skip the system records.
*/
msgs_pos = ftell(fil) - msgshdr.recsize;
sysstart = ftell(fil);
fseek(fil, msgshdr.syssize, SEEK_CUR);
if (((!strcasecmp(what, msgs.Tag) && !newsgroup && !bad) ||
(!strcmp(what, msgs.Newsgroup) && newsgroup && !bad) ||
(!strcmp(CFG.badboard, msgs.Base) && bad)) && msgs.Active) {
sysrecord = 0;
fclose(fil);
msgs_crc = 0xffffffff;
msgs_crc = upd_crc32((char *)&msgs, msgs_crc, msgshdr.recsize);
mgrp_pos = -1;
mgrp_crc = -1;
if (strlen(msgs.Group)) {
if ((fil = fopen(mgrp_fil, "r")) != NULL) {
fread(&mgrouphdr, sizeof(mgrouphdr), 1, fil);
while ((fread(&mgroup, mgrouphdr.recsize, 1, fil)) == 1) {
if (!strcmp(msgs.Group, mgroup.Name)) {
mgrp_pos = ftell(fil) - mgrouphdr.recsize;
mgrp_crc = 0xffffffff;
mgrp_crc = upd_crc32((char *)&mgroup, mgrp_crc, mgrouphdr.recsize);
break;
}
}
fclose(fil);
}
} else
memset(&mgroup, 0, sizeof(mgroup));
return TRUE;
}
}
sysstart = -1;
msgs_crc = -1;
msgs_pos = -1;
fclose(fil);
return FALSE;
}
int SearchMsgs(char *Area)
{
return smsgarea(Area, FALSE, FALSE);
}
int SearchMsgsNews(char *Group)
{
return smsgarea(Group, TRUE, FALSE);
}
int SearchBadBoard(void)
{
return smsgarea((char *)"xXxX", FALSE, TRUE);
}
/*
* Check if system is connected
*/
int MsgSystemConnected(sysconnect Sys)
{
FILE *fil;
sysconnect T;
if (sysstart == -1)
return FALSE;
if ((fil = fopen(msgs_fil, "r")) == NULL)
return FALSE;
if (fseek(fil, sysstart, SEEK_SET) != 0) {
fclose(fil);
return FALSE;
}
while (ftell(fil) != (sysstart + msgshdr.syssize)) {
fread(&T, sizeof(sysconnect), 1, fil);
if ((T.aka.zone == Sys.aka.zone) &&
(T.aka.net == Sys.aka.net) &&
(T.aka.node == Sys.aka.node) &&
(T.aka.point == Sys.aka.point)) {
fclose(fil);
return TRUE;
}
}
fclose(fil);
return FALSE;
}
/*
* Change system's status, if the Read or Write flags are clear,
* the connection will be erased, else updated or connected.
*/
int MsgSystemConnect(sysconnect *Sys, int New)
{
FILE *fil;
sysconnect T;
if (sysstart == -1)
return FALSE;
if ((fil = fopen(msgs_fil, "r+")) == NULL)
return FALSE;
if (fseek(fil, sysstart, SEEK_SET) != 0) {
fclose(fil);
return FALSE;
}
while (ftell(fil) != (sysstart + msgshdr.syssize)) {
fread(&T, sizeof(sysconnect), 1, fil);
/*
* For a new connection, search an empty slot.
*/
if (New && (!T.aka.zone)) {
fseek(fil, - sizeof(sysconnect), SEEK_CUR);
fwrite(Sys, sizeof(sysconnect), 1, fil);
fclose(fil);
return TRUE;
}
/*
* If not new it is an update
*/
if ((!New) && (T.aka.zone == Sys->aka.zone) &&
(T.aka.net == Sys->aka.net) && (T.aka.node == Sys->aka.node) &&
(T.aka.point == Sys->aka.point)) {
fseek(fil, - sizeof(sysconnect), SEEK_CUR);
if ((!Sys->sendto) && (!Sys->receivefrom)) {
/*
* It's a deletion, if the area is mandatory or
* the node is cutoff, refuse the deletion.
*/
if (msgs.Mandatory || T.cutoff) {
fclose(fil);
return FALSE;
}
memset(&T, 0, sizeof(sysconnect));
fwrite(&T, sizeof(sysconnect), 1, fil);
} else {
/*
* It's a update, refuse it if the node is cutoff.
*/
if (T.cutoff) {
fclose(fil);
return FALSE;
}
fwrite(Sys, sizeof(sysconnect), 1, fil);
}
fclose(fil);
return TRUE;
}
}
fclose(fil);
return FALSE;
}
int GetMsgSystem(sysconnect * Sys, int First)
{
FILE *fil;
memset(Sys, 0, sizeof(sysconnect));
if (sysstart == -1)
return FALSE;
if (First)
sysrecord = 0;
else
sysrecord++;
if (sysrecord >= CFG.toss_systems)
return FALSE;
if ((fil = fopen(msgs_fil, "r")) == NULL)
return FALSE;
if (fseek(fil, sysstart + (sysrecord * sizeof(sysconnect)), SEEK_SET) != 0) {
fclose(fil);
return FALSE;
}
if (fread(Sys, sizeof(sysconnect), 1, fil) == 1) {
fclose(fil);
return TRUE;
}
fclose(fil);
return FALSE;
}
int SearchNetBoard(unsigned short zone, unsigned short net)
{
FILE *fil;
mgrp_pos = -1;
mgrp_crc = -1;
if ((fil = fopen(msgs_fil, "r")) == NULL) {
return FALSE;
}
fread(&msgshdr, sizeof(msgshdr), 1, fil);
while (fread(&msgs, msgshdr.recsize, 1, fil) == 1) {
fseek(fil, msgshdr.syssize, SEEK_CUR);
if ((msgs.Type == NETMAIL) && (msgs.Active) &&
(zone == msgs.Aka.zone) && (net == msgs.Aka.net)) {
msgs_pos = ftell(fil) - (msgshdr.recsize + msgshdr.syssize);
msgs_crc = 0xffffffff;
msgs_crc = upd_crc32((char *)&msgs, msgs_crc, msgshdr.recsize);
fclose(fil);
return TRUE;
}
}
fclose(fil);
msgs_pos = -1;
msgs_crc = -1;
sysstart = -1;
return FALSE;
}
void UpdateMsgs()
{
unsigned int crc = 0xffffffff;
FILE *fil;
if (msgs_pos == -1)
return;
crc = upd_crc32((char *)&msgs, crc, msgshdr.recsize);
if (crc != msgs_crc) {
if ((fil = fopen(msgs_fil, "r+")) == NULL) {
msgs_pos = -1;
return;
}
fseek(fil, msgs_pos, SEEK_SET);
fwrite(&msgs, msgshdr.recsize, 1, fil);
fclose(fil);
}
msgs_pos = -1;
msgs_crc = -1;
if (mgrp_pos == -1)
return;
crc = 0xffffffff;
crc = upd_crc32((char *)&mgroup, crc, mgrouphdr.recsize);
if (crc != mgrp_crc) {
if ((fil = fopen(mgrp_fil, "r+")) == NULL) {
mgrp_pos = -1;
return;
}
fseek(fil, mgrp_pos, SEEK_SET);
fwrite(&mgroup, mgrouphdr.recsize, 1, fil);
fclose(fil);
}
mgrp_pos = -1;
mgrp_crc = -1;
}

219
lib/dbnode.c Normal file
View File

@@ -0,0 +1,219 @@
/*****************************************************************************
*
* $Id: dbnode.c,v 1.10 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Noderecord Access
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
char nodes_fil[PATH_MAX]; /* Nodes database filename */
int nodes_pos = -1; /* Noderecord position */
int nodes_fgp = -1; /* Nodes files group position */
int nodes_mgp = -1; /* Nodes message group position */
unsigned int nodes_crc = -1; /* Noderecord crc value */
int InitNode(void)
{
FILE *fil;
memset(&nodes, 0, sizeof(nodes));
LoadConfig();
snprintf(nodes_fil, PATH_MAX -1, "%s/etc/nodes.data", getenv("MBSE_ROOT"));
if ((fil = fopen(nodes_fil, "r")) == NULL)
return FALSE;
fread(&nodeshdr, sizeof(nodeshdr), 1, fil);
fseek(fil, 0, SEEK_END);
nodes_cnt = (ftell(fil) - nodeshdr.hdrsize) / (nodeshdr.recsize + nodeshdr.filegrp + nodeshdr.mailgrp);
fclose(fil);
return TRUE;
}
int TestNode(fidoaddr aka)
{
int i, nodeok = FALSE;
for (i = 0; i < 20; i++) {
if (((aka.zone == 0) || (aka.zone == nodes.Aka[i].zone)) &&
(aka.net == nodes.Aka[i].net) &&
(aka.node == nodes.Aka[i].node) &&
(aka.point == nodes.Aka[i].point))
nodeok = TRUE;
}
return(nodeok);
}
int SearchNodeFaddr(faddr *n)
{
fidoaddr Sys;
memset(&Sys, 0, sizeof(Sys));
Sys.zone = n->zone;
Sys.net = n->net;
Sys.node = n->node;
Sys.point = n->point;
if (n->domain != NULL)
strncpy(Sys.domain, n->domain, 12);
return SearchNode(Sys);
}
int SearchNode(fidoaddr aka)
{
FILE *fil;
nodes_pos = -1;
nodes_crc = -1;
if ((fil = fopen(nodes_fil, "r")) == NULL)
return FALSE;
fread(&nodeshdr, sizeof(nodeshdr), 1, fil);
while (fread(&nodes, nodeshdr.recsize, 1, fil) == 1) {
fseek(fil, nodeshdr.filegrp + nodeshdr.mailgrp, SEEK_CUR);
if (TestNode(aka)) {
nodes_pos = ftell(fil) - (nodeshdr.recsize + nodeshdr.filegrp + nodeshdr.mailgrp);
fclose(fil);
nodes_crc = 0xffffffff;
nodes_crc = upd_crc32((char *)&nodes, nodes_crc, nodeshdr.recsize);
return TRUE;
}
}
memset(&nodes, 0, sizeof(nodes));
fclose(fil);
return FALSE;
}
/*
* Update current noderecord if changed.
*/
int UpdateNode()
{
unsigned int crc;
FILE *fil;
if (nodes_pos == -1)
return FALSE;
crc = 0xffffffff;
crc = upd_crc32((char *)&nodes, crc, nodeshdr.recsize);
if (crc != nodes_crc) {
if ((fil = fopen(nodes_fil, "r+")) == NULL)
return FALSE;
fseek(fil, nodes_pos, SEEK_SET);
fwrite(&nodes, nodeshdr.recsize, 1, fil);
fclose(fil);
}
nodes_crc = -1;
nodes_pos = -1;
memset(&nodes, 0, sizeof(nodes));
return TRUE;
}
char *GetNodeMailGrp(int First)
{
FILE *fil;
char group[13], *gr;
if (nodes_pos == -1)
return NULL;
if (First)
nodes_mgp = nodes_pos + nodeshdr.recsize + nodeshdr.filegrp;
if (nodes_mgp > (nodes_pos + nodeshdr.recsize + nodeshdr.filegrp + nodeshdr.mailgrp))
return NULL;
if ((fil = fopen(nodes_fil, "r")) == NULL)
return NULL;
fseek(fil, nodes_mgp, SEEK_SET);
fread(&group, sizeof(group), 1, fil);
fclose(fil);
nodes_mgp += sizeof(group);
if (group[0] == '\0')
return NULL;
gr = xstrcpy(group);
return gr;
}
char *GetNodeFileGrp(int First)
{
FILE *fil;
char group[13], *gr;
if (nodes_pos == -1)
return NULL;
if (First)
nodes_fgp = nodes_pos + nodeshdr.recsize;
if (nodes_fgp > (nodes_pos + nodeshdr.recsize + nodeshdr.filegrp))
return NULL;
if ((fil = fopen(nodes_fil, "r")) == NULL)
return NULL;
fseek(fil, nodes_fgp, SEEK_SET);
fread(&group, sizeof(group), 1, fil);
fclose(fil);
nodes_fgp += sizeof(group);
if (group[0] == '\0')
return NULL;
gr = xstrcpy(group);
return gr;
}

303
lib/dbtic.c Normal file
View File

@@ -0,0 +1,303 @@
/*****************************************************************************
*
* $Id: dbtic.c,v 1.9 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Tic areas record Access
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
char tic_fil[PATH_MAX]; /* Database filename */
char tgrp_fil[PATH_MAX]; /* Group database filename */
int tic_pos = -1; /* Current record position */
int tgrp_pos = -1; /* Current group position */
unsigned int tic_crc = -1; /* CRC value of current record */
unsigned int tgrp_crc = -1; /* CRC value of group record */
static int sysstart, sysrecord;
int InitTic(void)
{
FILE *fil;
memset(&tic, 0, sizeof(tic));
memset(&fgroup, 0, sizeof(fgroup));
LoadConfig();
sysstart = -1;
snprintf(tic_fil, PATH_MAX -1, "%s/etc/tic.data", getenv("MBSE_ROOT"));
if ((fil = fopen(tic_fil, "r")) == NULL)
return FALSE;
fread(&tichdr, sizeof(tichdr), 1, fil);
fseek(fil, 0, SEEK_END);
tic_cnt = (ftell(fil) - tichdr.hdrsize) / (tichdr.recsize + tichdr.syssize);
fclose(fil);
snprintf(tgrp_fil, PATH_MAX -1, "%s/etc/fgroups.data", getenv("MBSE_ROOT"));
return TRUE;
}
int SearchTic(char *Area)
{
FILE *fil;
if ((fil = fopen(tic_fil, "r")) == NULL) {
return FALSE;
}
fread(&tichdr, sizeof(tichdr), 1, fil);
while (fread(&tic, tichdr.recsize, 1, fil) == 1) {
/*
* Mark the start of the connected systems records
* for later use and skip the system records.
*/
tic_pos = ftell(fil) - tichdr.recsize;
sysstart = ftell(fil);
fseek(fil, tichdr.syssize, SEEK_CUR);
if (!strcasecmp(Area, tic.Name) && tic.Active) {
sysrecord = 0;
fclose(fil);
tic_crc = 0xffffffff;
tic_crc = upd_crc32((char *)&tic, tic_crc, tichdr.recsize);
tgrp_pos = -1;
tgrp_crc = -1;
if (strlen(tic.Group)) {
if ((fil = fopen(tgrp_fil, "r")) != NULL) {
fread(&fgrouphdr, sizeof(fgrouphdr), 1, fil);
while ((fread(&fgroup, fgrouphdr.recsize, 1, fil)) == 1) {
if (!strcmp(tic.Group, fgroup.Name)) {
tgrp_pos = ftell(fil) - fgrouphdr.recsize;
tgrp_crc = 0xffffffff;
tgrp_crc = upd_crc32((char *)&fgroup, tgrp_crc, fgrouphdr.recsize);
break;
}
}
fclose(fil);
}
} else
memset(&fgroup, 0, sizeof(fgroup));
return TRUE;
}
}
sysstart = -1;
tic_crc = -1;
tic_pos = -1;
fclose(fil);
return FALSE;
}
/*
* Check if system is connected
*/
int TicSystemConnected(sysconnect Sys)
{
FILE *fil;
sysconnect T;
if (sysstart == -1)
return FALSE;
if ((fil = fopen(tic_fil, "r")) == NULL)
return FALSE;
if (fseek(fil, sysstart, SEEK_SET) != 0) {
fclose(fil);
return FALSE;
}
while (ftell(fil) != (sysstart + tichdr.syssize)) {
fread(&T, sizeof(sysconnect), 1, fil);
if ((T.aka.zone == Sys.aka.zone) &&
(T.aka.net == Sys.aka.net) &&
(T.aka.node == Sys.aka.node) &&
(T.aka.point == Sys.aka.point)) {
fclose(fil);
return TRUE;
}
}
fclose(fil);
return FALSE;
}
/*
* Change the system's status, if the Read and Write flags are clear,
* the connection will be erased, else updated or connected.
*/
int TicSystemConnect(sysconnect *Sys, int New)
{
FILE *fil;
sysconnect T;
if (sysstart == -1)
return FALSE;
if ((fil = fopen(tic_fil, "r+")) == NULL)
return FALSE;
if (fseek(fil, sysstart, SEEK_SET) != 0) {
fclose(fil);
return FALSE;
}
while (ftell(fil) != (sysstart + tichdr.syssize)) {
fread(&T, sizeof(sysconnect), 1, fil);
/*
* For a new connection, search an empty slot.
*/
if (New && (!T.aka.zone)) {
fseek(fil, - sizeof(sysconnect), SEEK_CUR);
fwrite(Sys, sizeof(sysconnect), 1, fil);
fclose(fil);
return TRUE;
}
/*
* If not new it is an update
*/
if ((!New) && (T.aka.zone == Sys->aka.zone) &&
(T.aka.node == Sys->aka.node) &&
(T.aka.net == Sys->aka.net) &&
(T.aka.point == Sys->aka.point)) {
fseek(fil, - sizeof(sysconnect), SEEK_CUR);
if ((!Sys->sendto) && (!Sys->receivefrom)) {
/*
* It's a deletion
*/
if (tic.Mandat) {
fclose(fil);
return FALSE;
}
memset(&T, 0, sizeof(sysconnect));
fwrite(&T, sizeof(sysconnect), 1, fil);
} else {
/*
* It's a update
*/
fwrite(Sys, sizeof(sysconnect), 1, fil);
}
fclose(fil);
return TRUE;
}
}
fclose(fil);
return FALSE;
}
int GetTicSystem(sysconnect * Sys, int First)
{
FILE *fil;
memset(Sys, 0, sizeof(sysconnect));
if (sysstart == -1)
return FALSE;
if (First)
sysrecord = 0;
else
sysrecord++;
if (sysrecord >= CFG.tic_systems)
return FALSE;
if ((fil = fopen(tic_fil, "r")) == NULL)
return FALSE;
if (fseek(fil, sysstart + (sysrecord * sizeof(sysconnect)), SEEK_SET) != 0) {
fclose(fil);
return FALSE;
}
if (fread(Sys, sizeof(sysconnect), 1, fil) == 1) {
fclose(fil);
return TRUE;
}
fclose(fil);
return FALSE;
}
void UpdateTic()
{
unsigned int crc = 0xffffffff;
FILE *fil;
if (tic_pos == -1)
return;
crc = upd_crc32((char *)&tic, crc, tichdr.recsize);
if (crc != tic_crc) {
if ((fil = fopen(tic_fil, "r+")) == NULL) {
tic_pos = -1;
return;
}
fseek(fil, tic_pos, SEEK_SET);
fwrite(&tic, tichdr.recsize, 1, fil);
fclose(fil);
}
tic_pos = -1;
tic_crc = -1;
if (tgrp_pos == -1)
return;
crc = 0xffffffff;
crc = upd_crc32((char *)&fgroup, crc, fgrouphdr.recsize);
if (crc != tgrp_crc) {
if ((fil = fopen(tgrp_fil, "r+")) == NULL) {
tgrp_pos = -1;
return;
}
fseek(fil, tgrp_pos, SEEK_SET);
fwrite(&fgroup, fgrouphdr.recsize, 1, fil);
fclose(fil);
}
tgrp_pos = -1;
tgrp_crc = -1;
}

99
lib/dbuser.c Normal file
View File

@@ -0,0 +1,99 @@
/*****************************************************************************
*
* $Id: dbuser.c,v 1.8 2005/08/28 10:03:17 mbse Exp $
* Purpose ...............: Userrecord Access
*
*****************************************************************************
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
int InitUser(void)
{
FILE *fil;
memset(&usr, 0, sizeof(usr));
LoadConfig();
snprintf(usr_fil, PATH_MAX -1, "%s/etc/users.data", getenv("MBSE_ROOT"));
if ((fil = fopen(usr_fil, "r")) == NULL)
return FALSE;
fread(&usrhdr, sizeof(usrhdr), 1, fil);
fseek(fil, 0, SEEK_END);
usr_cnt = (ftell(fil) - usrhdr.hdrsize) / usrhdr.recsize;
fclose(fil);
return TRUE;
}
int TestUser(char *Name)
{
int userok = FALSE;
if ((strcasecmp(usr.sUserName, Name) == 0) ||
((strlen(usr.sHandle) > 0) && (strcasecmp(usr.sHandle, Name) == 0)) ||
(strcmp(usr.Name, Name) == 0)) {
if (!usr.Deleted)
userok = TRUE;
}
return(userok);
}
int SearchUser(char *Name)
{
FILE *fil;
/*
* Allways reread the users file.
*/
if ((fil = fopen(usr_fil, "r")) == NULL) {
memset(&usr, 0, sizeof(usr));
return FALSE;
}
fread(&usrhdr, sizeof(usrhdr), 1, fil);
while (fread(&usr, usrhdr.recsize, 1, fil) == 1) {
if (TestUser(Name)) {
fclose(fil);
return TRUE;
}
}
fclose(fil);
return FALSE;
}

1795
lib/diesel.c Normal file

File diff suppressed because it is too large Load Diff

57
lib/diesel.h Normal file
View File

@@ -0,0 +1,57 @@
/* $Id: diesel.h,v 1.7 2007/02/26 21:02:30 mbse Exp $ */
#ifndef _DIESEL_H
#define _DIESEL_H
#define UNIXTENSIONS
#define VARIABLES
#define FALSE 0
#define TRUE 1
#define DIAGNOSTIC 2
#define EOS '\0'
#define V (void)
/* Globals exported */
#ifdef DIESEL_TRACE
int tracing = TRUE; /* Trace macro evalution */
#endif
/* Local variables. */
#define MAXARGS 10 /* Maximum arguments to a macro */
#define MAXSTR 19200 /* Maximum string length */ /* Was 2560 */ /* Size full UTF-8 code filesdesc */
#define MAXDEPTH 32 /* Maximum recursion depth for eval */
#define MACROCHAR '@' /* Macro trigger character */
#define ARGOPEN '(' /* Argument open bracket */
#define ARGCLOSE ')' /* Argument close bracket */
#define ARGSEP ',' /* Argument separator character */
#define QUOTE '"' /* Literal string quote character */
#define CASEINS /* Case-insensitive function names */
#define STRLIMIT (MAXSTR - 20) /* String output length limit */
#define OverFlow " @(++)" /* Glyph indicating string overflow */
#define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
#define FUZZEQ(a, b) ((((a) < (b)) ? ((b) - (a)) : ((a) - (b))) < 1E-10)
int diesel(char *, char *);
/*
* MBSE BBS specific functions
*/
char *ParseMacro( const char *, int * );
void MacroVars( const char *, const char *, ... );
void MacroClear(void);
void html_massage(char *, char *, size_t);
FILE *OpenMacro(const char *, int, int);
#endif

93
lib/dostran.c Normal file
View File

@@ -0,0 +1,93 @@
/*****************************************************************************
*
* $Id: dostran.c,v 1.7 2005/08/28 09:42:09 mbse Exp $
* Purpose ...............: DOS to Unix filename translation
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
char *Dos2Unix(char *dosname)
{
char buf[PATH_MAX];
static char buf2[PATH_MAX];
char *p, *q;
memset(&buf, 0, sizeof(buf));
memset(&buf2, 0, sizeof(buf2));
snprintf(buf, PATH_MAX -1, "%s", dosname);
p = buf;
if (strlen(CFG.dospath)) {
if (strncasecmp(p, CFG.dospath, strlen(CFG.dospath)) == 0) {
strcpy((char *)buf2, CFG.uxpath);
for (p+=strlen(CFG.dospath), q = buf2 + strlen(buf2); *p; p++, q++)
*q = ((*p) == '\\')?'/':tolower(*p);
*q = '\0';
p = buf2;
} else {
if (strncasecmp(p, CFG.uxpath, strlen(CFG.uxpath)) == 0) {
for (p+=strlen(CFG.uxpath), q = buf2 + strlen(buf2); *p; p++, q++)
*q = ((*p) == '\\')?'/':tolower(*p);
*q = '\0';
p = buf2;
}
}
}
return buf2;
}
char *Unix2Dos(char *uxname)
{
char *q;
static char buf[PATH_MAX];
memset(&buf, 0, sizeof(buf));
if (strlen(CFG.dospath)) {
snprintf(buf, PATH_MAX -1, "%s", CFG.dospath);
if (*(CFG.dospath+strlen(CFG.dospath)-1) != '\\')
buf[strlen(buf)] = '\\';
if (*(q=uxname+strlen(CFG.uxpath)) == '/')
q++;
for (; *q; q++)
buf[strlen(buf)] = (*q == '/')?'\\':*q;
} else {
snprintf(buf, PATH_MAX -1, "%s", uxname);
}
return buf;
}

59
lib/endian.c Normal file
View File

@@ -0,0 +1,59 @@
/*****************************************************************************
*
* $Id: endian.c,v 1.6 2006/01/22 19:52:33 mbse Exp $
* Purpose ...............: Change integer value CPU endian independant
*
*****************************************************************************
* 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "mbselib.h"
/*
* Return an integer in endian independent format. This is used to make menu
* files portable on little and big-endian systems. Normal datafiles are
* not portable, only the menus.
*/
int le_int(int val)
{
#ifdef WORDS_BIGENDIAN
return ((val & 0xff) << 24) | (((val >> 8) & 0xff) << 16) | (((val >> 16) & 0xff) << 8) | ((val >> 24) & 0xff);
#else
return val;
#endif
}
unsigned short le_us(unsigned short val)
{
#ifdef WORDS_BIGENDIAN
return ((val & 0xff) << 8) | ((val >> 8) & 0xff);
#else
return val;
#endif
}

301
lib/execute.c Normal file
View File

@@ -0,0 +1,301 @@
/*****************************************************************************
*
* $Id: execute.c,v 1.24 2008/02/23 21:50:41 mbse Exp $
* Purpose ...............: Execute subprogram
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
int e_pid = 0; /* Execute child pid */
int _execute(char **, char *, char *, char *);
int _execute(char **args, char *in, char *out, char *err)
{
char buf[PATH_MAX];
int i, pid, status = 0, rc = 0;
memset(&buf, 0, sizeof(buf));
for (i = 0; i < 16; i++) {
if (args[i])
snprintf(buf + strlen(buf), PATH_MAX - strlen(buf), " %s", args[i]);
else
break;
}
Syslog('+', "Execute:%s",buf);
fflush(stdout);
fflush(stderr);
if ((pid = fork()) == 0) {
/*
* A delay in the child to prevent it returns before the main
* process sees it ever started.
*/
msleep(150);
if (in) {
close(0);
if (open(in,O_RDONLY) != 0) {
WriteError("$Reopen of stdin to %s failed", MBSE_SS(in));
exit(MBERR_EXEC_FAILED);
}
}
if (out) {
close(1);
if (open(out,O_WRONLY | O_APPEND | O_CREAT,0600) != 1) {
WriteError("$Reopen of stdout to %s failed", MBSE_SS(out));
exit(MBERR_EXEC_FAILED);
}
}
if (err) {
close(2);
if (open(err,O_WRONLY | O_APPEND | O_CREAT,0600) != 2) {
WriteError("$Reopen of stderr to %s failed", MBSE_SS(err));
exit(MBERR_EXEC_FAILED);
}
}
errno = 0;
if (CFG.priority) {
rc = getpriority(PRIO_PROCESS, 0);
if (errno == 0) {
rc = setpriority(PRIO_PROCESS, 0, CFG.priority);
if (rc)
WriteError("$execv can't set priority to %d", CFG.priority);
}
}
rc = execv(args[0],args);
WriteError("$execv \"%s\" returned %d", MBSE_SS(args[0]), rc);
exit(MBERR_EXEC_FAILED);
}
e_pid = pid;
do {
rc = wait(&status);
e_pid = 0;
} while (((rc > 0) && (rc != pid)) || ((rc == -1) && (errno == EINTR)));
switch (rc) {
case -1:
if (errno == ECHILD) {
Syslog('+', "Execute: no child process");
return 0;
} else {
WriteError("$Wait returned %d, status %d,%d", rc,status>>8,status&0xff);
return -1;
}
case 0:
return 0;
default:
if (WIFEXITED(status)) {
rc = WEXITSTATUS(status);
if (rc) {
if ((strstr(args[0], (char *)"unzip") == NULL) || (rc != 11)) {
WriteError("Execute: returned error %d", rc);
}
return (rc + MBERR_EXTERNAL);
}
}
if (WIFSIGNALED(status)) {
rc = WTERMSIG(status);
WriteError("Wait stopped on signal %d", rc);
return rc;
}
if (rc)
WriteError("Wait stopped unknown, rc=%d", rc);
return rc;
}
return 0;
}
int execute(char **args, char *in, char *out, char *err)
{
int rc;
if (CFG.do_sync)
sync();
rc = _execute(args, in, out, err);
if (CFG.do_sync)
sync();
return rc;
}
/*
* The old behaviour, parse command strings to arguments.
*/
int execute_str(char *cmd, char *fil, char *pkt, char *in, char *out, char *err)
{
int i;
char *args[16], buf[PATH_MAX];
memset(args, 0, sizeof(args));
memset(&buf, 0, sizeof(buf));
i = 0;
if ((pkt != NULL) && strlen(pkt))
snprintf(buf, PATH_MAX -1, "%s %s %s", cmd, fil, pkt);
else
snprintf(buf, PATH_MAX -1, "%s %s", cmd, fil);
args[i++] = strtok(buf, " \t\0");
while ((args[i++] = strtok(NULL," \t\n")) && (i < 15));
args[i++] = NULL;
return execute(args, in, out, err);
}
/*
* Execute command in the PATH.
*/
int execute_pth(char *prog, char *opts, char *in, char *out, char *err)
{
char *pth;
int rc;
if (strchr(prog, ' ') || strchr(prog, '/')) {
WriteError("First parameter of execute_pth() must be a program name");
return -1;
}
pth = xstrcpy((char *)"/usr/bin/");
pth = xstrcat(pth, prog);
if (access(pth, X_OK) == -1) {
free(pth);
pth = xstrcpy((char *)"/usr/local/bin/");
pth = xstrcat(pth, prog);
if (access(pth, X_OK) == -1) {
free(pth);
pth = xstrcpy((char *)"/bin/");
pth = xstrcat(pth, prog);
if (access(pth, X_OK) == -1) {
free(pth);
pth = xstrcpy((char *)"/usr/pkg/bin/");
pth = xstrcat(pth, prog);
if (access(pth, X_OK) == -1) {
WriteError("Can't find %s", prog);
free(pth);
return -1;
}
}
}
}
rc = execute_str(pth, opts, NULL, in, out, err);
free(pth);
return rc;
}
#define SHELL "/bin/sh"
int _execsh(char *, char *, char *, char *);
int _execsh(char *cmd, char *in, char *out, char *err)
{
int pid, status, rc, sverr;
Syslog('+', "Execute shell: %s", MBSE_SS(cmd));
fflush(stdout);
fflush(stderr);
if ((pid = fork()) == 0) {
/*
* A delay in the child to prevent it returns before the main
* process sess it ever started.
*/
msleep(150);
if (in) {
close(0);
if (open(in, O_RDONLY) != 0) {
WriteError("$Reopen of stdin to %s failed",MBSE_SS(in));
exit(MBERR_EXEC_FAILED);
}
}
if (out) {
close(1);
if (open(out, O_WRONLY | O_APPEND | O_CREAT,0600) != 1) {
WriteError("$Reopen of stdout to %s failed",MBSE_SS(out));
exit(MBERR_EXEC_FAILED);
}
}
if (err) {
close(2);
if (open(err, O_WRONLY | O_APPEND | O_CREAT,0600) != 2) {
WriteError("$Reopen of stderr to %s failed",MBSE_SS(err));
exit(MBERR_EXEC_FAILED);
}
}
rc = execl(SHELL, "sh", "-c", cmd, NULL);
WriteError("$execl \"%s\" returned %d", MBSE_SS(cmd), rc);
exit(MBERR_EXEC_FAILED);
}
e_pid = pid;
do {
rc = wait(&status);
e_pid = 0;
sverr = errno;
if (status)
WriteError("$Wait returned %d, status %d,%d", rc, status >> 8, status & 0xff);
}
while (((rc > 0) && (rc != pid)) || ((rc == -1) && (sverr == EINTR)));
if (rc == -1) {
WriteError("$Wait returned %d, status %d,%d", rc, status >> 8, status & 0xff);
return 0;
}
return status;
}
int execsh(char *cmd, char *in, char *out, char *err)
{
int rc;
if (CFG.do_sync)
sync();
rc = _execsh(cmd, in, out, err);
if (CFG.do_sync)
sync();
return rc;
}

187
lib/expipe.c Normal file
View File

@@ -0,0 +1,187 @@
/*****************************************************************************
*
* $Id: expipe.c,v 1.7 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: MBSE BBS Execute pipe
*
*****************************************************************************
* 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 "mbselib.h"
static struct _fppid {
FILE *fp;
int pid;
} fppid[] = {
{NULL, 0}, {NULL, 0}, {NULL, 0}
};
#define maxfppid 2
FILE *expipe(char *cmd, char *from, char *to)
{
char buf[256], *buflimit, *vector[16], *p, *q, *f=from, *t=to;
FILE *fp;
int i, rc, pid, slot, pipedes[2];
buflimit = buf + sizeof(buf) -1 - (f&&t&&(strlen(f)>strlen(t))?strlen(f):t?strlen(t):0);
for (slot = 0; slot <= maxfppid; slot++) {
if (fppid[slot].fp == NULL)
break;
}
if (slot > maxfppid) {
WriteError("Attempt to pipe more than %d processes", maxfppid + 1);
return NULL;
}
for (p = cmd, q = buf; (*p); p++) {
if (q > buflimit) {
WriteError("Attempt to pipe too long command");
return NULL;
}
switch (*p) {
case '$': switch (*(++p)) {
case 'f':
case 'F': if ((f))
while (*f)
*(q++) = *(f++);
f=from;
break;
case 't':
case 'T': if ((t))
while (*t)
*(q++) = *(t++);
t=to;
break;
default: *(q++)='$';
*(q++)=*p;
break;
}
break;
case '\\': *(q++) = *(++p);
break;
default: *(q++) = *p;
break;
}
}
*q = '\0';
Syslog('+', "Expipe: %s",buf);
i = 0;
vector[i++] = strtok(buf," \t\n");
while ((vector[i++] = strtok(NULL," \t\n")) && (i<16));
vector[15] = NULL;
fflush(stdout);
fflush(stderr);
if (pipe(pipedes) != 0) {
WriteError("$Pipe failed for command \"%s\"", MBSE_SS(vector[0]));
return NULL;
}
Syslog('e', "pipe() returned read=%d, write=%d", pipedes[0], pipedes[1]);
if ((pid = fork()) == 0) {
close(pipedes[1]);
close(0);
if (dup(pipedes[0]) != 0) {
WriteError("$Reopen of stdin for command %s failed", MBSE_SS(vector[0]));
exit(MBERR_EXEC_FAILED);
}
rc = execv(vector[0],vector);
WriteError("$Exec \"%s\" returned %d", MBSE_SS(vector[0]), rc);
exit(MBERR_EXEC_FAILED);
}
close(pipedes[0]);
if ((fp = fdopen(pipedes[1],"w")) == NULL) {
WriteError("$fdopen failed for pipe to command \"%s\"", MBSE_SS(vector[0]));
}
fppid[slot].fp = fp;
fppid[slot].pid = pid;
return fp;
}
int exclose(FILE *fp)
{
int status, rc, pid, slot, sverr;
for (slot = 0; slot <= maxfppid; slot++) {
if (fppid[slot].fp == fp)
break;
}
if (slot > maxfppid) {
WriteError("Attempt to close unopened pipe");
return -1;
}
pid = fppid[slot].pid;
fppid[slot].fp = NULL;
fppid[slot].pid = 0;
Syslog('e', "Closing pipe to the child process %d",pid);
if ((rc = fclose(fp)) != 0) {
WriteError("$Error closing pipe to transport (rc=%d)", rc);
if ((rc = kill(pid,SIGKILL)) != 0)
WriteError("$kill for pid %d returned %d",pid,rc);
}
Syslog('e', "Waiting for process %d to finish",pid);
do {
rc = wait(&status);
sverr = errno;
if (status)
Syslog('e', "$Wait returned %d, status %d,%d", rc, status >> 8, status & 0xff);
} while (((rc > 0) && (rc != pid)) || ((rc == -1) && (sverr == EINTR)));
switch (rc) {
case -1:WriteError("$Wait returned %d, status %d,%d", rc, status >> 8, status & 0xff);
return MBERR_EXEC_FAILED;
case 0: return 0;
default:
if (WIFEXITED(status)) {
rc = WEXITSTATUS(status);
if (rc) {
WriteError("Expipe: returned error %d", rc);
return (rc + MBERR_EXTERNAL);
}
}
if (WIFSIGNALED(status)) {
rc = WTERMSIG(status);
WriteError("Wait stopped on signal %d", rc);
return rc;
}
if (rc)
WriteError("Wait stopped unknown, rc=%d", rc);
return rc;
}
return 0;
}

121
lib/faddr.c Normal file
View File

@@ -0,0 +1,121 @@
/*****************************************************************************
*
* $Id: faddr.c,v 1.9 2005/08/28 13:34:43 mbse Exp $
* Purpose ...............: Fidonet Address conversions.
*
*****************************************************************************
* Copyright (C) 1993-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MB 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.
*
* MB 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 MB 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 "mbselib.h"
/************************************************************************
*
* String functions
*/
/*
* Fidonet aka to string, returns Z:N/N@domain or Z:N/N.P@domain
*/
char *aka2str(fidoaddr aka)
{
static char result[43];
result[0] = '\0';
if (strlen(aka.domain)) {
if (aka.point == 0)
snprintf(result, 43, "%d:%d/%d@%s", aka.zone, aka.net, aka.node, aka.domain);
else
snprintf(result, 43, "%d:%d/%d.%d@%s", aka.zone, aka.net, aka.node, aka.point, aka.domain);
} else {
if (aka.point == 0)
snprintf(result, 43, "%d:%d/%d", aka.zone, aka.net, aka.node);
else
snprintf(result, 43, "%d:%d/%d.%d", aka.zone, aka.net, aka.node, aka.point);
}
return result;
}
/*
* Try to create a aka structure of a string.
*/
fidoaddr str2aka(char *addr)
{
char a[256];
static char b[43];
char *p, *temp = NULL;
static fidoaddr n;
n.zone = 0;
n.net = 0;
n.node = 0;
n.point = 0;
n.domain[0] = '\0';
/*
* Safety check
*/
if (strlen(addr) > 42)
return n;
snprintf(b, 43, "%s~", addr);
if ((strchr(b, ':') == NULL) || (strchr(b, '/') == NULL))
return n;
/*
* First split the f:n/n.p and domain part
*/
if ((strchr(b, '@'))) {
temp = strtok(b, "@");
p = strtok(NULL, "~");
if (p)
strcpy(n.domain, p);
}
/*
* Handle f:n/n.p part
*/
if (temp)
strcpy(a, strcat(temp, "~"));
else
strcpy(a, b);
if (strchr(a, '.') == NULL) {
n.zone = atoi(strtok(a, ":"));
n.net = atoi(strtok(NULL, "/"));
n.node = atoi(strtok(NULL, "~"));
} else {
n.zone = atoi(strtok(a, ":"));
n.net = atoi(strtok(NULL, "/"));
n.node = atoi(strtok(NULL, "."));
n.point = atoi(strtok(NULL, "~"));
}
return n;
}

224
lib/falists.c Normal file
View File

@@ -0,0 +1,224 @@
/*****************************************************************************
*
* $Id: falists.c,v 1.8 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: SEEN-BY and PATH lists
*
*****************************************************************************
* 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 "mbselib.h"
void tidy_falist(fa_list **fap)
{
fa_list *tmp,*old;
for (tmp = *fap; tmp; tmp = old) {
old = tmp->next;
tidy_faddr(tmp->addr);
free(tmp);
}
*fap = NULL;
}
int in_list(faddr *addr, fa_list **fap, int fourd)
{
fa_list *tmp;
/*
* No seenby check for points
*/
if (addr->point) {
return 0;
}
for (tmp = *fap; tmp; tmp = tmp->next)
if ((tmp->addr->net == addr->net) &&
((!fourd) || (fourd && (tmp->addr->zone == addr->zone))) &&
((!fourd) || (fourd && (tmp->addr->point == addr->point))) &&
(tmp->addr->node == addr->node)) {
return 1;
}
return 0;
}
void fill_list(fa_list **fap, char *str, fa_list **omit)
{
fa_list *tmp;
faddr *ta;
static unsigned int oldzone, oldnet;
char *buf, *p, *q, *r;
int allowskip = 1;
if ((str == NULL) || (*str == '\0'))
return;
buf = xstrcpy(str);
r = buf + strlen(buf);
for (p = strtok(buf," \t\n"), q = p + strlen(p) + 1;
p;
p = (q < r) ? strtok(q, " \t\n"):NULL, q = p ? p + strlen(p) + 1:r)
if ((ta = parsefnode(p))) {
if (ta->zone == 0)
ta->zone = oldzone;
else
oldzone = ta->zone;
if (ta->net == 0)
ta->net = oldnet;
else
oldnet = ta->net;
if (allowskip && omit && *omit && (metric(ta,(*omit)->addr) == 0)) {
tmp = *omit;
*omit = (*omit)->next;
tmp->next = NULL;
tidy_falist(&tmp);
} else {
allowskip = 0;
tmp = (fa_list *)malloc(sizeof(fa_list));
tmp->next = *fap;
tmp->addr = ta;
*fap = tmp;
}
}
free(buf);
return;
}
void fill_path(fa_list **fap, char *str)
{
fa_list **tmp;
faddr *ta;
static unsigned int oldnet;
char *buf, *p, *q, *r;
if ((str == NULL) || (*str == '\0'))
return;
buf = xstrcpy(str);
for (tmp = fap; *tmp; tmp = &((*tmp)->next)); /*nothing*/
r = buf + strlen(buf);
for (p = strtok(buf, " \t\n"), q = p + strlen(p) + 1;
p;
p = (q < r) ? strtok(q, " \t\n") : NULL, q = p ? p + strlen(p) + 1 : r)
if ((ta = parsefnode(p))) {
if (ta->net == 0)
ta->net=oldnet;
else
oldnet=ta->net;
*tmp = (fa_list *)malloc(sizeof(fa_list));
(*tmp)->next = NULL;
(*tmp)->addr = ta;
tmp = &((*tmp)->next);
}
free(buf);
return;
}
int compaddr(fa_list **,fa_list **);
void uniq_list(fa_list **fap)
{
fa_list *ta, *tan;
if (*fap == NULL)
return;
for (ta = *fap; ta; ta = ta->next) {
while ((tan = ta->next) && (compaddr(&ta, &tan) == 0)) {
ta->next = tan->next;
tidy_faddr(tan->addr);
free(tan);
}
ta->next = tan;
}
}
void sort_list(fa_list **fap)
{
fa_list *ta, **vector;
size_t n = 0, i;
if (*fap == NULL)
return;
for (ta = *fap; ta; ta = ta->next)
n++;
vector = (fa_list **)malloc(n * sizeof(fa_list *));
i = 0;
for (ta = *fap; ta; ta = ta->next) {
vector[i++] = ta;
}
qsort(vector,n,sizeof(faddr*),
(int(*)(const void*,const void*))compaddr);
(*fap) = vector[0];
i = 1;
for (ta = *fap; ta; ta = ta->next) {
while ((i < n) && (compaddr(&ta,&(vector[i])) == 0)) {
tidy_faddr((vector[i])->addr);
free(vector[i]);
i++;
}
if (i < n)
ta->next=vector[i++];
else
ta->next=NULL;
}
free(vector);
return;
}
int compaddr(fa_list **fap1, fa_list **fap2)
{
if ((*fap1)->addr->net != (*fap2)->addr->net)
return ((*fap1)->addr->net - (*fap2)->addr->net);
else
return ((*fap1)->addr->node - (*fap2)->addr->node);
}

684
lib/ftn.c Normal file
View File

@@ -0,0 +1,684 @@
/*****************************************************************************
*
* $Id: ftn.c,v 1.11 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Fidonet Technology Network functions
* Remark ................: From ifmail with patches from P.Saratxaga
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
#ifndef MAXUSHORT
#define MAXUSHORT 65535
#endif
#ifndef BLANK_SUBS
#define BLANK_SUBS '.'
#endif
int addrerror = 0;
void tidy_faddr(faddr *addr)
{
if (addr == NULL)
return;
if (addr->name)
free(addr->name);
if (addr->domain)
free(addr->domain);
free(addr);
}
faddr *parsefnode(char *s)
{
faddr addr, *tmp;
char *buf, *str, *p, *q, *n;
int good = 1;
if (s == NULL)
return NULL;
str = buf = xstrcpy(s);
while (isspace(*str))
str++;
if (*(p=str+strlen(str)-1) == '\n')
*(p--) ='\0';
while (isspace(*p))
*(p--) = '\0';
p=str + strlen(str) - 1;
if (((*str == '(') && (*p == ')')) || ((*str == '\"') && (*p == '\"')) ||
((*str == '\'') && (*p == '\'')) || ((*str == '<') && (*p == '>')) ||
((*str == '[') && (*p == ']')) || ((*str == '{') && (*p == '}'))) {
str++;
*p = '\0';
}
memset(&addr, 0, sizeof(faddr));
if ((p = strrchr(str,' '))) {
n = str;
str = p + 1;
while (isspace(*p))
*(p--) = '\0';
if (!strcasecmp(p - 2," of"))
*(p-2) = '\0';
else if (!strcasecmp(p - 1," @"))
*(p-1) = '\0';
p -= 3;
while (isspace(*p) || (*p == ','))
*(p--) = '\0';
if (strlen(n) > MAXNAME)
n[MAXNAME] = '\0';
if (*n != '\0')
addr.name = xstrcpy(n);
}
if ((p = strrchr(str, '@')))
*(p++) = '\0';
else if ((p = strrchr(str,'%')))
*(p++) = '\0';
else if ((q = strrchr(str,'#'))) {
*(q++) = '\0';
p = str;
str = q;
} else if (addr.name && (strrchr(addr.name,'@'))) {
str = xstrcpy(addr.name);
if ((p=strrchr(str,'@')))
*(p++) = '\0';
else if ((p=strrchr(str,'%')))
*(p++) = '\0';
} else
p = NULL;
if (p && ((q = strchr(p,'.'))))
*q = '\0';
addr.point = 0;
addr.node = 0;
addr.net = 0;
addr.zone = 0;
addr.domain = xstrcpy(p);
if ((p = strchr(str, ':'))) {
*(p++) = '\0';
if (strspn(str, "0123456789") == strlen(str))
addr.zone = atoi(str);
else
if (strcmp(str,"*") == 0)
addr.zone = -1;
else
good = 0;
str = p;
}
if ((p = strchr(str, '/'))) {
*(p++) = '\0';
if (strspn(str, "0123456789") == strlen(str))
addr.net = atoi(str);
else
if (strcmp(str, "*") == 0)
addr.net = -1;
else
good = 0;
str = p;
}
if ((p=strchr(str, '.'))) {
*(p++) = '\0';
if (strspn(str, "0123456789") == strlen(str))
addr.node = atoi(str);
else
if (strcmp(str, "*") == 0)
addr.node = -1;
else
good = 0;
str = p;
} else {
if (strspn(str, "0123456789") == strlen(str))
addr.node = atoi(str);
else
if (strcmp(str, "*") == 0)
addr.node = -1;
else
good = 0;
str = NULL;
}
if (str) {
if (strspn(str, "0123456789") == strlen(str))
addr.point = atoi(str);
else
if (strcmp(str, "*") == 0)
addr.point = -1;
else
good = 0;
}
if (buf)
free(buf);
if (good) {
tmp = (faddr *)malloc(sizeof(addr));
tmp->name = NULL;
tmp->domain = addr.domain;
tmp->point = addr.point;
tmp->node = addr.node;
tmp->net = addr.net;
tmp->zone = addr.zone;
return tmp;
} else {
if (addr.name)
free(addr.name);
if (addr.domain)
free(addr.domain);
return NULL;
}
}
faddr *parsefaddr(char *s)
{
faddr *tmpaddr = NULL;
parsedaddr rfcaddr;
int gotzone = 0, gotnet = 0, gotnode = 0, gotpoint = 0;
int zone = 0, net = 0, noden = 0, point = 0;
char *domain = NULL, *freename = NULL;
int num;
char *p = NULL,*q = NULL,*t = NULL;
int l, quoted;
FILE *fp;
rfcaddr.target = NULL;
rfcaddr.remainder = NULL;
rfcaddr.comment = NULL;
t = xstrcpy(s);
if (*(q=t+strlen(t)-1) == '\n')
*q='\0';
if (((*(p=t) == '(') && (*(q=p+strlen(p)-1) == ')')) || ((*p == '\"') && (*q == '\"'))) {
p++;
*q='\0';
}
if (strchr(s,'@') || strchr(s,'%') || strchr(s,'!'))
rfcaddr = parserfcaddr(p);
else {
addrerror = 0;
rfcaddr.target = xstrcpy(p);
}
free(t);
if ((addrerror) || (rfcaddr.target == NULL))
goto leave;
p = calloc(PATH_MAX, sizeof(char));
snprintf(p, PATH_MAX -1, "%s/etc/domain.data", getenv("MBSE_ROOT"));
if ((fp = fopen(p, "r")) == NULL) {
WriteError("$Can't open %s", p);
free(p);
} else {
free(p);
fread(&domainhdr, sizeof(domainhdr), 1, fp);
p = rfcaddr.target;
while (fread(&domtrans, domainhdr.recsize, 1, fp) == 1) {
q = p + strlen(p) - strlen(domtrans.intdom);
if ((q >= p) && (strcasecmp(domtrans.intdom, q) == 0)) {
*q = '\0';
q = malloc(strlen(p) + strlen(domtrans.ftndom) +1);
strcpy(q, p);
strcat(q, domtrans.ftndom);
p = q;
free(rfcaddr.target);
rfcaddr.target = p;
break;
}
}
fclose(fp);
}
if (((l = strlen(rfcaddr.target)) > 4) && (strcasecmp(rfcaddr.target + l - 4,".ftn") == 0)) {
rfcaddr.target[l-4] = '\0';
}
for (p = strtok(rfcaddr.target, "."); p; p = strtok(NULL,".")) {
if (((l = strlen(p + 1)) > 0) && (l <= 5) &&
(strspn(p + 1, "0123456789") == l)) {
num = atol(p + 1);
switch (*p) {
case 'z':
case 'Z':
gotzone++;
if (num > MAXUSHORT)
addrerror |= ADDR_BADTOKEN;
zone = num;
break;
case 'n':
case 'N':
gotnet++;
if (num > MAXUSHORT)
addrerror |= ADDR_BADTOKEN;
net = num;
break;
case 'f':
case 'F':
gotnode++;
if (num > MAXUSHORT)
addrerror |= ADDR_BADTOKEN;
noden = num;
break;
case 'p':
case 'P':
gotpoint++;
if (num > MAXUSHORT)
addrerror |= ADDR_BADTOKEN;
point = num;
break;
default:
if (gotnet && gotnode) {
if (domain == NULL)
domain = xstrcpy(p);
} else
addrerror |= ADDR_BADTOKEN;
break;
}
} else { /* not "cNNNN" token */
if (gotnet && gotnode) {
if (domain == NULL)
domain = xstrcpy(p);
} else
addrerror |= ADDR_BADTOKEN;
}
}
if ((gotzone > 1) || (gotnet != 1) || (gotnode != 1) || (gotpoint > 1)) {
addrerror |= ADDR_BADSTRUCT;
}
if (addrerror)
goto leave;
if (rfcaddr.remainder) {
quoted = 0;
if ((*(p = rfcaddr.remainder) == '\"') && (*(q = p + strlen(p) -1) == '\"')) {
p++;
*q='\0';
quoted = 1;
}
if (strchr(p,'@') || strchr(p,'%') || strchr(p,'!')) {
if (((q=strrchr(p,'%'))) && !strchr(p,'@'))
*q = '@';
} else if ((!quoted) && (!strchr(p, ' '))) {
for (q = p; *q; q++) {
if (*q == BLANK_SUBS)
*q = ' ';
else if (*q == '.')
*q = ' ';
else if (*q == '_')
*q = ' ';
}
}
for (q = p; *q; q++) {
if ((*q == '\\') && ((*(q+1) == '"') || ((*(q+1) == '\\') && (!quoted)))) {
*q='\0';
strcat(p, q+1);
}
}
if (strspn(p," ") != strlen(p))
freename = xstrcpy(p);
}
tmpaddr=(faddr*)malloc(sizeof(faddr));
tmpaddr->zone=zone;
tmpaddr->net=net;
tmpaddr->node=noden;
tmpaddr->point=point;
tmpaddr->domain=domain;
domain=NULL;
tmpaddr->name=freename;
freename=NULL;
leave:
if (domain)
free(domain);
if (freename)
free(freename);
tidyrfcaddr(rfcaddr);
return tmpaddr;
}
char *ascinode(faddr *a, int fl)
{
static char buf[128], *f, *t, *p;
static char *q;
int skip, found = FALSE;
FILE *fp;
if (a == NULL) {
strcpy(buf,"<none>");
return buf;
}
buf[0]='\0';
if ((fl & 0x80) && (a->name)) {
if ((strchr(a->name,'.')) || (strchr(a->name,'@')) ||
(strchr(a->name,'\'')) || (strchr(a->name,',')) ||
(strchr(a->name,'<')) || (strchr(a->name,'>')))
snprintf(buf+strlen(buf), 128, "\"%s\" <", a->name);
else
snprintf(buf+strlen(buf), 128, "%s <", a->name);
}
if ((fl & 0x40) && (a->name)) {
f = a->name;
t = buf + strlen(buf);
skip = 0;
if ((!strchr(f,'@')) && ((strchr(f,BLANK_SUBS)) || (strchr(f,'.')) || (strchr(f,'_')))) {
skip = 1;
*t++='"';
}
while (*f) {
switch (*f) {
case '_':
case '.': *t++=*f;
break;
case ' ': if (!skip)
*t++=BLANK_SUBS;
else {
*t++='='; *t++='2'; *t++='0';
}
break;
case ',': { /* "," is a problem on mail addr */
if (!skip)
*t++='\\';
*t++='=';
*t++='2';
*t++='c';
}
case '@': if (skip) {
*t++='"';
skip=0;
}
*t++='%';
break;
case '"': *t++='\\';
*t++=*f;
break;
case '>':
case '<':
case '\'': if (!skip)
*t++='\\';
*t++=*f;
break;
default: if ((((*f & 0xff) > 0x29) && ((*f & 0xff) < 0x3a)) ||
(((*f & 0xff) > 0x40) && ((*f & 0xff) < 0x5b)) ||
(((*f & 0xff) > 0x60) && ((*f & 0xff) < 0x7b)))
*t++=*f;
else {
if (!skip)
*t++='\\';
*t++=*f;
}
break;
}
f++;
}
if (skip)
*t++='"';
skip = 0;
*t++ = '@';
*t++ = '\0';
}
if ((fl & 0x01) && (a->point))
snprintf(buf+strlen(buf), 128, "p%u.", a->point);
if (fl & 0x02)
snprintf(buf+strlen(buf), 128, "f%u.", a->node);
if (fl & 0x04)
snprintf(buf+strlen(buf), 128, "n%u.", a->net);
if ((fl & 0x08) && (a->zone))
snprintf(buf+strlen(buf), 128, "z%u.", a->zone);
buf[strlen(buf)-1]='\0';
if (fl & 0x10) {
if (a->domain)
snprintf(buf+strlen(buf), 128, ".%s", a->domain);
}
if (fl & 0x20) {
if (a->domain) {
if ((fl & 0x10) == 0)
snprintf(buf+strlen(buf), 128, ".%s", a->domain);
} else {
if (SearchFidonet(a->zone))
snprintf(buf+strlen(buf), 128, ".%s", fidonet.domain);
else
snprintf(buf+strlen(buf), 128, ".fidonet");
}
p = calloc(128, sizeof(char));
snprintf(p, 128, "%s/etc/domain.data", getenv("MBSE_ROOT"));
if ((fp = fopen(p, "r")) == NULL) {
WriteError("$Can't open %s", p);
} else {
fread(&domainhdr, sizeof(domainhdr), 1, fp);
while (fread(&domtrans, domainhdr.recsize, 1, fp) == 1) {
q = buf + strlen(buf) - strlen(domtrans.ftndom);
if ((q >= buf) && (strcasecmp(domtrans.ftndom, q) == 0)) {
strcpy(q, domtrans.intdom);
found = TRUE;
break;
}
}
fclose(fp);
}
free(p);
if (!found)
snprintf(buf + strlen(buf), 128, ".ftn");
}
if ((fl & 0x80) && (a->name))
snprintf(buf+strlen(buf), 128, ">");
return buf;
}
/*
* Return ASCII string for node, the bits in 'fl' set the
* output format.
*/
char *ascfnode(faddr *a, int fl)
{
static char buf[128];
if (a == NULL) {
strcpy(buf, "<none>");
return buf;
}
buf[0] = '\0';
if ((fl & 0x40) && (a->name))
snprintf(buf+strlen(buf),128,"%s of ",a->name);
if ((fl & 0x08) && (a->zone))
snprintf(buf+strlen(buf),128,"%u:",a->zone);
if (fl & 0x04)
snprintf(buf+strlen(buf),128,"%u/",a->net);
if (fl & 0x02)
snprintf(buf+strlen(buf),128,"%u",a->node);
if ((fl & 0x01) && (a->point))
snprintf(buf+strlen(buf),128,".%u",a->point);
if ((fl & 0x10) && (a->domain))
snprintf(buf+strlen(buf),128,"@%s",a->domain);
return buf;
}
int metric(faddr *a1, faddr *a2)
{
if ((a1->domain != NULL) && (a2->domain != NULL) &&
(strcasecmp(a1->domain,a2->domain) != 0))
return METRIC_DOMAIN;
if ((a1->zone != 0) && (a2->zone != 0) &&
(a1->zone != a2->zone)) return METRIC_ZONE;
if (a1->net != a2->net) return METRIC_NET;
if (a1->node != a2->node) return METRIC_NODE;
if (a1->point != a2->point) return METRIC_POINT;
return METRIC_EQUAL;
}
/*
* Convert mbse style to ifcico style.
*/
faddr *fido2faddr(fidoaddr aka)
{
faddr *fa;
fa = (faddr *)malloc(sizeof(faddr));
fa->name = NULL;
fa->domain = xstrcpy(aka.domain);;
fa->zone = aka.zone;
fa->net = aka.net;
fa->node = aka.node;
fa->point = aka.point;
return fa;
}
/*
* Convert ifcico style to mbse style
*/
fidoaddr *faddr2fido(faddr *aka)
{
fidoaddr *Sys;
Sys = (fidoaddr *)malloc(sizeof(fidoaddr));
memset(Sys, 0, sizeof(Sys));
Sys->zone = aka->zone;
Sys->net = aka->net;
Sys->node = aka->node;
Sys->point = aka->point;
if (aka->domain != NULL)
snprintf(Sys->domain, 13, "%s", aka->domain);
return Sys;
}
faddr *bestaka_s(faddr *addr)
{
faddr *best = NULL, *tmp;
int i, minmetric, wt;
for (i = 0; i < 40; i++) {
if (CFG.akavalid[i]) {
best = fido2faddr(CFG.aka[i]);
break;
}
}
if (addr == NULL)
return best;
minmetric = metric(addr, best);
for (i = 0; i < 40; i++) {
if (CFG.akavalid[i]) {
tmp = fido2faddr(CFG.aka[i]);
wt = metric(addr, tmp);
tidy_faddr(tmp);
if ((wt < minmetric) && ((best->point != 0) || (minmetric > METRIC_NODE))) {
/*
* In the same network, use node address even when
* routing to the node where we have a point address
*/
minmetric = wt;
tidy_faddr(best);
best = fido2faddr(CFG.aka[i]);
}
}
}
return best;
}
int is_local(faddr *addr)
{
int i;
faddr *tmp;
for (i = 0; i < 40; i++) {
tmp = fido2faddr(CFG.aka[i]);
if ((CFG.akavalid[i]) && (metric(tmp, addr) == METRIC_EQUAL)) {
tidy_faddr(tmp);
return TRUE;
}
tidy_faddr(tmp);
}
return FALSE;
}
int chkftnmsgid(char *msgid)
{
faddr *p;
if (msgid == NULL)
return 0;
while (isspace(*msgid))
msgid++;
if ((p=parsefaddr(msgid))) {
if (p->name && (strspn(p->name,"0123456789") == strlen(p->name)))
return 1;
} else if ((!strncmp(msgid,"<MSGID_",7)) || (!strncmp(msgid,"<NOMSGID_",9)) || (!strncmp(msgid,"<ftn_",5))) {
return 1;
}
return 0;
}

181
lib/ftnmsg.c Normal file
View File

@@ -0,0 +1,181 @@
/*****************************************************************************
*
* $Id: ftnmsg.c,v 1.10 2005/10/11 20:49:42 mbse Exp $
* File ..................: ftnmsg.c
* Purpose ...............: Fidonet mailer
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
static char *months[] = {
(char *)"Jan",(char *)"Feb",(char *)"Mar",
(char *)"Apr",(char *)"May",(char *)"Jun",
(char *)"Jul",(char *)"Aug",(char *)"Sep",
(char *)"Oct",(char *)"Nov",(char *)"Dec"
};
char *ftndate(time_t t)
{
static char buf[32];
struct tm *ptm;
ptm = localtime(&t);
if (ptm->tm_sec > 59)
ptm->tm_sec = 59;
snprintf(buf, 32, "%02d %s %02d %02d:%02d:%02d",ptm->tm_mday,
months[ptm->tm_mon], ptm->tm_year%100,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return buf;
}
FILE *ftnmsghdr(ftnmsg *fmsg, FILE *pkt, faddr *routeaddr, char flavor, char *Pid)
{
unsigned char buffer[0x0e];
time_t Now;
faddr *from;
if ((strlen(fmsg->to->name) > 36) ||
(strlen(fmsg->from->name) > 36) ||
(strlen(fmsg->subj) > 72))
return NULL;
if (routeaddr == NULL)
routeaddr = fmsg->to;
pkt = openpkt(pkt, routeaddr, flavor, FALSE);
if (pkt == NULL)
return NULL;
if (fmsg->area)
from = bestaka_s(fmsg->to);
else
from = fmsg->from;
memset(&buffer, 0, sizeof(buffer));
buffer[0x00] = 2;
buffer[0x02] = (from->node & 0x00ff);
buffer[0x03] = (from->node & 0xff00) >> 8;
buffer[0x04] = (fmsg->to->node & 0x00ff);
buffer[0x05] = (fmsg->to->node & 0xff00) >> 8;
buffer[0x06] = (from->net & 0x00ff);
buffer[0x07] = (from->net & 0xff00) >> 8;
buffer[0x08] = (fmsg->to->net & 0x00ff);
buffer[0x09] = (fmsg->to->net & 0xff00) >> 8;
buffer[0x0a] = (fmsg->flags & 0x00ff);
buffer[0x0b] = (fmsg->flags & 0xff00) >> 8;
fwrite(buffer, 1, sizeof(buffer), pkt);
fprintf(pkt, "%s%c", ftndate(fmsg->date), '\0');
fprintf(pkt, "%s%c", fmsg->to->name?fmsg->to->name:(char *)"Sysop", '\0');
fprintf(pkt, "%s%c", fmsg->from->name?fmsg->from->name:(char *)"Sysop", '\0');
fprintf(pkt, "%s%c", fmsg->subj?fmsg->subj:(char *)"<none>", '\0');
if (fmsg->area) {
fprintf(pkt, "AREA:%s\r", fmsg->area);
} else {
if (fmsg->to->point)
fprintf(pkt, "\1TOPT %u\r", fmsg->to->point);
if (fmsg->from->point)
fprintf(pkt, "\1FMPT %u\r", fmsg->from->point);
fprintf(pkt, "\1INTL %u:%u/%u %u:%u/%u\r",
fmsg->to->zone,
fmsg->to->net,
fmsg->to->node,
fmsg->from->zone,
fmsg->from->net,
fmsg->from->node
);
}
if (fmsg->msgid_s)
fprintf(pkt, "\1MSGID: %s\r", fmsg->msgid_s);
else if (fmsg->msgid_a)
fprintf(pkt, "\1MSGID: %s %08x\r",
fmsg->msgid_a,
fmsg->msgid_n);
if (fmsg->reply_s)
fprintf(pkt, "\1REPLY: %s\r", fmsg->reply_s);
else if (fmsg->reply_a)
fprintf(pkt, "\1REPLY: %s %08x\r",
fmsg->reply_a,
fmsg->reply_n);
Now = time(NULL) - (gmt_offset((time_t)0) * 60);
fprintf(pkt, "\001PID: %s %s (%s-%s)\r", Pid, VERSION, OsName(), OsCPU());
fprintf(pkt, "\001TZUTC: %s\r", gmtoffset(Now));
if (ferror(pkt))
return NULL;
else
return pkt;
}
void tidy_ftnmsg(ftnmsg *tmsg)
{
if (tmsg == NULL)
return;
tmsg->flags = 0;
if (tmsg->to)
tidy_faddr(tmsg->to);
tmsg->to=NULL;
if (tmsg->from)
tidy_faddr(tmsg->from);
tmsg->from=NULL;
if (tmsg->subj)
free(tmsg->subj);
tmsg->subj=NULL;
if (tmsg->msgid_s)
free(tmsg->msgid_s);
tmsg->msgid_s=NULL;
if (tmsg->msgid_a)
free(tmsg->msgid_a);
tmsg->msgid_a=NULL;
if (tmsg->reply_s)
free(tmsg->reply_s);
tmsg->reply_s=NULL;
if (tmsg->reply_a)
free(tmsg->reply_a);
tmsg->reply_a=NULL;
if (tmsg->origin)
free(tmsg->origin);
tmsg->origin=NULL;
if (tmsg->area)
free(tmsg->area);
tmsg->area=NULL;
free(tmsg);
}

296
lib/ftscprod.010 Normal file
View File

@@ -0,0 +1,296 @@
0000,Fido,MS-DOS,Packer/mailer,Tom_Jennings,1:125/111
0001,Rover,MS-DOS,Packer/mailer,Bob_Hartman,1:104/501
0002,SEAdog,MS-DOS,Packer/mailer,Thom_Henderson,1:107/542.1
0003,WinDog,MS-DOS,Mailer,Solar_Wind_Computing,1:115/333
0004,Slick-150,HP-150,Packer/mailer,Jerry_Bain,????
0005,Opus,MS-DOS,Packer/mailer,Doug_Boone,1:124/4227
0006,Dutchie,MS-DOS,Packer/mailer,Henk_Wevers,2:500/1
0007,WPL_Library,Amiga,Mailer,Russell_McOrmand,1:163/109
0008,Tabby,Macintosh,Packer/mailer,Michael_Connick,1:107/412
0009,SWMail,OS/2,Mailer,Solar_Wind_Computing,1:115/333
000A,Wolf-68k,CPM-68k,Packer/mailer,Robert_Heller,1:321/153
000B,QMM,QNX,Packer/mailer,Rick_Duff,1:167/201
000C,FrontDoor,MS-DOS,Packer/mailer,Joaquim_Homrighausen,2:270/17
000D,GOmail,MS-DOS,Packer,Scott_Green,????
000E,FFGate,MS-DOS,Packer,Ruedi_Kneubuehler,2:301/580
000F,FileMgr,MS-DOS,Packer,Erik_van_Emmerik,2:281/611
0010,FIDZERCP,MS-DOS,Packer,Thorsten_Seidel,2:242/55
0011,MailMan,MS-DOS,Packer,Ron_Bemis,1:124/1113
0012,OOPS,MS-DOS,Packer,Tom_Kashuba,1:322/379
0013,GS-Point,Atari_ST,Packer/mailer,Harry_Lee,1:124/4230
0014,BGMail,????,????,Ray_Gwinn,1:265/104
0015,ComMotion/2,OS/2,Packer/mailer,Michael_Buenter,2:301/602
0016,OurBBS_Fidomailer,MS-DOS/Unix/Coherent,Packer/mailer,Brian_Keahl,1:133/524
0017,FidoPcb,MS-DOS,Packer,Matjaz_Koce,2:380/100
0018,WimpLink,Archimedes,Packer/mailer,Remco_de_Vreugd,2:283/307
0019,BinkScan,MS-DOS,Packer,Shawn_Stoddard,1:362/101
001A,D'Bridge,MS-DOS,Packer/mailer,Chris_Irwin,1:18/68
001B,BinkleyTerm,MS-DOS,Mailer,Vince_Perriello,1:343/491
001C,Yankee,MS-DOS,Packer,Randy_Edwards,????
001D,uuGate,MS-DOS,Packer,Geoff_Watts,3:690/710
001E,Daisy,Apple_][,Packer/mailer,Raymond_&_Ken_Lo,3:700/1
001F,Polar_Bear,????,Packer/mailer,Kenneth_McLeod,1:101/190
0020,The-Box,MS-DOS/Atari_ST,Packer/mailer,Jac_Kersing/Arjen_Lentz,2:283/333
0021,STARgate/2,OS/2,Packer/mailer,Shawn_Stoddard,1:362/101
0022,TMail,MS-DOS,Packer,Larry_Lewis,3:713/600.1701
0023,TCOMMail,MS-DOS,Packer/mailer,Mike_Ratledge,1:372/888
0024,GIGO,MS-DOS,Packer,Jason_Fesler,1:203/7707,,940228
0025,RBBSMail,MS-DOS,Packer,Jan_Terpstra,2:512/10
0026,Apple-Netmail,Apple_][,Packer/mailer,Bill_Fenner,1:129/87
0027,Chameleon,Amiga,Mailer,Juergen_Hermann,2:241/2.12
0028,Majik_Board,MS-DOS,Packer/mailer,Dale_Barnes,1:3601/14.20
0029,QM,MS-DOS,Packer,George_Peace,1:270/101
002A,Point_And_Click,Amiga,Packer,Rob_Tillotson,1:201/40.302
002B,Aurora_Three_Bundler,MS-DOS,Packer,Oliver_McDonald,????
002C,FourDog,MS-DOS,Packer,Shay_Walters,1:376/12
002D,MSG-PACK,MS-DOS,Packer,Tom_Hendricks,1:261/662
002E,AMAX,MS-DOS,Packer,Alan_Applegate,1:104/36
002F,Domain_Communication_System,????,????,Hal_Duprie,1:101/106
0030,LesRobot,????,Packer,Lennart_Svensonn,2:501/2
0031,Rose,MS-DOS,Packer/mailer,Glen_Jackson,1:100/617
0032,Paragon,Amiga,Packer/mailer,Jon_Radoff,1:322/545
0033,BinkleyTerm/oMMM/ST,Atari_ST,Packer/mailer,Bill_Scull,1:363/112,,19951209
0034,StarNet,Atari_ST,Mailer,Eric_Drewry,1:322/566
0035,ZzyZx,MS-DOS,Packer,Jason_Steck,1:124/424
0036,QEcho,MS-DOS,Packer,The_QuickBBS_Group,1:363/1701
0037,BOOM,MS-DOS,Packer,Andrew_Farmer,1:243/1
0038,PBBS,Amiga,Packer/mailer,Todd_Kover,1:261/1028
0039,TrapDoor,Amiga,Mailer,Maximilian_Hantsch,2:310/6
003A,Welmat,Amiga,Mailer,Russell_McOrmand,1:163/109
003B,NetGate,Unix-386,Packer,David_Nugent,3:632/348
003C,Odie,MS-DOS,Mailer,Matt_Farrenkopf,1:105/376
003D,Quick_Gimme,CPM-80/MS-DOS,Packer/mailer,Laeeth_Isaacs,2:254/18
003E,dbLink,MS-DOS,Packer/mailer,Chris_Irwin,1:18/68
003F,TosScan,MS-DOS,Packer,Joaquim_Homrighausen,2:270/17
0040,Beagle,MS-DOS,Mailer,Alexander_Holy,2:310/90
0041,Igor,MS-DOS,Mailer,Harry_Lee,1:124/4230
0042,TIMS,MS-DOS,Packer/mailer,Bit_Bucket_Software,1:104/501
0043,Phoenix,MS-DOS,Packer/mailer,International_Telecommunications,1:296/5,,19930624
0044,FrontDoor_APX,MS-DOS,Packer/mailer,Joaquim_Homrighausen,2:270/17
0045,XRS,MS-DOS,Packer,Mike_Ratledge,1:372/888
0046,Juliet_Mail_System,Amiga,Packer,Gregory_Kritsch,1:163/109.30
0047,Jabberwocky,Macintosh,Packer,Eric_Larson,1:2605/620
0048,XST,MS-DOS,Packer,Wayne_Michaels,1:380/100
0049,MailStorm,Amiga,Packer,Russel_Miranda,1:268/106
004A,BIX-Mail,????,Mailer,Bob_Hartman,1:104/501
004B,IMAIL,MS-DOS,Packer,IMAIL_INC.,2:246/47
004C,FTNGate,MS-DOS,Packer,Jason_Steck,1:104/424
004D,RealMail,MS-DOS,Packer,Taine_Gilliam,1:372/42
004E,Lora-CBIS,MS-DOS,Mailer,Marco_Maccaferri,2:332/402
004F,TDCS,PDP-11,Packer/mailer,Terry_Ebdon,2:254/6
0050,InterMail,MS-DOS,Packer/mailer,Peter_Stewart,1:369/35
0051,RFD,MS-DOS,Packer,Doug_Belkofer,1:234/10
0052,Yuppie!,MS-DOS,Packer,Leo_Moll,2:242/2
0053,EMMA,MS-DOS,Packer,Johan_Zwiekhorst,2:292/100
0054,QBoxMail,QDOS,Packer/mailer,Jan_Bredenbeek,2:283/500
0055,Number_4,MS-DOS,Packer/mailer,Ola_Garstad,2:502/15
0056,Number_5,MS-DOS,Packer/mailer,Ola_Garstad,2:502/15
0057,GSBBS,MS-DOS,Packer,Michelangelo_Jones,1:260/244
0058,Merlin,MS-DOS,Packer/mailer,Mark_Lewis,2:258/25
0059,TPCS,MS-DOS,Packer,Mikael_Kjellstrom,2:201/211
005A,Raid,MS-DOS,Packer,George_Peace,1:270/101
005B,Outpost,MS-DOS,Packer/mailer,Mike_Dailor,????
005C,Nizze,MS-DOS,Packer,Tomas_Nielsen,2:205/202
005D,Armadillo,Macintosh,Packer,Erik_Sea,1:221/109
005E,rfmail,Unix,Packer/mailer,Per_Lindqvist,2:201/332
005F,Msgtoss,MS-DOS,Packer,Mike_Zakharoff,1:343/36
0060,InfoTex,MS-DOS,Packer/mailer,Jan_Spooren,2:292/852
0061,GEcho,MS-DOS,Packer,Gerard_van_der_Land,2:283/555,951209
0062,CDEhost,MS-DOS,Packer,Dennis_D'Annunzio,1:379/28
0063,Pktize,MS-DOS,Packer,Joaquim_Homrighausen,2:270/17
0064,PC-RAIN,MS-DOS,Packer/mailer,Ray_Hyder,1:272/40
0065,Truffle,MS-DOS/OS2,Mailer,Mike_Rissa,2:504/59
0066,Foozle,Amiga,Packer,Peer_Hasselmeyer,2:247/4
0067,White_Pointer,Macintosh,Packer/mailer,Alastair_Rakine,3:680/820
0068,GateWorks,MS-DOS,Packer,Jamie_Penner,1:153/1025
0069,Portal_of_Power,MS-DOS,Mailer,Soren_Ager,2:230/12
006A,MacWoof,Macintosh,Packer/mailer,Craig_Vaughan,1:109/342
006B,Mosaic,MS-DOS,Packer,Christopher_King,1:103/315
006C,TPBEcho,MS-DOS,Packer,Gerd_Qualmann,2:242/1
006D,HandyMail,MS-DOS,Packer/mailer,jim_nutt,1:114/30
006E,EchoSmith,MS-DOS,Packer,Noel_Crow,1:170/409
006F,FileHost,MS-DOS,Packer,Mark_Cole,2:252/186
0070,SFTS,MS-DOS,Packer,Bruce_Anderson,1:3402/6
0071,Benjamin,MS-DOS,Packer/mailer,Stefan_Graf,2:245/4.5436
0072,RiBBS,OS9_(COCO),Packer/mailer,Ron_Bihler,1:104/54
0073,MP,MS-DOS,Packer,Ivan_Leong,6:600/28
0074,Ping,MS-DOS,Packer,David_Nugent,3:632/348
0075,Door2Europe,MS-DOS,Packer/mailer,Michaela_Schoebel,2:247/14
0076,SWIFT,MS-DOS,Packer/mailer,Hanno_van_der_Maas,2:500/2
0077,WMAIL,MS-DOS,Packer,Silvan_Calarco,2:334/100.2
0078,RATS,MS-DOS,Packer,Jason_DeCaro,1:260/205
0079,Harry_the_Dirty_Dog,OS2,Mailer/packer,George_Edwards,3:632/340.7
007A,Maximus-CBCS,MS-DOS/OS2,Packer,Scott_Dudley,1:249/106
007B,SwifEcho,MS-DOS,Packer,Dana_Bell,1:3801/8
007C,GCChost,Amiga,Packer,Davide_Massarenti,2:332/505.3
007D,RPX-Mail,MS-DOS,Packer,Joerg_Wirtgen,2:241/4034
007E,Tosser,MS-DOS,Packer,Albert_Ng,6:700/185
007F,TCL,MS-DOS,Packer,Ulf_Hedlund,2:201/602
0080,MsgTrack,MS-DOS,Packer,Andrew_Farmer,1:243/1
0081,FMail,MS-DOS/DOS_DPMI/OS2/WIN32,Packer,Folkert_Wijnstra,2:283/619
0082,Scantoss,MS-DOS,Packer,Michael_Matter,2:243/44.3443
0083,Point_Manager,Amiga,Packer,Pino_Aliberti,2:335/602.2,,19931012
0084,IMBINK,MS-DOS,Packer,Mike_Hartmann,2:246/48
0085,Simplex,MS-DOS/OS2,Packer,Chris_Laforet,1:152/401
0086,UMTP,MS-DOS,Packer,Byron_Copeland,1:272/26
0087,Indaba,MS-DOS,Packer,Pieter_Muller,5:7102/11
0088,Echomail_Engine,MS-DOS,Packer,Joe_Jared,1:103/200
0089,DragonMail,OS2,Packer,Patrick_O'Riva,1:143/37
008A,Prox,MS-DOS,Packer,Gerhard_Hoogterp,2:283/1.2
008B,Tick,MS-DOS/OS2,Packer,Barry_Geller,1:266/12
008C,RA-Echo,MS-DOS,Packer,Roger_Kirchhoff,2:245/4
008D,TrapToss,Amiga,Packer,Maximilian_Hantsch,2:310/6
008E,Babel,MS-DOS/OS2,Packer,Jorgen_Abrahamsen,2:230/100.9
008F,UMS,Amiga,Packer,Martin_Horneffer,2:242/7.9
0090,RWMail,MS-DOS,Packer,Remko_Westrik,2:285/309.5
0091,WildMail,MS-DOS,Packer,Derek_Koopowitz,1:161/502
0092,AlMAIL,MS-DOS,Packer,Alan_Leung,1:348/207
0093,XCS,MS-DOS,Packer,Rudi_Kusters,2:512/34.4
0094,Fone-Link,MS-DOS,Packer/mailer,Chris_Sloyan,1:269/602
0095,Dogfight,MS-DOS,Packer,Chris_Tyson,2:256/36
0096,Ascan,MS-DOS,Packer,Arjen_van_Loon,2:281/1.397
0097,FastMail,MS-DOS,Packer,Jan_Berends,2:282/5
0098,DoorMan,MS-DOS,Mailer,Christopher_Dean,1:105/70
0099,PhaedoZap,Atari_ST,Packer,Jeff_Mitchell,1:229/422
009A,SCREAM,MS-DOS,Packer/mailer,Jem_Miller,1:147/33
009B,MoonMail,MS-DOS,Packer/mailer,Hasse_Wigdahl,2:206/101
009C,Backdoor,Sinclair_QL,Packer,Erik_Slagter,2:283/500.3
009D,MailLink,Archimedes,Packer/mailer,Jan-Jaap_v._d._Geer,2:500/133.1138
009E,Mail_Manager,MS-DOS,Packer,Andreas_Brodowski,2:241/4006
009F,Black_Star,Xenix_386,Packer/mailer,Jac_Kersing,2:283/333
00A0,Bermuda,Atari_ST/MS-DOS,Packer,Jac_Kersing,2:283/333
00A1,PT,MS-DOS,Packer/mailer,Jerry_Andrew,1:109/426
00A2,UltiMail,MS-DOS,Mailer,Brett_Floren,1:363/1000
00A3,GMD,MS-DOS,Packer,John_Souvestre,1:396/1
00A4,FreeMail,MS-DOS,Packer,Chad_Nelson,1:109/536
00A5,Meliora,MS-DOS,Packer,Erik_van_Riper,1:107/230
00A6,Foodo,CPM-80,Packer/mailer,Ron_Murray,3:690/640.7
00A7,MSBBS,CPM-80,Packer,Marc_Newman,1:106/601
00A8,Boston_BBS,MS-DOS,Packer/mailer,Tom_Bradford,1:101/625
00A9,XenoMail,MS-DOS,Packer/mailer,Noah_Wood,1:284/14
00AA,XenoLink,Amiga,Packer/mailer,Jonathan_Forbes,1:250/642
00AB,ObjectMatrix,MS-DOS,Packer,Roberto_Ceccarelli,2:332/305.1
00AC,Milquetoast,Win3/MS-DOS,Mailer,Vince_Perriello,1:343/491
00AD,PipBase,MS-DOS,Packer,Roberto_Piola,2:334/306
00AE,EzyMail,MS-DOS,Packer,Peter_Davies,3:636/204
00AF,FastEcho,MS-DOS,Packer,Tobias_Burchhardt,2:245/39
00B0,IOS,Atari_ST/TT,Packer,Rinaldo_Visscher,2:280/3.1
00B1,Communique,MS-DOS,Packer,Ian_Harris,3:620/251
00B2,PointMail,MS-DOS,Packer,Michele_Clinco,2:331/302.11
00B3,Harvey's_Robot,MS-DOS,Packer,Harvey_Parisien,1:249/114
00B4,2daPoint,MS-DOS,Packer,Ron_Pritchett,1:376/74
00B5,CommLink,MS-DOS,Mailer,Steve_Shapiro,1:382/35
00B6,fronttoss,MS-DOS,Packer,Dirk_Astrath,2:241/5603
00B7,SysopPoint,MS-DOS,Packer,Rudolf_Heeb,2:243/44
00B8,PTMAIL,MS-DOS,Packer,Arturo_Krogulski,2:341/27.7
00B9,MHS,MS-DOS/OS2/WINNT,Packer/mailer,Matthias_Hertzog,2:301/402,,19940310
00BA,DLGMail,Amiga,Packer,Steve_Lewis,1:114/52
00BB,GatePrep,MS-DOS,Packer,Andrew_Allen,1:382/92
00BC,Spoint,MS-DOS,Packer,Conrad_Thompson,1:130/29.106
00BD,TurboMail,MS-DOS,Packer,B._J._Weschke,1:2606/403
00BE,FXMAIL,MS-DOS,Packer,Kenneth_Roach,1:208/401
00BF,NextBBS,MS-DOS,Packer/mailer,Tomas_Hood,1:352/777
00C0,EchoToss,MS-DOS,Packer,Mikel_Beck,1:107/218
00C1,SilverBox,Amiga,Packer,David_Lebel,1:240/516
00C2,MBMail,MS-DOS,Packer,Ruud_Uphoff,2:500/116.1928
00C3,SkyFreq,Amiga,Packer,Luca_Spada,2:331/106
00C4,ProMailer,Amiga,Mailer,Ivan_Pintori,2:335/311.21
00C5,Mega_Mail,MS-DOS,Packer/mailer,Mirko_Mucko,2:242/94
00C6,YaBom,MS-DOS,Packer,Berin_Lautenbach,3:620/248
00C7,TachEcho,MS-DOS,Packer,Tom_Zacios,1:107/376
00C8,XAP,MS-DOS,Packer,Jeroen_Smulders,2:512/1.8
00C9,EZMAIL,MS-DOS,Packer,Torben_Paving,2:234/41
00CA,Arc-Binkley,Archimedes,Mailer,Geoff_Riley,2:250/208
00CB,Roser,MS-DOS,Packer,Chan_Kafai,6:700/158
00CC,UU2,MS-DOS,Packer,Dmitri_Zavalishin,2:5020/32
00CD,NMS,MS-DOS,Packer/mailer,Michiel_de.Bruijn,2:285/505.2
00CE,BBCSCAN,Archimedes,Packer/mailer,E._G._Snel,2:512/222.17
00CF,XBBS,MS-DOS,Packer,Mark_Kimes,1:380/16
00D0,LoTek_Vzrul,,Packer/mailer,Kevin_Gates,gates@sasknet.sk.ca,19951229,20000122
00D1,Private_Point_Project,MS-DOS,Packer,Oliver_von_Bueren,2:301/701
00D2,NoSnail,MS-DOS,Packer,Eddie_Rowe,1:19/124
00D3,SmlNet,MS-DOS,Packer,Steve_T._Gove,1:106/6
00D4,STIR,MS-DOS,Packer,Paul_Martin,2:250/107.3
00D5,RiscBBS,Archimedes,Packer,Carl_Declerck,2:292/500.10
00D6,Hercules,Amiga,Packer/mailer,Andrew_Gray,1:231/590
00D7,AMPRGATE,MS-DOS,Packer/mailer,Mike_Bilow,1:323/120.1
00D8,BinkEMSI,MS-DOS,Mailer,Tobias_Burchhardt,2:245/39
00D9,EditMsg,MS-DOS,Packer,G._K._Pace,1:374/26
00DA,Roof,Amiga,Packer,Robert_Williamson,1:167/104
00DB,QwkPkt,MS-DOS,Packer,Ross_West,1:250/412
00DC,MARISCAN,MS-DOS,Packer,Mario_Elkati,2:341/14.9
00DD,NewsFlash,MS-DOS,Packer,Chris_Lueders,2:241/5306
00DE,Paradise,MS-DOS,Packer/mailer,Kenneth_Wall,1:300/5
00DF,DogMatic-ACB,N/A,Packer/mailer,Martin_Allard,2:245/48
00E0,T-Mail,MS-DOS,Packer/mailer,Andy_Elkin,2:5030/15
00E1,JetMail,Atari_ST/STE/TT,Packer,Daniel_Roesen,2:243/93.8
00E2,MainDoor,MS-DOS,Packer/mailer,Francisco_Sedano,2:341/20
00E3,Starnet_Products,MS-DOS/OS2,Mailer/Packer,Starnet_Software_Development,1:102/925,,19951209
00E4,BMB,Amiga,Packer,Dentato_Remo,2:335/311.33
00E5,BNP,MS-DOS,Packer,Nathan_Moschkin,1:109/427
00E6,MailMaster,MS-DOS,Packer/mailer,Gary_Murphy,1:130/85
00E7,Mail_Manager_+Plus+,MS-DOS,Packer,Chip_Morrow,1:226/1240
00E8,BloufGate,Atari_ST/Unix,Packer,Vincent_Pomey,2:320/100.2
00E9,CrossPoint,MS-DOS,Packer/mailer,Peter_Mandrella,2:2454/97.80,19920713,19960601
00EA,DeltaEcho,MS-DOS,Packer,Mikael_Staldal,2:201/337
00EB,ALLFIX,MS-DOS,Packer,Harald_Harms,2:512/145
00EC,NetWay,Archimedes,Mailer,Steve_Haslam,2:250/116.3
00ED,MARSmail,Atari_ST,Packer,Folkert_val_Heusden,2:285/750.2,,19940122
00EE,ITRACK,MS-DOS/OS2,Packer,Frank_Prade,2:2480/55,,19990119
00EF,GateUtil,MS-DOS,Packer,Michael_Skurka,1:397/2.1
00F0,Bert,MS-DOS,Packer/mailer,Arnim_Wiezer,2:241/2104.9
00F1,Techno,MS-DOS,Packer,Patrik_Holmsten,2:203/133
00F2,AutoMail,MS-DOS,Packer,Mats_Wallin,2:201/239
00F3,April,Amiga,Packer,Nick_de_Jong,2:282/309.3
00F4,Amanda,MS-DOS,Packer,David_Douthitt,1:121/99.14
00F5,NmFwd,MS-DOS,Packer,Alberto_Pasquale,2:332/504
00F6,FileScan,MS-DOS,Packer,Matthias_Duesterhoeft,2:241/4512.2
00F7,FredMail,MS-DOS,Packer,Michael_Butler,3:712/515
00F8,TP_Kom,MS-DOS,Packer/mailer,Per_Sten,2:201/124
00F9,FidoZerb,MS-DOS,Packer,Ulrich_Schlechte,2:241/3410.12
00FA,!!MessageBase,MS-DOS,Packer/mailer,Holger_Lembke,2:240/500.20
00FB,EMFido,Amiga,Packer,Gary_Glendown,2:249/3.999
00FC,GS-Toss,MS-DOS,Packer,Marco_Bungalski,2:241/2021
00FD,QWKDoor,Atari_ST,Packer,Christian_Limpach,2:270/20.1
00FE,No_product_id_allocated,Any,Packer,No_Author,3:3/20
00FF,16-bit_product_id,Any,Packer/Mailer,No_Author,3:3/20
0100,Reserved,None,None,No_Author,3:3/20,19951209
0101,The_Brake!,Mailer,John_Gladkih,2:5051/16,19951209
0102,Zeus_BBS,Amiga,Mailer,Alex_May,2:441/58.0,19951209
0103,XenoPhobe-Mailer,Msdos/Windows/OS2/Linux,Mailer,Peter_Kling,1:374/969.0,19951209
0104,None,None,None,None,0:0/0,
0105,Terminate,Msdos/Os2/Windows,Mailer/Packer,SerWiz_Comm_&_Bo_Bendtsen,2:254/261,19951209
0106,TeleMail,Msdos,Mailer/Packer,Juergen_Weigelt,2:2453/900,19951209
0107,CMBBS,Msdos/Os2,Mailer/Packer,Christof_Engel,2:2490/5110,19951209
0108,Shuttle,Windows,Mailer/Packer,MCH_Development_&_Marvin_Hart,1:106/500,19951209
0109,Quater,Amiga,Mailer,Felice_Murolo,2:335/206,19951209
010A,Windo,Windows,Mailer,Alan_Chavis,1:147/55,19951209
010B,Xenia,Msdos/Os2,Mailer,Arjen_Lentz,2:283/512,19960601
010C,GMS,AmigaOS,Mailer,Mirko_Viviani,2:331/213,19960601
010D,HNET,Msdos,???,Pedro_Jaramillo,1:102/160,19960601
010E,Shotgun_Professional,Msdos,???,Brent_Shellenberg,1:140/146,19960621
010F,SLIPgate,Msdos,???,Kieran_Morrissey,3:634/376,19960723
0110,BBBS,MSDOS/OS2/NT/Amiga/Unix,Mailer/Packer,Kim_Heino,2:22/222,19980216
0111,NewsGate,Windows/NT,Packer/Gateway,Leilo_denna_Pietra,2:335/244,19980216
01FF,BBBS,MSDOS/OS2/NT/Amiga/Unix,Mailer/Packer,Kim_Heino,2:22/222,19980216
02FF,NewsGate,Windows/NT,Packer/Gateway,Leilo_denna_Pietra,2:335/244,19980216
03FF,Ravel,Macintosh,Mailer/Packer,Cyril_Moorzin,2:5030/700,19980310
04FF,Beemail,Windows,Mailer/Packer,Andrius_Cepaitis,2:470/1,19980310
05FF,QuickToss,DOS,Packer,Sandra_Godinez,1:387/601.3,19980310
06FF,SpaceMail,???,Mailer,Andreas_Habicht,2:244/6121,19980710
07FF,Argus,Windows/NT,Mailer,Max_Masyutin,2:469/84,19990216
08FF,Hurricane,Windows/NT/Solaris,Packer,Paul_Walker,2:254/175.44,19990216
09FF,Hub_Mailer,OS2,Mailer,Viatcheslav_Odintsov,2:5020/181,19990216
0AFF,FDInt,MSDOS,Packer,Colin_Turner,2:443/13,19990216
0BFF,GPMail,OS2,Mailer,Igor_Vanin,2:5030/448,19990216
0CFF,FTrack,NT/OS2,Tracker,Fyodor_Ustinov,2:5020/79,19990313
0DFF,Nice_Tosser,DOS/OS2/Win32,Tosser,Robert_Agababyan,2:5020/234.1,19990518
0EFF,LuckyGate,DOS/OS2/Linux,Packer,Pavel_Gulchouck,2:463/68,19990709
0FFF,McMail,DOS,Mailer,Simon_Slater,2:443/777,20000102
10FF,HPT,DOS/OS2/Win32/Unix/BeOS,Packer,Dmitry_Sergienko,2:464/910,20030215
11FF,MBSEBBS,Linux/FreeBSD/NetBSD,Mailer/Packer,Michiel_Broek,2:280/2802,20030215
12FF,SBBSecho,DOS/OS2/Win32/Linux/FreeBSD/OpenBSD/Solaris,Packer,Rob_Swindell,1:103/705,20030215
13FF,binkd,DOS/OS2/Win32/Unix,Mailer,Pavel_Gulchouck,2:463/68,20030215
14FF,Mail-ennium/32,Win32,Mailer/Packer,Chris_Cranford,1:379/1200,20031231
15FF,Radius,Win32,Mailer,Denis_Voituk,2:5012/38,20040115
16FF,RNtrack,Linux/BSD/AIX/Solaris/MacOSX/OS2/DOS/Win32,Packer,Alex_Soukhotine,2:5030/1157,20050115

230
lib/getheader.c Normal file
View File

@@ -0,0 +1,230 @@
/*****************************************************************************
*
* $Id: getheader.c,v 1.14 2006/03/20 12:36:21 mbse Exp $
* Purpose ...............: Read fidonet .pkt header
*
*****************************************************************************
* 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "mbselib.h"
faddr pktfrom;
char pktpwd[9];
/*
* Return codes:
* 0 - All Seems Well
* 1 - Invalid type (not 2 or 2+)
* 2 - Read header error
* 3 - Not for me
* 4 - Password error
* 5 - Unsecure session
*
* If session is TRUE, the password is checked as being the session password,
* otherwise it is checked as the mail password.
*/
int getheader(faddr *f, faddr *t, FILE *pkt, char *pname, int session)
{
unsigned char buffer[0x3a];
int i, capword, prodx, major, minor = 0, tome = FALSE;
char *p, *prodn = NULL, *fa, *ta, buf[5];
int year, month, day, hour, min, sec;
f->domain = NULL;
f->name = NULL;
t->domain = NULL;
t->name = NULL;
/*
* Read type 2+ packet header, see FSC-0039 version 4 and FTS-0001
*/
if (fread(buffer, 1, 0x3a, pkt) != 0x3a) {
WriteError("Could not read header (%s)", pname);
return 2;
}
if ((buffer[0x12] + (buffer[0x13] << 8)) != 2) {
WriteError("Not a type 2 packet (%s)", pname);
return 1;
}
f->node = (buffer[0x01] << 8) + buffer[0x00];
t->node = (buffer[0x03] << 8) + buffer[0x02];
f->net = (buffer[0x15] << 8) + buffer[0x14];
t->net = (buffer[0x17] << 8) + buffer[0x16];
f->zone = (buffer[0x23] << 8) + buffer[0x22];
t->zone = (buffer[0x25] << 8) + buffer[0x24];
year = (buffer[0x05] << 8) + buffer[0x04];
/*
* Check for Y2K bugs, if there are any this is not important,
* it is just for logging!
*/
if (year < 50)
year = year + 2000;
else if (year < 1900)
year = year + 1900;
month = (buffer[0x07] << 8) + buffer[0x06] + 1;
day = (buffer[0x09] << 8) + buffer[0x08];
hour = (buffer[0x0b] << 8) + buffer[0x0a];
min = (buffer[0x0d] << 8) + buffer[0x0c];
sec = (buffer[0x0f] << 8) + buffer[0x0e];
prodx = buffer[0x18];
major = buffer[0x19];
capword = (buffer[0x2d] << 8) + buffer[0x2c];
if (capword != ((buffer[0x28] << 8) + buffer[0x29]))
capword = 0;
if (capword & 0x0001) {
/*
* FSC-0039 packet type 2+
*/
prodx = prodx + (buffer[0x2a] << 8);
minor = buffer[0x2b];
f->zone = buffer[0x2e] + (buffer[0x2f] << 8);
t->zone = buffer[0x30] + (buffer[0x31] << 8);
f->point = buffer[0x32] + (buffer[0x33] << 8);
t->point = buffer[0x34] + (buffer[0x35] << 8);
} else {
/*
* Stone age @%#$@
*/
f->zone = buffer[0x22] + (buffer[0x23] << 8);
t->zone = buffer[0x24] + (buffer[0x25] << 8);
if ((f->zone == 0) && (t->zone == 0)) {
/*
* No zone info, since the packet should be for us, guess the zone
* against our aka's from the setup using a 2d test.
*/
for (i = 0; i < 40; i++) {
if ((CFG.akavalid[i]) && (t->net == CFG.aka[i].net) && (t->node == CFG.aka[i].node)) {
t->zone = CFG.aka[i].zone;
f->zone = CFG.aka[i].zone;
Syslog('!', "Warning, zone %d assumed", CFG.aka[i].zone);
break;
}
}
}
}
for (i = 0; i < 8; i++)
pktpwd[i] = buffer[0x1a + i];
pktpwd[8]='\0';
for (p = pktpwd + 7; (p >= pktpwd) && (*p == ' '); p--) *p='\0';
if (pktpwd[0])
f->name = pktpwd;
/*
* Fill in a default product code in case it doesn't exist
*/
snprintf(buf, 5, "%04x", prodx);
prodn = xstrcpy((char *)"Unknown 0x");
prodn = xstrcat(prodn, buf);
for (i = 0; ftscprod[i].name; i++)
if (ftscprod[i].code == prodx) {
free(prodn);
prodn = xstrcpy(ftscprod[i].name);
break;
}
pktfrom.name = NULL;
pktfrom.domain = NULL;
pktfrom.zone = f->zone;
pktfrom.net = f->net;
pktfrom.node = f->node;
if (capword & 0x0001)
pktfrom.point = f->point;
else
pktfrom.point = 0;
for (i = 0; i < 40; i++) {
if ((CFG.akavalid[i]) && ((t->zone == 0) || (t->zone == CFG.aka[i].zone)) &&
(t->net == CFG.aka[i].net) && (t->node == CFG.aka[i].node) &&
((!(capword & 0x0001)) || (t->point == CFG.aka[i].point) || (t->point && !CFG.aka[i].point)))
tome = TRUE;
}
fa = xstrcpy(ascfnode(f, 0x1f));
ta = xstrcpy(ascfnode(t, 0x1f));
Syslog('+', "Packet : %s type %s", pname, (capword & 0x0001) ? "2+":"stone-age");
Syslog('+', "From : %s to %s", fa, ta);
Syslog('+', "Dated : %02u-%02u-%u %02u:%02u:%02u", day, month, year, hour, min, sec);
Syslog('+', "Program : %s %d.%d", prodn, major, minor);
free(ta);
free(fa);
if (capword & 0x0001) {
buf[0] = buffer[0x36];
buf[1] = buffer[0x37];
buf[2] = buffer[0x38];
buf[3] = buffer[0x39];
buf[4] = '\0';
}
if (prodn)
free(prodn);
if (!tome)
return 3;
if (session) {
/*
* FTS-0001 session setup mode.
*/
if (noderecord(f) && strlen(nodes.Spasswd)) {
if (strcasecmp(nodes.Spasswd, pktpwd) == 0) {
return 0; /* Secure session */
} else {
Syslog('!', "Password : got \"%s\", expected \"%s\"", pktpwd, nodes.Spasswd);
return 4; /* Bad password */
}
} else {
Syslog('+', "Node not in setup or no password set");
return 5; /* Unsecure session */
}
} else {
/*
* Mail password check
*/
if (noderecord(f) && nodes.MailPwdCheck && strlen(nodes.Epasswd)) {
if (strcasecmp(nodes.Epasswd, pktpwd) == 0) {
return 0; /* Password Ok */
} else {
Syslog('!', "Password : got \"%s\", expected \"%s\"", pktpwd, nodes.Epasswd);
return 4; /* Bad password */
}
} else {
return 0; /* Not checked, still Ok */
}
}
return 0;
}

167
lib/gmtoffset.c Normal file
View File

@@ -0,0 +1,167 @@
/*****************************************************************************
*
* $Id: gmtoffset.c,v 1.9 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: Calculate UTC offset
* Source ................: Eugene G. Crosser's ifmail package.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
/*
* Returns the offset from your location to UTC. So in the MET timezone
* this returns -60 (wintertime). People in the USA get positive results.
*/
int gmt_offset(time_t now)
{
struct tm ptm;
struct tm gtm;
int offset;
if (!now)
now = time(NULL);
ptm = *localtime(&now);
/*
* To get the timezone, compare localtime with GMT.
*/
gtm = *gmtime(&now);
/*
* Assume we are never more than 24 hours away.
*/
offset = gtm.tm_yday - ptm.tm_yday;
if (offset > 1)
offset = -24;
else if (offset < -1)
offset = 24;
else
offset *= 24;
/*
* Scale in the hours and minutes; ignore seconds.
*/
offset += gtm.tm_hour - ptm.tm_hour;
offset *= 60;
offset += gtm.tm_min - ptm.tm_min;
return offset;
}
/*
* Returns the TZUTC string, note that the sign is opposite from the
* function above.
*/
char *gmtoffset(time_t now)
{
static char buf[6]="+0000";
char sign;
int hr, min;
int offset;
offset = gmt_offset(now);
if (offset <= 0) {
sign = '+';
offset = -offset;
} else
sign = '-';
hr = offset / 60L;
min = offset % 60L;
if (sign == '-')
snprintf(buf, 6, "%c%02d%02d", sign, hr, min);
else
snprintf(buf, 6, "%02d%02d", hr, min);
return(buf);
}
char *str_time(time_t total)
{
static char buf[10];
int h, m;
memset(&buf, 0, sizeof(buf));
/*
* 0 .. 59 seconds
*/
if (total < (time_t)60) {
snprintf(buf, 10, "%2d.00s", (int)total);
return buf;
}
/*
* 1:00 .. 59:59 minutes:seconds
*/
if (total < (time_t)3600) {
h = total / 60;
m = total % 60;
snprintf(buf, 10, "%2d:%02d ", h, m);
return buf;
}
/*
* 1:00 .. 23:59 hours:minutes
*/
if (total < (time_t)86400) {
h = (total / 60) / 60;
m = (total / 60) % 60;
snprintf(buf, 10, "%2d:%02dm", h, m);
return buf;
}
/*
* 1/00 .. 30/23 days/hours
*/
if (total < (time_t)2592000) {
h = (total / 3600) / 24;
m = (total / 3600) % 24;
snprintf(buf, 10, "%2d/%02dh", h, m);
return buf;
}
snprintf(buf, 10, "N/A ");
return buf;
}
char *t_elapsed(time_t start, time_t end)
{
return str_time(end - start);
}

45
lib/hdr.c Normal file
View File

@@ -0,0 +1,45 @@
/*****************************************************************************
*
* $Id: hdr.c,v 1.5 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: Header parser
*
*****************************************************************************
* 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 "mbselib.h"
char *hdr(char *key, rfcmsg *msg)
{
for (; msg; msg = msg->next)
if (!strcasecmp(key, msg->key)) {
return(msg->val);
}
return(NULL);
}

196
lib/jam.h Normal file
View File

@@ -0,0 +1,196 @@
/*
** JAM(mbp) - The Joaquim-Andrew-Mats Message Base Proposal
**
** C API
**
** Written by Joaquim Homrighausen.
**
** ----------------------------------------------------------------------
**
** jam.h (JAMmb)
**
** Prototypes and definitions for the JAM message base format
**
** Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch, and
** Mats Wallin. ALL RIGHTS RESERVED.
**
** 93-06-28 JoHo
** Initial coding.
**
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __JAM_H__
#define __JAM_H__
#ifndef __JAMSYS_H__
#include "jamsys.h"
#endif
/*
** File extensions
*/
#define EXT_HDRFILE ".jhr"
#define EXT_TXTFILE ".jdt"
#define EXT_IDXFILE ".jdx"
#define EXT_LRDFILE ".jlr"
/*
** Revision level and header signature
*/
#define CURRENTREVLEV 1
#define HEADERSIGNATURE "JAM"
/*
** Header file information block, stored first in all .JHR files
*/
typedef struct
{
CHAR8 Signature[4]; /* <J><A><M> followed by <NUL> */
UINT32 DateCreated; /* Creation date */
UINT32 ModCounter; /* Last processed counter */
UINT32 ActiveMsgs; /* Number of active (not deleted) msgs */
UINT32 PasswordCRC; /* CRC-32 of password to access */
UINT32 BaseMsgNum; /* Lowest message number in index file */
CHAR8 RSRVD[1000]; /* Reserved space */
}
JAMHDRINFO, _JAMDATA * JAMHDRINFOptr;
/*
** Message status bits
*/
#define MSG_LOCAL 0x00000001L /* Msg created locally */
#define MSG_INTRANSIT 0x00000002L /* Msg is in-transit */
#define MSG_PRIVATE 0x00000004L /* Private */
#define MSG_READ 0x00000008L /* Read by addressee */
#define MSG_SENT 0x00000010L /* Sent to remote */
#define MSG_KILLSENT 0x00000020L /* Kill when sent */
#define MSG_ARCHIVESENT 0x00000040L /* Archive when sent */
#define MSG_HOLD 0x00000080L /* Hold for pick-up */
#define MSG_CRASH 0x00000100L /* Crash */
#define MSG_IMMEDIATE 0x00000200L /* Send Msg now, ignore restrictions */
#define MSG_DIRECT 0x00000400L /* Send directly to destination */
#define MSG_GATE 0x00000800L /* Send via gateway */
#define MSG_FILEREQUEST 0x00001000L /* File request */
#define MSG_FILEATTACH 0x00002000L /* File(s) attached to Msg */
#define MSG_TRUNCFILE 0x00004000L /* Truncate file(s) when sent */
#define MSG_KILLFILE 0x00008000L /* Delete file(s) when sent */
#define MSG_RECEIPTREQ 0x00010000L /* Return receipt requested */
#define MSG_CONFIRMREQ 0x00020000L /* Confirmation receipt requested */
#define MSG_ORPHAN 0x00040000L /* Unknown destination */
#define MSG_ENCRYPT 0x00080000L /* Msg text is encrypted */
#define MSG_COMPRESS 0x00100000L /* Msg text is compressed */
#define MSG_ESCAPED 0x00200000L /* Msg text is seven bit ASCII */
#define MSG_FPU 0x00400000L /* Force pickup */
#define MSG_TYPELOCAL 0x00800000L /* Msg is for local use only (not for export) */
#define MSG_TYPEECHO 0x01000000L /* Msg is for conference distribution */
#define MSG_TYPENET 0x02000000L /* Msg is direct network mail */
#define MSG_NODISP 0x20000000L /* Msg may not be displayed to user */
#define MSG_LOCKED 0x40000000L /* Msg is locked, no editing possible */
#define MSG_DELETED 0x80000000L /* Msg is deleted */
/*
** Message header
*/
typedef struct
{
CHAR8 Signature[4]; /* <J><A><M> followed by <NUL> */
UINT16 Revision; /* CURRENTREVLEV */
UINT16 ReservedWord; /* Reserved */
UINT32 SubfieldLen; /* Length of subfields */
UINT32 TimesRead; /* Number of times message read */
UINT32 MsgIdCRC; /* CRC-32 of MSGID line */
UINT32 ReplyCRC; /* CRC-32 of REPLY line */
UINT32 ReplyTo; /* This msg is a reply to.. */
UINT32 Reply1st; /* First reply to this msg */
UINT32 ReplyNext; /* Next msg in reply chain */
UINT32 DateWritten; /* When msg was written */
UINT32 DateReceived; /* When msg was received/read */
UINT32 DateProcessed; /* When msg was processed by packer */
UINT32 MsgNum; /* Message number (1-based) */
UINT32 Attribute; /* Msg attribute, see "Status bits" */
UINT32 Attribute2; /* Reserved for future use */
UINT32 TxtOffset; /* Offset of text in text file */
UINT32 TxtLen; /* Length of message text */
UINT32 PasswordCRC; /* CRC-32 of password to access msg */
UINT32 Cost; /* Cost of message */
}
JAMHDR, _JAMDATA * JAMHDRptr;
/*
** Message header subfield types
*/
#define JAMSFLD_OADDRESS 0
#define JAMSFLD_DADDRESS 1
#define JAMSFLD_SENDERNAME 2
#define JAMSFLD_RECVRNAME 3
#define JAMSFLD_MSGID 4
#define JAMSFLD_REPLYID 5
#define JAMSFLD_SUBJECT 6
#define JAMSFLD_PID 7
#define JAMSFLD_TRACE 8
#define JAMSFLD_ENCLFILE 9
#define JAMSFLD_ENCLFWALIAS 10
#define JAMSFLD_ENCLFREQ 11
#define JAMSFLD_ENCLFILEWC 12
#define JAMSFLD_ENCLINDFILE 13
#define JAMSFLD_EMBINDAT 1000
#define JAMSFLD_FTSKLUDGE 2000
#define JAMSFLD_SEENBY2D 2001
#define JAMSFLD_PATH2D 2002
#define JAMSFLD_FLAGS 2003
#define JAMSFLD_TZUTCINFO 2004
#define JAMSFLD_UNKNOWN 0xffff
/*
** Message header subfield
*/
typedef struct
{
UINT16 LoID; /* Field ID, 0 - 0xffff */
UINT16 HiID; /* Reserved for future use */
UINT32 DatLen; /* Length of buffer that follows */
CHAR8 Buffer[1]; /* DatLen bytes of data */
}
JAMSUBFIELD, _JAMDATA * JAMSUBFIELDptr;
typedef struct
{
UINT16 LoID; /* Field ID, 0 - 0xffff */
UINT16 HiID; /* Reserved for future use */
UINT32 DatLen; /* Length of buffer that follows */
}
JAMBINSUBFIELD, _JAMDATA * JAMBINSUBFIELDptr;
/*
** Message index record
*/
typedef struct
{
UINT32 UserCRC; /* CRC-32 of destination username */
UINT32 HdrOffset; /* Offset of header in .JHR file */
}
JAMIDXREC, _JAMDATA * JAMIDXRECptr;
/*
** Lastread structure, one per user
*/
typedef struct
{
UINT32 UserCRC; /* CRC-32 of user name (lowercase) */
UINT32 UserID; /* Unique UserID */
UINT32 LastReadMsg; /* Last read message number */
UINT32 HighReadMsg; /* Highest read message number */
}
JAMLREAD, _JAMDATA * JAMLREADptr;
#endif /* __JAM_H__ */
#ifdef __cplusplus
}
#endif
/* end of file "jam.h" */

1543
lib/jammsg.c Normal file

File diff suppressed because it is too large Load Diff

30
lib/jammsg.h Normal file
View File

@@ -0,0 +1,30 @@
/* $Id: jammsg.h,v 1.3 2005/10/11 20:49:42 mbse Exp $ */
#ifndef _JAMMSG_H
#define _JAMMSG_H
int JAM_AddMsg(void);
void JAM_Close(void);
int JAM_Delete(unsigned int);
void JAM_DeleteJAM(char *);
int JAM_GetLastRead(lastread *);
unsigned int JAM_Highest(void);
int JAM_Lock(unsigned int);
unsigned int JAM_Lowest(void);
void JAM_New(void);
int JAM_NewLastRead(lastread);
int JAM_Next(unsigned int *);
unsigned int JAM_Number(void);
int JAM_Open(char *);
void JAM_Pack(void);
int JAM_Previous(unsigned int *);
int JAM_ReadHeader(unsigned int);
int JAM_Read(unsigned int, int);
int JAM_SetLastRead(lastread);
void JAM_UnLock(void);
int JAM_WriteHeader(unsigned int);
#endif

102
lib/jamsys.h Normal file
View File

@@ -0,0 +1,102 @@
/*
** $Id: jamsys.h,v 1.2 2005/10/11 20:49:42 mbse Exp $
**
** JAM(mbp) - The Joaquim-Andrew-Mats Message Base Proposal
**
** C API
**
** Written by Joaquim Homrighausen and Mats Wallin.
**
** ----------------------------------------------------------------------
**
** jamsys.h (JAMmb)
**
** Compiler and platform dependant definitions
**
** Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch, and
** Mats Wallin. ALL RIGHTS RESERVED.
**
** 93-06-28 JoHo/MW
** Initial coding.
*/
#ifndef __JAMSYS_H__
#define __JAMSYS_H__
/*
** The following assumptions are made about compilers and platforms:
**
** __MSDOS__ Defined if compiling for MS-DOS
** _WINDOWS Defined if compiling for Microsoft Windows
** __NT__ Defined if compiling for Windows NT
** __OS2__ Defined if compiling for OS/2 2.x
** __sparc__ Defined if compiling for Sun Sparcstation
** __50SERIES Defined if compiling for Prime with Primos
**
** __SMALL__ Defined if compiling under MS-DOS in small memory model
** __MEDIUM__ Defined if compiling under MS-DOS in medium memory model
** __COMPACT__ Defined if compiling under MS-DOS in compact memory model
** __LARGE__ Defined if compiling under MS-DOS in large memory model
**
** __ZTC__ Zortech C++ 3.x
** __BORLANDC__ Borland C++ 3.x
** __TURBOC__ Turbo C 2.0
** __TSC__ JPI TopSpeed C 1.06
** _MSC_VER Microsoft C 6.0 and later
** _QC Microsoft Quick C
*/
typedef int INT32; /* 32 bits signed integer */
typedef unsigned int UINT32; /* 32 bits unsigned integer */
typedef short int INT16; /* 16 bits signed integer */
typedef unsigned short int UINT16; /* 16 bits unsigned integer */
typedef char CHAR8; /* 8 bits signed integer */
typedef unsigned char UCHAR8; /* 8 bits unsigned integer */
typedef int FHANDLE; /* File handle */
#define _JAMFAR
#define _JAMPROC
#define _JAMDATA
typedef INT32 _JAMDATA * INT32ptr;
typedef UINT32 _JAMDATA * UINT32ptr;
typedef INT16 _JAMDATA * INT16ptr;
typedef UINT16 _JAMDATA * UINT16ptr;
typedef CHAR8 _JAMDATA * CHAR8ptr;
typedef UCHAR8 _JAMDATA * UCHAR8ptr;
typedef void _JAMDATA * VOIDptr;
/*
** Values for "AccessMode" and "ShareMode" parameter to JAMsysSopen.
*/
#define JAMO_RDWR O_RDWR
#define JAMO_RDONLY O_RDONLY
#define JAMO_WRONLY O_WRONLY
#define JAMSH_DENYNO 0
#define JAMSH_DENYRD 0
#define JAMSH_DENYWR 0
#define JAMSH_DENYRW 0
/*
** Structure to contain date/time information
*/
typedef struct JAMtm
{
int tm_sec, /* Seconds 0..59 */
tm_min, /* Minutes 0..59 */
tm_hour, /* Hour of day 0..23 */
tm_mday, /* Day of month 1..31 */
tm_mon, /* Month 0..11 */
tm_year, /* Years since 1900 */
tm_wday, /* Day of week 0..6 (Sun..Sat) */
tm_yday, /* Day of year 0..365 */
tm_isdst; /* Daylight savings time (not used) */
} JAMTM, _JAMDATA * JAMTMptr;
#endif /* __JAMSYS_H__ */
/* end of file "jamsys.h" */

101
lib/magic.c Normal file
View File

@@ -0,0 +1,101 @@
/*****************************************************************************
*
* $Id: magic.c,v 1.3 2007/03/03 14:28:40 mbse Exp $
* Purpose ...............: Magic filename handling
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
/*
* Update magic alias with new filename.
*/
void magic_update(char *Alias, char *FileName)
{
char *path;
FILE *fp;
if (!strlen(CFG.req_magic)) {
WriteError("No magic filename path configured");
return;
}
path = xstrcpy(CFG.req_magic);
path = xstrcat(path, (char *)"/");
path = xstrcat(path, Alias);
if ((fp = fopen(path, "w")) == NULL) {
WriteError("$Can't create %s", path);
free(path);
return;
}
fprintf(fp, "%s\n", FileName);
fclose(fp);
chmod(path, 0644);
free(path);
}
/*
* Check if magic filename is valid.
*/
int magic_check(char *Alias, char *FileName)
{
char *path;
FILE *fp;
int rc = -1;
if (!strlen(CFG.req_magic)) {
WriteError("magic_check(): no magic filename path configured");
return -1;
}
path = xstrcpy(CFG.req_magic);
path = xstrcat(path, (char *)"/");
path = xstrcat(path, Alias);
if ((fp = fopen(path, "r")) == NULL) {
WriteError("$No magic alias %s", path);
free(path);
return -1;
}
free(path);
path = calloc(PATH_MAX, sizeof(char));
fgets(path, PATH_MAX -1, fp);
fclose(fp);
Striplf(path);
if (strcmp(path, FileName) == 0)
rc = 0;
free(path);
return rc;
}

470
lib/mangle.c Normal file
View File

@@ -0,0 +1,470 @@
/*****************************************************************************
*
* $Id: mangle.c,v 1.19 2007/03/03 14:28:40 mbse Exp $
* Purpose ...............: Mangle a unix name to DOS 8.3 filename
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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.
*****************************************************************************
* Ideas taken from Samba, Copyright (C) Andrew Tridgell 1992-1998
*****************************************************************************/
#include "../config.h"
#include "mbselib.h"
/*
* Prototype functions
*/
int strhaslower(const char *);
char *safe_strcpy(char *, const char *, size_t);
static void init_chartest(void);
static int is_reserved_msdos(char *);
int is_8_3(char *);
#define PTR_DIFF(p1,p2) ((int)(((const char *)(p1)) - (const char *)(p2)))
/* -------------------------------------------------------------------------- **
* Other stuff...
*
* magic_char - This is the magic char used for mangling. It's global.
*
* MANGLE_BASE - This is the number of characters we use for name mangling.
*
* basechars - The set characters used for name mangling. This
* is static (scope is this file only).
*
* mangle() - Macro used to select a character from basechars (i.e.,
* mangle(n) will return the nth digit, modulo MANGLE_BASE).
*
* chartest - array 0..255. The index range is the set of all possible
* values of a byte. For each byte value, the content is a
* two nibble pair. See BASECHAR_MASK and ILLEGAL_MASK,
* below.
*
* ct_initialized - False until the chartest array has been initialized via
* a call to init_chartest().
*
* BASECHAR_MASK - Masks the upper nibble of a one-byte value.
*
* ILLEGAL_MASK - Masks the lower nibble of a one-byte value.
*
* isillegal() - Given a character, check the chartest array to see
* if that character is in the illegal characters set.
* This is faster than using strchr().
*
*/
char magic_char = '~';
static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1)
static unsigned char chartest[256] = { 0 };
static int ct_initialized = FALSE;
#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
#define BASECHAR_MASK 0xf0
#define ILLEGAL_MASK 0x0f
#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK )
/****************************************************************************
does a string have any lowercase chars in it?
****************************************************************************/
int strhaslower(const char *s)
{
while (*s) {
if (islower(*s))
return TRUE;
s++;
}
return FALSE;
}
/*******************************************************************
safe string copy into a known length string. maxlength does not
include the terminating zero.
********************************************************************/
char *safe_strcpy(char *dest,const char *src, size_t maxlength)
{
size_t len;
if (!dest) {
Syslog('+', "ERROR: NULL dest in safe_strcpy");
return NULL;
}
if (!src) {
*dest = 0;
return dest;
}
len = strlen(src);
if (len > maxlength) {
WriteError("ERROR: string overflow by %d in safe_strcpy [%.50s]", (int)(len-maxlength), src);
len = maxlength;
}
memcpy(dest, src, len);
dest[len] = 0;
return dest;
}
/* ************************************************************************** **
* Initialize the static character test array.
*
* Input: none
*
* Output: none
*
* Notes: This function changes (loads) the contents of the <chartest>
* array. The scope of <chartest> is this file.
*
* ************************************************************************** **
*/
static void init_chartest( void )
{
char *illegalchars = (char *)"*\\/?<>|\":";
unsigned char *s;
memset( (char *)chartest, '\0', 256 );
for( s = (unsigned char *)illegalchars; *s; s++ )
chartest[*s] = ILLEGAL_MASK;
for( s = (unsigned char *)basechars; *s; s++ )
chartest[*s] |= BASECHAR_MASK;
ct_initialized = TRUE;
} /* init_chartest */
/* ************************************************************************** **
* Return True if a name is a special msdos reserved name.
*
* Input: fname - String containing the name to be tested.
*
* Output: True, if the name matches one of the list of reserved names.
*
* Notes: This is a static function called by is_8_3(), below.
*
* ************************************************************************** **
*/
static int is_reserved_msdos( char *fname )
{
char upperFname[13];
char *p;
strncpy (upperFname, fname, 12);
/* lpt1.txt and con.txt etc are also illegal */
p = strchr(upperFname,'.');
if (p)
*p = '\0';
tu(upperFname);
p = upperFname + 1;
switch (upperFname[0]) {
case 'A':
if( 0 == strcmp( p, "UX" ) )
return TRUE;
break;
case 'C':
if ((0 == strcmp( p, "LOCK$" )) || (0 == strcmp( p, "ON" )) || (0 == strcmp( p, "OM1" ))
|| (0 == strcmp( p, "OM2" )) || (0 == strcmp( p, "OM3" )) || (0 == strcmp( p, "OM4" )))
return TRUE;
break;
case 'L':
if( (0 == strcmp( p, "PT1" )) || (0 == strcmp( p, "PT2" )) || (0 == strcmp( p, "PT3" )))
return TRUE;
break;
case 'N':
if( 0 == strcmp( p, "UL" ) )
return TRUE;
break;
case 'P':
if( 0 == strcmp( p, "RN" ) )
return TRUE;
break;
}
return FALSE;
} /* is_reserved_msdos */
/* ************************************************************************** **
* Return True if the name is a valid DOS name in 8.3 DOS format.
*
* Input: fname - File name to be checked.
* check_case - If True, then the
* name will be checked to see if all characters
* are the correct case.
*
* Output: True if the name is a valid DOS name, else FALSE.
*
* ************************************************************************** **
*/
int is_8_3( char *fname)
{
int len;
int l, i;
char *p;
char *dot_pos;
char *slash_pos = strrchr( fname, '/' );
/* If there is a directory path, skip it. */
if (slash_pos)
fname = slash_pos + 1;
len = strlen(fname);
/* Can't be 0 chars or longer than 12 chars */
if ((len == 0) || (len > 12))
return FALSE;
/* Mustn't be an MS-DOS Special file such as lpt1 or even lpt1.txt */
if (is_reserved_msdos(fname))
return FALSE;
init_chartest();
for (i = 0; i < strlen(fname); i++) {
if (isillegal(fname[i])) {
Syslog('+', "Illegal character in filename");
return FALSE;
}
}
/* Can't contain invalid dos chars */
p = fname;
dot_pos = NULL;
while (*p) {
if (*p == '.' && !dot_pos)
dot_pos = (char *)p;
p++;
}
/* no dot and less than 9 means OK */
if (!dot_pos)
return (len <= 8);
l = PTR_DIFF(dot_pos, fname);
/* base must be at least 1 char except special cases . and .. */
if (l == 0)
return(0 == strcmp( fname, "." ) || 0 == strcmp( fname, ".." ));
/* base can't be greater than 8 */
if (l > 8)
return FALSE;
if (len - l == 1 && !strchr( dot_pos + 1, '.' )) {
*dot_pos = 0;
return TRUE;
}
/* extension must be between 1 and 3 */
if ((len - l < 2 ) || (len - l > 4))
return FALSE;
/* extensions may not have a dot */
if (strchr( dot_pos+1, '.' ))
return FALSE;
/* must be in 8.3 format */
return TRUE;
}
/*****************************************************************************
* do the actual mangling to 8.3 format
* the buffer must be able to hold 13 characters (including the null)
*****************************************************************************
*/
void mangle_name_83(char *s)
{
int crc16, i;
char *p, *q;
char extension[4];
char base[9];
int baselen = 0;
int extlen = 0;
extension[0] = 0;
base[0] = 0;
/*
* First, convert some common Unix extensions to extensions of 3
* characters. If none fits, don't change anything now.
*/
if (strcmp(q = s + strlen(s) - strlen(".tar.gz"), ".tar.gz") == 0) {
*q = '\0';
q = (char *)"tgz";
} else if (strcmp(q = s + strlen(s) - strlen(".tar.z"), ".tar.z") == 0) {
*q = '\0';
q = (char *)"tgz";
} else if (strcmp(q = s + strlen(s) - strlen(".tar.Z"), ".tar.Z") == 0) {
*q = '\0';
q = (char *)"taz";
} else if (strcmp(q = s + strlen(s) - strlen(".html"), ".html") == 0) {
*q = '\0';
q = (char *)"htm";
} else if (strcmp(q = s + strlen(s) - strlen(".shtml"), ".shtml") == 0) {
*q = '\0';
q = (char *)"stm";
} else if (strcmp(q = s + strlen(s) - strlen(".conf"), ".conf") == 0) {
*q = '\0';
q = (char *)"cnf";
} else if (strcmp(q = s + strlen(s) - strlen(".mpeg"), ".mpeg") == 0) {
*q = '\0';
q = (char *)"mpg";
} else if (strcmp(q = s + strlen(s) - strlen(".smil"), ".smil") == 0) {
*q = '\0';
q = (char *)"smi";
} else if (strcmp(q = s + strlen(s) - strlen(".perl"), ".perl") == 0) {
*q = '\0';
q = (char *)"pl";
} else if (strcmp(q = s + strlen(s) - strlen(".jpeg"), ".jpeg") == 0) {
*q = '\0';
q = (char *)"jpg";
} else if (strcmp(q = s + strlen(s) - strlen(".tiff"), ".tiff") == 0) {
*q = '\0';
q = (char *)"tif";
} else {
q = NULL;
}
if (q) {
/*
* Extension is modified, apply changes
*/
p = s + strlen(s);
*p++ = '.';
for (i = 0; i < strlen(q); i++)
*p++ = q[i];
*p++ = '\0';
}
/*
* Now start name mangling
*/
p = strrchr(s,'.');
if (p && (strlen(p+1) < (size_t)4)) {
int all_normal = (!strhaslower(p+1)); /* XXXXXXXXX */
if (all_normal && p[1] != 0) {
*p = 0;
crc16 = crc16xmodem(s, strlen(s));
*p = '.';
} else {
crc16 = crc16xmodem(s, strlen(s));
}
} else {
crc16 = crc16xmodem(s, strlen(s));
}
tu(s);
if (p) {
if (p == s)
safe_strcpy(extension, "___", 3);
else {
*p++ = 0;
while (*p && extlen < 3) {
if (*p != '.' )
extension[extlen++] = p[0];
p++;
}
extension[extlen] = 0;
}
}
p = s;
/*
* Changed to baselen 4, original this is 5.
* 24-11-2002 MB.
*/
while (*p && baselen < 4) {
if (*p != '.' )
base[baselen++] = p[0];
p++;
}
base[baselen] = 0;
if (crc16 > (MANGLE_BASE * MANGLE_BASE * MANGLE_BASE))
Syslog('!', "WARNING: mangle_name_83() crc16 overflow");
crc16 = crc16 % (MANGLE_BASE * MANGLE_BASE * MANGLE_BASE);
snprintf(s, 9, "%s%c%c%c%c", base, magic_char,
mangle(crc16 / (MANGLE_BASE * MANGLE_BASE)), mangle(crc16 / MANGLE_BASE), mangle(crc16));
if ( *extension ) {
(void)strcat(s, ".");
(void)strcat(s, extension);
}
}
/*****************************************************************************
* Convert a filename to DOS format.
*
* Input: OutName - Source *and* destination buffer.
*
* NOTE that OutName must point to a memory space that
* is at least 13 bytes in size! That should always be
* the case of course.
*
* ****************************************************************************
*/
void name_mangle(char *OutName)
{
char *p;
p = xstrcpy(OutName);
/*
* check if it's already in 8.3 format
*/
if (!is_8_3(OutName)) {
mangle_name_83(OutName);
} else {
/*
* No mangling needed, convert to uppercase
*/
tu(OutName);
}
free(p);
}

373
lib/mbdiesel.c Normal file
View File

@@ -0,0 +1,373 @@
/*****************************************************************************
*
* $Id: mbdiesel.c,v 1.29 2007/03/03 14:28:40 mbse Exp $
* Purpose ...............: MBSE BBS functions for TURBODIESEL
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
#include "diesel.h"
static int firstrandom = TRUE;
void MacroVars( const char *codes, const char *fmt, ...)
{
char *tmp1, *tmp2, *vs, vc;
va_list ap;
int j, dieselrc, vd;
double vf;
tmp1 = calloc(MAXSTR, sizeof(char));
tmp2 = calloc(MAXSTR, sizeof(char));
va_start(ap,fmt);
for (j = 0; (codes[j] != '\0') && (fmt[j] != '\0') ; j++ ){
tmp1[0] = '\0';
switch (fmt[j]) {
case 's': /* string */
vs = va_arg(ap, char *);
snprintf(tmp1, MAXSTR -1, "@(setvar,%c,\"%s\")",codes[j], clencode(vs));
break;
case 'd': /* int */
vd = va_arg(ap, int);
snprintf(tmp1, MAXSTR -1, "@(setvar,%c,%d)",codes[j],vd);
break;
case 'c': /* char */
vc = va_arg(ap, int);
snprintf(tmp1, MAXSTR -1, "@(setvar,%c,%c)",codes[j],vc);
break;
case 'f': /* float */
vf = va_arg(ap, double);
snprintf(tmp1, MAXSTR -1, "@(setvar,%c,%f)",codes[j],vf);
break;
}
dieselrc = diesel(tmp1,tmp2);
if (dieselrc) {
Syslog('!', "MacroVars error %d argument %d, macro %c type %c", dieselrc, j, codes[j], fmt[j]);
Syslogp('!', printable(tmp1, 0));
}
}
va_end(ap);
free(tmp1);
free(tmp2);
}
void MacroClear(void)
{
int dieselrc;
char tmp1[] = "@(CLEAR)", *tmp2;
tmp2 = calloc(10,sizeof(char));
dieselrc = diesel(tmp1, tmp2);
if (dieselrc)
Syslog('!', "MacroClear error %d", dieselrc);
free(tmp2);
}
char *ParseMacro( const char *line, int *dieselrc)
{
static char res[MAXSTR];
const char *i;
char *tmp1, *tmp2, *tmp3;
int j, l;
char code;
res[0]='\0';
*dieselrc=0;
if ( *line == '#' )
return res;
tmp1 = calloc(MAXSTR, sizeof(char));
tmp2 = calloc(MAXSTR, sizeof(char));
tmp3 = calloc(MAXSTR, sizeof(char));
tmp1[0]='\0';
for (i = line; i[0] != '\0'; i++) {
if ( (i[0] == '@') && isalpha(i[1]) ){
l=2;
i++;
if (i[0] != '@') {
if ((code = i[0]) != '\0' )
i++;
while (( i[0] == '_') || ( i[0] == '>') || ( i[0] == '<') ){
l++;
i++;
}
i--;
snprintf(tmp2, MAXSTR, "@(GETVAR,%c)",code);
if (!diesel(tmp2,tmp3)==0){
snprintf(tmp3, MAXSTR, "%c%c",'@',code);
}
if (l>2){
if ( *i != '>')
l=-l;
snprintf(&tmp1[strlen(tmp1)], MAXSTR, "%*.*s", l, l, tmp3);
}else{
snprintf(&tmp1[strlen(tmp1)], MAXSTR, "%s", tmp3);
}
}else{
tmp1[(j=strlen(tmp1))]='@';
tmp1[j+1]='\0';
}
}else{
tmp1[(j=strlen(tmp1))]=i[0];
tmp1[j+1]='\0';
}
}
i = tmp1;
snprintf(tmp2, MAXSTR, "%s", tmp1);
if ((tmp1[0]=='@') && (tmp1[1]=='{')){
i++;
i++;
for (j=2; ((tmp1[j]!='}') && (tmp1[j]!='\0'));j++){
i++;
}
if ( (tmp1[j]=='}') ){
i++;
res[0]='\0';
if (j>2)
snprintf(res, MAXSTR, "%.*s",j-2, &tmp1[2]);
if ((diesel(res,tmp3)!=0) || (atoi(tmp3)==0))
snprintf(tmp2, MAXSTR, "@!%s",i);
else
snprintf(tmp2, MAXSTR, "%s",i);
}
}
*dieselrc=diesel(tmp2, res);
free(tmp1);
free(tmp2);
free(tmp3);
while (isspace(res[strlen(res) - 1])) {
res[strlen(res) - 1] = EOS;
}
if ((res[0] == '@') && (res[1] =='!' ))
res[0]='\0';
cldecode(res);
return res;
}
/*
* Add random fortune cookie to the macrovars
*/
void Cookie(int);
void Cookie(int HtmlMode)
{
FILE *olf;
char *fname, outbuf[256];
int recno, records;
MacroVars("F", "s", "");
fname = calloc(PATH_MAX, sizeof(char));
snprintf(fname, PATH_MAX -1, "%s/etc/oneline.data", getenv("MBSE_ROOT"));
if ((olf = fopen(fname, "r")) == NULL) {
WriteError("Can't open %s", fname);
free(fname);
return;
}
fread(&olhdr, sizeof(olhdr), 1, olf);
fseek(olf, 0, SEEK_END);
records = (ftell(olf) - olhdr.hdrsize) / olhdr.recsize;
if (firstrandom) {
srand(getpid());
firstrandom = FALSE;
}
recno = (1+(int) (1.0 * records * rand() / (RAND_MAX + 1.0))) - 1;
if (fseek(olf, olhdr.hdrsize + (recno * olhdr.recsize), SEEK_SET) == 0) {
if (fread(&ol, olhdr.recsize, 1, olf) == 1) {
if (HtmlMode) {
html_massage(ol.Oneline, outbuf, 255);
MacroVars("F", "s", outbuf);
} else {
MacroVars("F", "s", ol.Oneline);
}
} else {
WriteError("Can't read record %d from %s", recno, fname);
}
} else {
WriteError("Can't seek record %d in %s", recno, fname);
}
fclose(olf);
free(fname);
return;
}
/*
* Translate ISO 8859-1 characters to named character entities
*/
void html_massage(char *inbuf, char *outbuf, size_t size)
{
char *inptr = inbuf;
char *outptr = outbuf;
memset(outbuf, 0, sizeof(outbuf));
while (*inptr) {
switch ((unsigned char)*inptr) {
case '"': snprintf(outptr, size, "&quot;"); break;
case '&': snprintf(outptr, size, "&amp;"); break;
case '<': snprintf(outptr, size, "&lt;"); break;
case '>': snprintf(outptr, size, "&gt;"); break;
default: *outptr++ = *inptr; *outptr = '\0'; break;
}
while (*outptr)
outptr++;
inptr++;
}
*outptr = '\0';
}
FILE *OpenMacro(const char *filename, int Language, int htmlmode)
{
FILE *pLang, *fi = NULL;
char *temp, *aka, linebuf[1024], outbuf[1024];
temp = calloc(PATH_MAX, sizeof(char));
aka = calloc(81, sizeof(char));
temp[0] = '\0';
if (Language != '\0') {
/*
* Maybe a valid language character, try to load the language
*/
snprintf(temp, PATH_MAX -1, "%s/etc/language.data", getenv("MBSE_ROOT"));
if ((pLang = fopen(temp, "rb")) == NULL) {
WriteError("mbdiesel: Can't open language file: %s", temp);
} else {
fread(&langhdr, sizeof(langhdr), 1, pLang);
while (fread(&lang, langhdr.recsize, 1, pLang) == 1) {
if ((lang.LangKey[0] == Language) && (lang.Available)) {
snprintf(temp, PATH_MAX -1, "%s/share/int/macro/%s/%s", getenv("MBSE_ROOT"), lang.lc, filename);
break;
}
}
fclose(pLang);
}
}
/*
* Try to open the selected language
*/
if (temp[0] != '\0')
fi = fopen(temp, "r");
/*
* If no selected language is loaded, try default language
*/
if (fi == NULL) {
Syslog('-', "Macro file \"%s\" for language %c not found, trying default", filename, Language);
snprintf(temp, PATH_MAX -1, "%s/share/int/macro/%s/%s", getenv("MBSE_ROOT"), CFG.deflang, filename);
fi = fopen(temp,"r");
}
if (fi == NULL)
WriteError("OpenMacro(%s, %c): not found", filename, Language);
else {
/*
* Check macro file for update correct charset.
*/
while (fgets(linebuf, sizeof(linebuf) -1, fi)) {
if (strcasestr(linebuf, (char *)"text/html")) {
if (! strcasestr(linebuf, (char *)"UTF-8")) {
WriteError("Macro file %s doesn't define 'Content-Type' content='text/html; charset=UTF-8'", temp);
}
}
}
rewind(fi);
snprintf(temp, PATH_MAX -1, "%s-%s", OsName(), OsCPU());
if (CFG.aka[0].point)
snprintf(aka, 80, "%d:%d/%d.%d@%s", CFG.aka[0].zone, CFG.aka[0].net, CFG.aka[0].node, CFG.aka[0].point, CFG.aka[0].domain);
else
snprintf(aka, 80, "%d:%d/%d@%s", CFG.aka[0].zone, CFG.aka[0].net, CFG.aka[0].node, CFG.aka[0].domain);
if (htmlmode) {
MacroVars("O", "s", temp);
snprintf(linebuf, 1024, "%s", CFG.sysop);
html_massage(linebuf, outbuf, 1024);
MacroVars("U", "s", outbuf);
snprintf(linebuf, 1024, "%s", CFG.location);
html_massage(linebuf, outbuf, 1024);
MacroVars("L", "s", outbuf);
snprintf(linebuf, 1024, "%s", CFG.bbs_name);
html_massage(linebuf, outbuf, 1024);
MacroVars("N", "s", outbuf);
snprintf(linebuf, 1024, "%s", CFG.sysop_name);
html_massage(linebuf, outbuf, 1024);
MacroVars("S", "s", outbuf);
snprintf(linebuf, 1024, "%s", CFG.comment);
html_massage(linebuf, outbuf, 1024);
MacroVars("T", "s", outbuf);
} else {
MacroVars("L", "s", CFG.location);
MacroVars("N", "s", CFG.bbs_name);
MacroVars("O", "s", temp);
MacroVars("S", "s", CFG.sysop_name);
MacroVars("T", "s", CFG.comment);
MacroVars("U", "s", CFG.sysop);
}
MacroVars("H", "s", CFG.www_url);
MacroVars("M", "s", CFG.sysdomain);
MacroVars("V", "s", VERSION);
MacroVars("Y", "s", aka);
MacroVars("Z", "d", 0);
Cookie(htmlmode);
}
free(aka);
free(temp);
return fi;
}

284
lib/mbfile.c Normal file
View File

@@ -0,0 +1,284 @@
/*****************************************************************************
*
* $Id: mbfile.c,v 1.19 2005/12/03 15:09:06 mbse Exp $
* Purpose ...............: Basic File I/O
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This toolkit 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 MBTOOL; 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 "mbselib.h"
/*
* Buffered file copy, filetime is preserved.
*/
int file_cp(char *from, char *to)
{
char *line;
FILE *stfrom, *stto;
int dummy, bread;
static int error;
struct stat sb;
struct utimbuf ut;
stfrom = fopen(from, "r");
if (stfrom == NULL)
return errno;
stto = fopen(to, "w");
if (stto == NULL) {
error = errno;
fclose(stfrom);
return error;
}
line = malloc(16384);
do {
bread = fread(line, 1, 16384, stfrom);
dummy = fwrite(line, 1, bread, stto);
if (bread != dummy) {
error = errno;
fclose(stfrom);
fclose(stto);
unlink(to);
free(line);
return error;
}
Nopper(); // For large files on slow systems
} while (bread != 0);
free(line);
fclose(stfrom);
if (fclose(stto) != 0) {
error = errno;
unlink(to);
return error;
}
/*
* copy successfull, now copy file- and modification-time
*/
if (stat(from, &sb) == 0) {
ut.actime = mktime(localtime(&sb.st_atime));
ut.modtime = mktime(localtime(&sb.st_mtime));
if (utime(to, &ut) != 0) {
error = errno;
unlink(to);
return error;
}
chmod(to, sb.st_mode);
}
return 0;
}
/*
* Remove a file
*/
int file_rm(char *path)
{
if (unlink(path) != 0)
return errno;
return 0;
}
/*
* Move or rename a file. Not fullproof if using NFS, see
* man 2 rename. If we are trying to move a file accross
* filesystems, which is not allowed, we fall back to simple
* copy the file and then delete the old file.
*/
int file_mv(char *oldpath, char *newpath)
{
static int error;
if (rename(oldpath, newpath) != 0) {
error = errno;
if (error != EXDEV)
return error;
/*
* We tried cross-device link, now the slow way :-)
*/
error = file_cp(oldpath, newpath);
if (error != 0)
return error;
error = file_rm(oldpath);
return 0;
}
return 0;
}
/*
* Test if the given file exists. The second option is:
* R_OK - test for Read rights
* W_OK - test for Write rights
* X_OK - test for eXecute rights
* F_OK - test file presence only
*/
int file_exist(char *path, int mode)
{
if (access(path, mode) != 0)
return errno;
return 0;
}
/*
* Return size of file, or -1 if file doesn't exist
*/
int file_size(char *path)
{
static struct stat sb;
if (stat(path, &sb) == -1)
return -1;
return sb.st_size;
}
/*
* Calculate the 32 bit CRC of a file. Return -1 if file not found.
*/
int file_crc(char *path, int slow)
{
static int crc;
int bread;
FILE *fp;
char *line;
if ((fp = fopen(path, "r")) == NULL)
return -1;
line = malloc(32768);
crc = 0xffffffff;
do {
bread = fread(line, 1, 32768, fp);
crc = upd_crc32(line, crc, bread);
Nopper(); // For large files on slow systems.
} while (bread > 0);
free(line);
fclose(fp);
return crc ^ 0xffffffff;
}
/*
* Return time of file, or -1 if file doen't exist, which is
* the same as 1 second before 1 jan 1970. You may test the
* result on -1 since time_t is actualy a long integer.
*/
time_t file_time(char *path)
{
static struct stat sb;
if (stat(path, &sb) == -1)
return -1;
return sb.st_mtime;
}
/*
* Make directory tree, the name must end with a /
*/
int mkdirs(char *name, mode_t mode)
{
char buf[PATH_MAX], *p, *q;
int rc, last = 0, oldmask;
memset(&buf, 0, sizeof(buf));
strncpy(buf, name, sizeof(buf)-1);
buf[sizeof(buf)-1] = '\0';
p = buf+1;
oldmask = umask(000);
while ((q = strchr(p, '/'))) {
*q = '\0';
rc = mkdir(buf, mode);
last = errno;
*q = '/';
p = q+1;
}
umask(oldmask);
if ((last == 0) || (last == EEXIST)) {
return TRUE;
} else {
WriteError("mkdirs(%s)", name);
return FALSE;
}
}
/*
* Give a directory path and a filename, locate that filename in that
* directory and return the filename with the correct case. This is
* to be able to detect filename.ext, FILENAME.EXT and FiLeNaMe.ExT
*/
int getfilecase(char *path, char *fil)
{
DIR *dp;
struct dirent *de;
int i, rc = FALSE;
if ((dp = opendir(path)) == NULL) {
WriteError("$Can't opendir(%s)", path);
return rc;
}
while ((de = readdir(dp))) {
if (strcasecmp(de->d_name, fil) == 0) {
for (i = 0; i < strlen(de->d_name); i++)
fil[i] = de->d_name[i];
rc = TRUE;
break;
}
}
closedir(dp);
return rc;
}

25
lib/mbinet.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef _MBINET_H
#define _MBINET_H
/* $Id: mbinet.h,v 1.2 2004/01/04 12:35:50 mbroek Exp $ */
int smtp_connect(void);
int smtp_send(char *);
char *smtp_receive(void);
int smtp_close(void);
int smtp_cmd(char *, int);
int nntp_connect(void);
int nntp_send(char *);
char *nntp_receive(void);
int nntp_close(void);
int nntp_cmd(char *, int);
int nntp_auth(void);
int pop3_connect(void);
int pop3_send(char *);
char *pop3_receive(void);
int pop3_close(void);
int pop3_cmd(char *);
#endif

115
lib/mbse.h Normal file
View File

@@ -0,0 +1,115 @@
/*****************************************************************************
*
* $Id: mbse.h,v 1.16 2007/02/20 20:24:06 mbse Exp $
* Purpose ...............: Global variables for MBSE BBS
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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.
*****************************************************************************/
#ifndef _MBSE_H
#define _MBSE_H
#define LANG 500 /* Amount of Language Entries */
typedef struct _TagRec {
int Area; /* File Area number */
int Active; /* Not deleted from taglist */
int Cost; /* Free download */
unsigned int Size; /* File Size */
char SFile[13]; /* Short File Name */
char LFile[81]; /* Long FIle Name */
} _Tag;
/*
* File Areas
*/
int iAreaNumber; /* Current File Area -1 */
char sAreaDesc[PATH_MAX]; /* Current File Area Name */
char sAreaPath[PATH_MAX]; /* Current File Area path */
FILE *pTagList; /* Tagged files for download */
_Tag Tag; /* Tag record */
/*
* Msg Areas
*/
int iMsgAreaNumber; /* Current Message Area number -1 */
int iMsgAreaType; /* Current Message Area Type */
char sMsgAreaDesc[PATH_MAX]; /* Current Message Area Name */
char sMsgAreaBase[PATH_MAX]; /* Current Message Area Base */
char sMailbox[21]; /* Current e-mail mailbox */
char sMailpath[PATH_MAX]; /* Current e-mail path */
/*
* Protocols
*/
char sProtName[21]; /* Current Transfer Protocol name */
char sProtUp[51]; /* Upload path & binary */
char sProtDn[51]; /* Download path & binary */
char sProtAdvice[31]; /* Advice for protocol */
unsigned uProtInternal; /* Internal protocol */
int iProtEfficiency; /* Protocol efficiency */
/*
* Global variables
*/
char *mLanguage[LANG]; /* Define LANG=nnn Language Variables */
char *mKeystroke[LANG]; /* Possible keystrokes */
char *Date1, *Date2; /* Result from function SwapDate() */
char *pTTY; /* Current tty name */
char sUserTimeleft[7]; /* Global Time Left Variable */
int iUserTimeLeft; /* Global Time Left Variable */
char LastLoginDate[12]; /* Last login date */
char LastLoginTime[9]; /* Last login time */
char LastCaller[36]; /* Last caller on system name */
time_t LastCallerTime; /* Last caller on system time */
char FirstName[20]; /* Users First name */
char LastName[30]; /* Users Last name */
int UserAge; /* Users age */
int grecno; /* User's Record Number in user file */
int SYSOP; /* Int to see if user is Sysop */
int iLineCount; /* Line Counter */
int iExpired; /* Check if users time ran out */
char sUnixName[9]; /* Unix login name */
time_t Time2Go; /* Calculated time to force logout */
struct tm *l_date; /* Structure for Date */
time_t ltime;
time_t Time_Now;
char current_language[10]; /* Current language of the user */
int utf8;
#endif

156
lib/mbsedb.h Normal file
View File

@@ -0,0 +1,156 @@
/*****************************************************************************
*
& $Id: mbsedb.h,v 1.10 2005/10/11 20:49:42 mbse Exp $
* Purpose ...............: MBSE BBS database library header
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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.
*****************************************************************************/
#ifndef _MBSEDB_H
#define _MBSEDB_H
void InitConfig(void); /* Initialize and load config */
void LoadConfig(void); /* Only load config file */
int IsOurAka(fidoaddr); /* Check if our aka */
/*
* Dupes database type
*/
typedef enum {D_ECHOMAIL, D_FILEECHO, D_NEWS} DUPETYPE;
void InitDupes(void);
int CheckDupe(unsigned int, int, int);
void CloseDupes(void);
/*
* Fidonet database
*/
struct _fidonethdr fidonethdr; /* Header record */
struct _fidonet fidonet; /* Fidonet datarecord */
int fidonet_cnt; /* Fidonet records in database */
char fidonet_fil[PATH_MAX]; /* Fidonet database filename */
int InitFidonet(void); /* Initialize fidonet database */
int TestFidonet(unsigned short); /* Test if zone is in memory */
int SearchFidonet(unsigned short); /* Search specified zone and load */
char *GetFidoDomain(unsigned short); /* Search Fidonet domain name */
/*
* Nodes database
*/
struct _nodeshdr nodeshdr; /* Header record */
struct _nodes nodes; /* Nodes datarecord */
int nodes_cnt; /* Node records in database */
int InitNode(void); /* Initialize nodes database */
int TestNode(fidoaddr); /* Check if noderecord is loaded */
int SearchNodeFaddr(faddr *); /* Search specified node and load */
int SearchNode(fidoaddr); /* Search specified node and load */
int UpdateNode(void); /* Update record if changed. */
char *GetNodeMailGrp(int); /* Get nodes mailgroup record */
char *GetNodeFileGrp(int); /* Get nodes filegroup record */
/*
* TIC area database
*/
struct _tichdr tichdr; /* Header record */
struct _tic tic; /* Tics datarecord */
struct _fgrouphdr fgrouphdr; /* Group header record */
struct _fgroup fgroup; /* Group record */
int tic_cnt; /* Tic records in database */
int InitTic(void); /* Initialize tic database */
int SearchTic(char *); /* Search specified msg are */
int TicSystemConnected(sysconnect); /* Is system connected */
int TicSystemConnect(sysconnect *, int); /* Connect/change/delete system*/
int GetTicSystem(sysconnect *, int);/* Get connected system */
void UpdateTic(void); /* Update current messages record */
/*
* User records
*/
struct userhdr usrhdr; /* Header record */
struct userrec usr; /* User datarecord */
int usr_cnt; /* User records in database */
char usr_fil[PATH_MAX]; /* User database filename */
int InitUser(void); /* Initialize user database */
int TestUser(char *); /* Test if user is in memory */
int SearchUser(char *); /* Search specified user and load */
/*
* Message areas database
*/
struct msgareashdr msgshdr; /* Header record */
struct msgareas msgs; /* Msgss datarecord */
struct _mgrouphdr mgrouphdr; /* Group header record */
struct _mgroup mgroup; /* Group record */
int msgs_cnt; /* Msgs records in database */
int InitMsgs(void); /* Initialize msgs database */
int SearchMsgs(char *); /* Search specified msg area */
int SearchMsgsNews(char *); /* Search specified msg area */
int SearchBadBoard(void); /* Search system badboard */
int MsgSystemConnected(sysconnect); /* Is system connected */
int MsgSystemConnect(sysconnect *, int); /* Connect/change/delete system*/
int GetMsgSystem(sysconnect *, int);/* Get connected system */
int SearchNetBoard(unsigned short, unsigned short); /* Search netmail */
void UpdateMsgs(void); /* Update current messages record */
/*
* Structure of current open file area
*/
struct _fdbarea {
int area; /* Area number */
int locked; /* Is area locked */
FILE *fp; /* File pointer */
};
struct _fdbarea *mbsedb_OpenFDB(int, int);
int mbsedb_CloseFDB(struct _fdbarea *);
int mbsedb_LockFDB(struct _fdbarea *, int);
int mbsedb_UnlockFDB(struct _fdbarea *);
int mbsedb_InsertFDB(struct _fdbarea *, struct FILE_record, int);
int mbsedb_PackFDB(struct _fdbarea *);
int mbsedb_SortFDB(struct _fdbarea *);
#endif

2723
lib/mbselib.h Normal file

File diff suppressed because it is too large Load Diff

17
lib/mkprod.awk Normal file
View File

@@ -0,0 +1,17 @@
# $Id: mkprod.awk,v 1.6 2004/02/21 14:24:04 mbroek Exp $
#
BEGIN {
print "#include \"../config.h\""
print "#include \"mbselib.h\""
print ""
print "struct _ftscprod ftscprod[] = {"
}
/^[^;]/ {
if ($2 != "DROPPED")
print " {0x" $1 ",(char *)\"" $2 "\"},"
}
END {
print " {0xff,(char*)0L}"
print "};"
}

546
lib/msg.c Normal file
View File

@@ -0,0 +1,546 @@
/*****************************************************************************
*
* $Id: msg.c,v 1.15 2005/10/11 20:49:44 mbse Exp $
* Purpose ...............: Global message base functions
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "msgtext.h"
#include "msg.h"
#include "jammsg.h"
char *strlwr (char *s)
{
char *p = s;
while (*p != '\0') {
*p = (char)tolower (*p);
p++;
}
return (s);
}
char *strupr (char *s)
{
char *p = s;
while (*p != '\0') {
*p = (char)toupper (*p);
p++;
}
return (s);
}
int filelength(int fd)
{
int retval = -1L;
struct stat buf;
if (fd != -1) {
fstat(fd, &buf);
retval = buf.st_size;
}
return (retval);
}
int tell(int fd)
{
int retval = -1L;
if (fd != -1)
retval = lseek(fd, 0L, SEEK_CUR);
return retval;
}
/*
* Add a message
*/
int Msg_AddMsg()
{
if (!MsgBase.Locked)
return FALSE;
return JAM_AddMsg();
}
/*
* Close current message base
*/
void Msg_Close(void)
{
if (MsgBase.Locked)
Msg_UnLock();
JAM_Close();
MsgText_Clear();
MsgBase.Open = FALSE;
}
/*
* Delete message number
*/
int Msg_Delete(unsigned int ulMsg)
{
if (!MsgBase.Locked)
return FALSE;
return JAM_Delete(ulMsg);
}
/*
* Delete message base
*/
void Msg_DeleteMsgBase(char *Base)
{
JAM_DeleteJAM(Base);
}
int Msg_GetLastRead(lastread *LR)
{
return JAM_GetLastRead(LR);
}
/*
* Get highest message number
*/
unsigned int Msg_Highest(void)
{
return MsgBase.Highest = JAM_Highest();
}
int Msg_Lock(unsigned int ulTimeout)
{
return MsgBase.Locked = JAM_Lock(ulTimeout);
}
/*
* Get lowest message number
*/
unsigned int Msg_Lowest(void)
{
return MsgBase.Lowest = JAM_Lowest();
}
void Msg_New(void)
{
JAM_New();
}
int Msg_NewLastRead(lastread LR)
{
return JAM_NewLastRead(LR);
}
int Msg_Next(unsigned int * ulMsg)
{
return JAM_Next(ulMsg);
}
/*
* Return number of messages
*/
unsigned int Msg_Number(void)
{
return MsgBase.Total = JAM_Number();
}
/*
* Open specified message base
*/
int Msg_Open(char *Base)
{
int RetVal = FALSE;
if (MsgBase.Open) {
if (strcmp(MsgBase.Path, Base) != 0)
Msg_Close();
else
return TRUE;
}
RetVal = JAM_Open(Base);
MsgBase.Open = RetVal;
strcpy(MsgBase.Path, Base);
return RetVal;
}
/*
* Pack deleted messages from the message base.
*/
void Msg_Pack(void)
{
if (!MsgBase.Locked)
return;
JAM_Pack();
}
int Msg_Previous (unsigned int * ulMsg)
{
return JAM_Previous(ulMsg);
}
int Msg_ReadHeader (unsigned int ulMsg)
{
return JAM_ReadHeader(ulMsg);
}
/*
* Read message
*/
int Msg_Read(unsigned int ulMsg, int nWidth)
{
return JAM_Read(ulMsg, nWidth);
}
int Msg_SetLastRead(lastread LR)
{
if (!MsgBase.Locked)
return FALSE;
return JAM_SetLastRead(LR);
}
/*
* Unlock the message base
*/
void Msg_UnLock(void)
{
JAM_UnLock();
MsgBase.Locked = FALSE;
}
/*
* Write message header
*/
int Msg_WriteHeader (unsigned int ulMsg)
{
if (!MsgBase.Locked)
return FALSE;
return JAM_WriteHeader(ulMsg);
}
/*
* Write messagetext from file, strip linefeeds.
*/
void Msg_Write(FILE *fp)
{
char *Buf;
Buf = calloc(MAX_LINE_LENGTH +1, sizeof(char));
while ((Fgets(Buf, MAX_LINE_LENGTH, fp)) != NULL)
MsgText_Add2(Buf);
free(Buf);
}
typedef struct {
unsigned int Subject;
unsigned int Number;
} MSGLINK;
/*
* Changes ansi background and foreground color
*/
void msg_colour(int, int);
void msg_colour(int fg, int bg)
{
int att=0, fore=37, back=40;
if (fg<0 || fg>31 || bg<0 || bg>7) {
fprintf(stdout, "ANSI: Illegal colour specified: %i, %i\n", fg, bg);
fflush(stdout);
return;
}
fprintf(stdout, "[");
if ( fg > WHITE) {
fprintf(stdout, "5;");
fg-= 16;
}
if (fg > LIGHTGRAY) {
att=1;
fg=fg-8;
}
if (fg == BLACK) fore=30;
else if (fg == BLUE) fore=34;
else if (fg == GREEN) fore=32;
else if (fg == CYAN) fore=36;
else if (fg == RED) fore=31;
else if (fg == MAGENTA) fore=35;
else if (fg == BROWN) fore=33;
else fore=37;
if (bg == BLUE) back=44;
else if (bg == GREEN) back=42;
else if (bg == CYAN) back=46;
else if (bg == RED) back=41;
else if (bg == MAGENTA) back=45;
else if (bg == BROWN) back=43;
else if (bg == LIGHTGRAY) back=47;
else back=40;
fprintf(stdout, "%d;%d;%dm", att, fore, back);
fflush(stdout);
}
/*
* Link messages in one area.
* Returns -1 if error, else the number of linked messages.
*/
int Msg_Link(char *Path, int do_quiet, int slow_util)
{
int i, m, msg_link = 0;
unsigned int Number, Prev, Next, Crc, Total;
char Temp[128], *p;
MSGLINK *Link;
if (! Msg_Open(Path)) {
return -1;
}
if (!do_quiet) {
msg_colour(LIGHTRED, BLACK);
printf(" (linking)");
msg_colour(LIGHTMAGENTA, BLACK);
fflush(stdout);
}
if ((Total = Msg_Number()) != 0L) {
if (Msg_Lock(30L)) {
if ((Link = (MSGLINK *)malloc((Total + 1) * sizeof(MSGLINK))) != NULL) {
memset(Link, 0, (Total + 1) * sizeof(MSGLINK));
Number = Msg_Lowest();
i = 0;
do {
Msg_ReadHeader(Number);
strcpy(Temp, Msg.Subject);
p = strupr(Temp);
if (!strncmp(p, "RE:", 3)) {
p += 3;
if (*p == ' ')
p++;
}
Link[i].Subject = StringCRC32(p);
Link[i].Number = Number;
i++;
if (((i % 10) == 0) && (!do_quiet)) {
printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
fflush(stdout);
}
} while(Msg_Next(&Number) == TRUE);
if (!do_quiet) {
printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
fflush(stdout);
}
Number = Msg_Lowest();
i = 0;
do {
Msg_ReadHeader(Number);
Prev = Next = 0;
Crc = Link[i].Subject;
for (m = 0; m < Total; m++) {
if (m == i)
continue;
if (Link[m].Subject == Crc) {
if (m < i)
Prev = Link[m].Number;
else if (m > i) {
Next = Link[m].Number;
break;
}
}
}
if (((i % 10) == 0) && (!do_quiet)) {
printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
fflush(stdout);
}
if (Msg.Original != Prev || Msg.Reply != Next) {
Msg.Original = Prev;
Msg.Reply = Next;
Msg_WriteHeader(Number);
msg_link++;
}
i++;
} while(Msg_Next(&Number) == TRUE);
if (!do_quiet) {
printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
fflush(stdout);
}
free(Link);
}
if (!do_quiet) {
printf(" \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
}
Msg_UnLock();
} else {
Syslog('+', "Can't lock %s", Path);
return -1;
}
}
Msg_Close();
if (!do_quiet) {
printf("\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
}
return msg_link;
}
/*
* Fgets() is like fgets() but never returns the line terminator
* at end of line and handles that line terminators:
*
* DOS/WINDOWS -> CR/LF
* UNIX -> LF only
* MAC -> CR only
*/
char *Fgets(char *l, int size, FILE *f) {
char *cp = l;
int cr, eol = FALSE;
if (feof(f)) return NULL;
cr = FALSE;
while (size>1 && !feof(f)) {
int c = fgetc(f);
if (c == EOF) {
if (ferror(f)) return NULL;
break;
}
if (cr && c != '\n') {
/* CR end-of-line (MAC) */
ungetc(c,f);
eol = TRUE;
break;
} else
cr = (c=='\r');
if ( cr )
continue;
--size;
if (c=='\n') { eol = TRUE; break; }
*(cp++) = c;
}
*cp = '\0';
cr = FALSE;
while (!eol && !feof(f)) {
int c = fgetc(f);
if (c == EOF)
break;
if (cr && c != '\n') {
/* CR end-of-line (MAC) */
ungetc(c,f);
break;
} else
cr = (c=='\r');
if ( cr )
continue;
if (c=='\n') break;
}
return l;
}

148
lib/msg.h Normal file
View File

@@ -0,0 +1,148 @@
/* $Id: msg.h,v 1.6 2005/10/11 20:49:44 mbse Exp $ */
#ifndef _MSG_H
#define _MSG_H
/*
* Global maximum line length for all files that do something with
* message text.
*/
#define MAX_LINE_LENGTH 2048
/*
* Global message buffer
*/
typedef struct _msgbuf {
unsigned int Id;
unsigned int Current;
char From[101]; /* From name */
char To[101]; /* To name */
char Subject[101]; /* Message subject */
unsigned Local : 1; /* Message is local */
unsigned Intransit : 1; /* Message is in transit */
unsigned Private : 1; /* Message is private */
unsigned Received : 1; /* Message is received */
unsigned Sent : 1; /* Message is sent */
unsigned KillSent : 1; /* Kill after sent */
unsigned ArchiveSent : 1; /* Archive after sent */
unsigned Hold : 1; /* Hold message */
unsigned Crash : 1; /* Crash flag */
unsigned Immediate : 1; /* Immediate mail */
unsigned Direct : 1; /* Direct flag */
unsigned Gate : 1; /* Send via gateway */
unsigned FileRequest : 1; /* File request */
unsigned FileAttach : 1; /* File attached */
unsigned TruncFile : 1; /* Trunc file after sent */
unsigned KillFile : 1; /* Kill file after sent */
unsigned ReceiptRequest : 1; /* Return receipt request */
unsigned ConfirmRequest : 1; /* Confirm receipt request */
unsigned Orphan : 1; /* Orphaned message */
unsigned Encrypt : 1; /* Encrypted message */
unsigned Compressed : 1; /* Compressed message */
unsigned Escaped : 1; /* Msg is 7bit ASCII */
unsigned ForcePU : 1; /* Force PickUp */
unsigned Localmail : 1; /* Local use only */
unsigned Echomail : 1; /* Echomail flag */
unsigned Netmail : 1; /* Netmail flag */
unsigned News : 1; /* News article */
unsigned Email : 1; /* e-mail message */
unsigned Nntp : 1; /* Offer to NNTP server */
unsigned Nodisplay : 1; /* No display to user */
unsigned Locked : 1; /* Locked, no edit allowed */
unsigned Deleted : 1; /* Msg is deleted */
time_t Written; /* Date message is written */
time_t Arrived; /* Date message arrived */
time_t Read; /* Date message is received */
char FromAddress[101]; /* From address */
char ToAddress[101]; /* To address */
unsigned int Reply; /* Message is reply to */
unsigned int Original; /* Original message */
unsigned int MsgIdCRC; /* Message Id CRC */
unsigned int ReplyCRC; /* Reply CRC */
char Msgid[81]; /* Msgid string */
char Replyid[81]; /* Replyid string */
char ReplyAddr[81]; /* Gated Reply Address */
char ReplyTo[81]; /* Gated Reply To */
int Size; /* Message size during write*/
} msgbuf;
/*
* Globale message area buffer
*/
typedef struct _msgbase {
char Path[PATH_MAX]; /* Path to message base */
unsigned Open : 1; /* If base is open */
unsigned Locked : 1; /* If base is locked */
unsigned int LastNum; /* Lastread message number */
unsigned int Lowest; /* Lowest message number */
unsigned int Highest; /* Highest message number */
unsigned int Total; /* Total number of msgs */
} msgbase;
/*
* LastRead structure
*/
typedef struct _lastread {
unsigned int UserCRC; /* CRC32 lowercase username */
unsigned int UserID; /* Unique user-id */
unsigned int LastReadMsg; /* Last Read message number */
unsigned int HighReadMsg; /* Highes read message */
} lastread;
/*
* Global variables
*/
msgbuf Msg; /* Message buffer */
msgbase MsgBase; /* Message Base buffer */
msgbase EmailBase; /* Email Base buffer */
lastread LastRead; /* LastRead pointer record */
char szWrp[MAX_LINE_LENGTH + 1];
/*
* Common function prototypes.
*/
char *strlwr(char *);
char *strupr(char *);
int filelength(int);
int tell(int);
char *Fgets(char *, int, FILE *);
/*
* Message Base Prototypes
*/
int Msg_AddMsg(void);
void Msg_Close(void);
int Msg_Delete(unsigned int);
void Msg_DeleteMsgBase(char *);
int Msg_GetLastRead(lastread *);
unsigned int Msg_Highest(void);
int Msg_Lock(unsigned int);
unsigned int Msg_Lowest(void);
void Msg_New(void);
int Msg_NewLastRead(lastread);
int Msg_Next(unsigned int *);
unsigned int Msg_Number(void);
int Msg_Open(char *);
void Msg_Pack(void);
int Msg_Previous(unsigned int *);
int Msg_ReadHeader(unsigned int);
int Msg_Read(unsigned int, int);
int Msg_SetLastRead(lastread);
void Msg_UnLock(void);
int Msg_WriteHeader(unsigned int);
void Msg_Write(FILE *);
int Msg_Link(char *, int, int);
#endif

335
lib/msgtext.c Normal file
View File

@@ -0,0 +1,335 @@
/*****************************************************************************
*
* $Id: msgtext.c,v 1.5 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: Message text memory storage.
*
*****************************************************************************
* Copyright (C) 1997-2004
*
* Michiel Broek FIDO: 2:2801/16
* Beekmansbos 10 Internet: mbroek@ux123.pttnwb.nl
* 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 "mbselib.h"
#include "msgtext.h"
#include "msg.h"
LDATA *List;
unsigned short MsgText_Add1(void * lpData)
{
unsigned short RetVal = 0;
LDATA *New;
if ((New = (LDATA *)malloc (sizeof (LDATA))) != NULL) {
memset (New, 0, sizeof (LDATA));
New->Value = (void *)lpData;
if (List != NULL) {
while (List->Next != NULL)
List = List->Next;
New->Previous = List;
New->Next = List->Next;
if (New->Next != NULL)
New->Next->Previous = New;
List->Next = New;
}
Elements++;
Msg.Size += sizeof((void *)lpData);
List = New;
RetVal = 1;
}
return (RetVal);
}
unsigned short MsgText_Add2(char * lpData)
{
return (MsgText_Add3((void *)lpData, (unsigned short)(strlen (lpData) + 1)));
}
unsigned short MsgText_Add3(void * lpData, unsigned short usSize)
{
unsigned short RetVal = 0;
LDATA *New;
if ((New = (LDATA *)malloc(sizeof (LDATA) + usSize)) != NULL) {
memset (New, 0, sizeof (LDATA) + usSize);
memcpy (New->Data, lpData, usSize);
New->Value = (void *)New->Data;
if (List != NULL) {
while (List->Next != NULL)
List = List->Next;
New->Previous = List;
New->Next = List->Next;
if (New->Next != NULL)
New->Next->Previous = New;
List->Next = New;
}
Elements++;
Msg.Size += usSize;
List = New;
RetVal = 1;
}
return (RetVal);
}
void MsgText_Clear (void)
{
while (List != NULL)
MsgText_Remove();
Elements = 0;
}
void *MsgText_First (void)
{
void *RetVal = NULL;
if (List != NULL) {
while (List->Previous != NULL)
List = List->Previous;
RetVal = List->Value;
}
return RetVal;
}
unsigned short MsgText_Insert1(void * lpData)
{
unsigned short RetVal = 0;
LDATA *New;
if ((New = (LDATA *)malloc (sizeof (LDATA))) != NULL) {
memset (New, 0, sizeof (LDATA));
New->Value = (void *)lpData;
if (List != NULL) {
New->Previous = List;
New->Next = List->Next;
if (New->Next != NULL)
New->Next->Previous = New;
List->Next = New;
}
Elements++;
List = New;
RetVal = 1;
}
return (RetVal);
}
unsigned short MsgText_Insert2(char * lpData)
{
return (MsgText_Insert3(lpData, (unsigned short)(strlen (lpData) + 1)));
}
unsigned short MsgText_Insert3(void * lpData, unsigned short usSize)
{
unsigned short RetVal = 0;
LDATA *New;
if ((New = (LDATA *)malloc (sizeof (LDATA) + usSize)) != NULL) {
memset (New, 0, sizeof (LDATA) + usSize);
memcpy (New->Data, lpData, usSize);
New->Value = (void *)New->Data;
if (List != NULL) {
New->Previous = List;
New->Next = List->Next;
if (New->Next != NULL)
New->Next->Previous = New;
List->Next = New;
}
Elements++;
List = New;
RetVal = 1;
}
return (RetVal);
}
void * MsgText_Last(void)
{
void * RetVal = NULL;
if (List != NULL) {
while (List->Next != NULL)
List = List->Next;
RetVal = List->Value;
}
return (RetVal);
}
void * MsgText_Next (void)
{
void * RetVal = NULL;
if (List != NULL) {
if (List->Next != NULL) {
List = List->Next;
RetVal = List->Value;
}
}
return (RetVal);
}
void * MsgText_Previous (void)
{
void * RetVal = NULL;
if (List != NULL) {
if (List->Previous != NULL) {
List = List->Previous;
RetVal = List->Value;
}
}
return (RetVal);
}
void MsgText_Remove(void)
{
LDATA *Temp;
if (List != NULL) {
if (List->Previous != NULL)
List->Previous->Next = List->Next;
if (List->Next != NULL)
List->Next->Previous = List->Previous;
Temp = List;
if (List->Next != NULL)
List = List->Next;
else if (List->Previous != NULL)
List = List->Previous;
else
List = NULL;
free (Temp);
Elements--;
}
}
unsigned short MsgText_Replace1(void * lpData)
{
unsigned short RetVal = 0;
LDATA *New;
if (List != NULL) {
if ((New = (LDATA *)malloc (sizeof (LDATA))) != NULL) {
memset (New, 0, sizeof (LDATA));
New->Value = (void *)lpData;
New->Next = List->Next;
New->Previous = List->Previous;
if (New->Next != NULL)
New->Next->Previous = New;
if (New->Previous != NULL)
New->Previous->Next = New;
free (List);
List = New;
RetVal = 1;
}
}
return (RetVal);
}
unsigned short MsgText_Replace2(char * lpData)
{
return (MsgText_Replace3(lpData, (unsigned short)(strlen (lpData) + 1)));
}
unsigned short MsgText_Replace3(void * lpData, unsigned short usSize)
{
unsigned short RetVal = 0;
LDATA *New;
if (List != NULL) {
if ((New = (LDATA *)malloc (sizeof (LDATA) + usSize)) != NULL) {
memset (New, 0, sizeof (LDATA) + usSize);
memcpy (New->Data, lpData, usSize);
New->Value = (void *)New->Data;
New->Next = List->Next;
New->Previous = List->Previous;
if (New->Next != NULL)
New->Next->Previous = New;
if (New->Previous != NULL)
New->Previous->Next = New;
free (List);
List = New;
RetVal = 1;
}
}
return (RetVal);
}
void * MsgText_Value(void)
{
return ((List == NULL) ? NULL : List->Value);
}

34
lib/msgtext.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef _MSGTEXT_H
#define _MSGTEXT_H
typedef struct _lData {
struct _lData *Previous;
struct _lData *Next;
void * Value;
char Data[1];
} LDATA;
unsigned short Elements;
unsigned short MsgText_Add1(void * lpData);
unsigned short MsgText_Add2(char * lpData);
unsigned short MsgText_Add3(void * lpData, unsigned short usSize);
void MsgText_Clear(void);
void * MsgText_First(void);
unsigned short MsgText_Insert1(void * lpData);
unsigned short MsgText_Insert2(char * lpData);
unsigned short MsgText_Insert3(void * lpData, unsigned short usSize);
void * MsgText_Last(void);
void * MsgText_Next(void);
void * MsgText_Previous(void);
void MsgText_Remove(void);
unsigned short MsgText_Replace1(void * lpData);
unsigned short MsgText_Replace2(char * lpData);
unsigned short MsgText_Replace3(void * lpData, unsigned short usSize);
void * MsgText_Value(void);
#endif

286
lib/nntp.c Normal file
View File

@@ -0,0 +1,286 @@
/*****************************************************************************
*
* $Id: nntp.c,v 1.16 2008/12/28 12:20:14 mbse Exp $
* Purpose ...............: MBSE BBS Internet Library
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "mbinet.h"
static int nntpsock = -1; /* TCP/IP socket */
struct hostent *nhp; /* Host info remote */
struct servent *nsp; /* Service information */
struct sockaddr_in nntp_loc; /* For local socket address */
struct sockaddr_in nntp_rem; /* For remote socket address */
int nntp_connect(void)
{
socklen_t addrlen;
char *p;
if (nntpsock != -1)
return nntpsock;
if (!strlen(CFG.nntpnode)) {
WriteError("NNTP: host not configured");
return -1;
}
Syslog('+', "NNTP: connecting host: %s:%d", CFG.nntpnode, CFG.nntpport);
memset(&nntp_loc, 0, sizeof(struct sockaddr_in));
memset(&nntp_rem, 0, sizeof(struct sockaddr_in));
nntp_rem.sin_family = AF_INET;
if ((nhp = gethostbyname(CFG.nntpnode)) == NULL) {
WriteError("NNTP: can't find host %s", CFG.nntpnode);
return -1;
}
nntp_rem.sin_addr.s_addr = ((struct in_addr *)(nhp->h_addr))->s_addr;
nntp_rem.sin_port = htons(CFG.nntpport);
if ((nntpsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
WriteError("$NNTP: unable to create tcp socket");
return -1;
}
if (connect(nntpsock, (struct sockaddr *)&nntp_rem, sizeof(struct sockaddr_in)) == -1) {
WriteError("$NNTP: cannot connect tcp socket");
return -1;
}
addrlen = sizeof(struct sockaddr_in);
if (getsockname(nntpsock, (struct sockaddr *)&nntp_loc, &addrlen) == -1) {
WriteError("$NNTP: unable to read socket address");
return -1;
}
p = nntp_receive();
if (strlen(p) == 0) {
WriteError("NNTP: no response");
nntp_close();
return -1;
}
Syslog('+', "NNTP: %s", p);
if ((strncmp(p, "480", 3) == 0) || CFG.nntpforceauth) {
/*
* Must login with username and password
*/
if (nntp_auth() == FALSE) {
WriteError("Authorisation failure");
nntp_close();
return -1;
}
} else if (strncmp(p, "200", 3)) {
WriteError("NNTP: bad response: %s", p);
// nntp_close(); FIXME: Don't close, the other end might have done that already
// If we do also, this program hangs. Must be fixed!
return -1;
}
if (CFG.modereader) {
Syslog('+', "NNTP: setting mode reader");
nntp_send((char *)"MODE READER\r\n");
p = nntp_receive();
Syslog('+', "NNTP: %s", p);
if (strncmp(p, "480", 3) == 0) {
/*
* Must login with username and password
*/
Syslog('+', "NNTP: %s", p);
if (nntp_auth() == FALSE) {
WriteError("NNTP: authorisation failure");
nntp_close();
return -1;
}
} else if (strncmp(p, "200", 3)) {
WriteError("NNTP: bad response: %s", p);
nntp_close();
return -1;
}
}
return nntpsock;
}
int nntp_send(char *buf)
{
if (nntpsock == -1)
return -1;
if (send(nntpsock, buf, strlen(buf), 0) != strlen(buf)) {
WriteError("$NNTP: socket send failed");
if (errno == ENOTCONN || errno == EPIPE) {
WriteError("NNTP: closing local side");
nntpsock = -1;
}
return -1;
}
return 0;
}
/*
* Return empty buffer if something went wrong, else the complete
* dataline is returned
*/
char *nntp_receive(void)
{
static char buf[SS_BUFSIZE];
int i = 0, j;
if (nntpsock == -1)
return NULL;
memset((char *)&buf, 0, SS_BUFSIZE);
while (TRUE) {
j = recv(nntpsock, &buf[i], 1, 0);
if (j == -1) {
WriteError("$NNTP: error reading socket");
memset((char *)&buf, 0, SS_BUFSIZE);
if (errno == ENOTCONN || errno == EPIPE) {
WriteError("NNTP: closing local side");
nntpsock = -1;
}
return buf;
}
if (buf[i] == '\n')
break;
i += j;
}
for (i = 0; i < strlen(buf); i++) {
if (buf[i] == '\n')
buf[i] = '\0';
if (buf[i] == '\r')
buf[i] = '\0';
}
return buf;
}
int nntp_close(void)
{
if (nntpsock == -1)
return 0;
nntp_cmd((char *)"QUIT\r\n", 205);
if (shutdown(nntpsock, 1) == -1) {
WriteError("$NNTP: can't close socket");
return -1;
}
nntpsock = -1;
Syslog('+', "NNTP: closed");
return 0;
}
/*
* Send NNTP command, check response code.
* If the code doesn't match, the value is returned, else zero.
*/
int nntp_cmd(char *cmd, int resp)
{
char *p, rsp[6];
if (nntp_send(cmd) == -1)
return -1;
snprintf(rsp, 6, "%d", resp);
p = nntp_receive();
if (strncmp(p, "480", 3) == 0) {
/*
* Must login with username and password
*/
Syslog('+', "NNTP: %s", p);
if (nntp_auth() == FALSE) {
WriteError("Authorisation failure");
nntp_close();
return -1;
}
/*
* Now send command again, we are now authorized.
*/
if (nntp_send(cmd) == -1)
return -1;
p = nntp_receive();
}
if (strncmp(p, rsp, strlen(rsp))) {
WriteError("NNTP> %s", cmd);
WriteError("NNTP< %s", p);
memset(&resp, 0, sizeof(rsp));
strncpy(rsp, p, 3);
return atoi(rsp);
}
return 0;
}
int nntp_auth(void)
{
char *cmd;
if (!(strlen(CFG.nntpuser) && strlen(CFG.nntppass))) {
WriteError("NNTP: password required but not configured");
return FALSE;
}
cmd = calloc(128, sizeof(char));
snprintf(cmd, 128, "AUTHINFO USER %s\r\n", CFG.nntpuser);
if (nntp_cmd(cmd, 381))
return FALSE;
snprintf(cmd, 128, "AUTHINFO PASS %s\r\n", CFG.nntppass);
if (nntp_cmd(cmd, 281) == 0) {
free(cmd);
Syslog('+', "NNTP: logged in");
return TRUE;
} else {
free(cmd);
return FALSE;
}
}

1164
lib/nodelist.c Normal file

File diff suppressed because it is too large Load Diff

187
lib/nodelist.conf Normal file
View File

@@ -0,0 +1,187 @@
############################################################################
#
# ~/etc/nodelist.conf Nodelist configuration for MBSE BBS.
# $Id: nodelist.conf,v 1.11 2004/07/11 11:49:51 mbse Exp $
#
############################################################################
# Copyright (C) 1997-2003
#
# 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.
#############################################################################
# WARNING: This file is needed from v0.37.00 and later. The format of this
# file is under development.
# It will implement some new features that will become FTSC standards
# during 2003
#
# WARNING: Do not change anything in this file unless you know what
# you are doing.
#
# WARNING: During development this file will be overwritten during each
# make install, so don't even bother to change it in the ~/etc directory.
#
# WARNING: This file will replace hardcoded behaviour of several parts of
# the MBSE BBS package, tampering with this file is at your own risk.
# Online special flags. CM and ICM must be the first two!
#
online CM 0x00000001
online ICM 0x00000002
online MO 0x00000004
online LO 0x00000008
online MN 0x00000010
# Request flags, masks:
# 0x00000001 Bark request
# 0x00000002 Bark update
# 0x00000004 Wazoo request
# 0x00000008 Wazoo update
#
request XA 0x0000000F # Bark request, Bark update, Wazoo request, Wazoo update
request XB 0x00000007 # Bark request, Bark update, Wazoo request
request XC 0x0000000D # Bark request, Wazoo request, Wazoo update
request XP 0x00000003 # Bark request, Bark update
request XR 0x00000005 # Bark request, Wazoo request
request XW 0x00000004 # Wazoo request
request XX 0x0000000C # Wazoo request, Wazoo update
# Request flags bits
#
reqbits RQ_BR 0x00000001 # Bark request
reqbits RQ_BU 0x00000002 # Bark update
reqbits RQ_WR 0x00000004 # Wazoo request
reqbits RQ_WU 0x00000008 # Wazoo update
# Network services, the valid IP flags translated to the internet service
# names and their default ports.
#
service IBN binkp 24554
service IFC fido 60179
service ITN telnet 23
# Switched network service names, they are used to build the
# URLs for modem and ISDN lines.
#
dialer pots
dialer isdn
# Modem flags, order is important to check the fastest possible connection
# method. This also masks implied modes.
#
# flag entry implied mask
pots MNP 0x00000001 0x00000001
pots V42 0x00000002 0x00000003 # implies MNP
pots V42B 0x00000004 0x00000007 # implies MNP and V42
pots V22 0x00000008 0x00000008
pots V29 0x00000010 0x00000010
pots V32 0x00000020 0x00000020
pots H96 0x00000040 0x00000040
pots HST 0x00000080 0x00000081 # implies MNP
pots MAX 0x00000100 0x00000100
pots PEP 0x00000200 0x00000200
pots CSP 0x00000400 0x00000400
pots V32B 0x00000800 0x00000820 # implies V32
pots H14 0x00001000 0x00001081 # implies HST and MNP
pots V32T 0x00002000 0x00002820 # implies V32B and V32
pots H16 0x00004000 0x00005087 # implies H14, HST, MNP, V42, V42B
pots ZYX 0x00008000 0x00008827 # implies V32B, V32, V42B, V42, MNP
pots Z19 0x00010000 0x00018827 # implies V32B, V32, V42B, V42, MNP, ZYX
pots VFC 0x00020000 0x00020000
pots V34 0x00040000 0x00040000
pots X2C 0x00080000 0x001B0000 # implies X2S, V34
pots X2S 0x00100000 0x00140000 # implies V34
pots V90C 0x00200000 0x00640000 # implies V90S, V34
pots V90S 0x00400000 0x00440000 # implies V34
# ISDN flags in order of best speed.
#
# flag mask ORed mask
isdn V110L 0x00000001 0x00000001
isdn V110H 0x00000002 0x00000002
isdn V120L 0x00000004 0x00000004
isdn V120H 0x00000008 0x00000008
isdn X75 0x00000010 0x00000010
# Supported IP protocols by the mailer in order of preference.
# The names must match the service names.
#
tcpip ITN 0x00000001 0x00000001
tcpip IFC 0x00000002 0x00000002
tcpip IBN 0x00000004 0x00000004
# The following gives the order to search for the
# FQDN or IP address of the node. Valid values are:
# field3 - Search in the system name field, may have :port suffix.
# 192.168.1.40:1234 or ntbox.mbse.ym:5678 are valid.
# field6 - Search the phone field for 000- prefix, may be a IP
# or a FQDN with or without a :port suffix.
# 000-192-168-1-40:1234 or 000-ntbox.mbse.ym:5678 are valid.
# The keyword ipprefix below define the possible prefix names.
# field8 - Search in the flags for a FQDN. Valid flags are like:
# IBN:domain.com Standard
# IFC:domain.com:port Standard
# IBN:1.2.3.5 Standard
# ITN:1.2.3.4:port Standard
# IBN:* Proposed, use default domain
# IBN:*:port Not yet proposed
# eslf - Extended St. Louis Format fields (NOT YET AVAILABLE)
# defdomain - Asume default domain (VERY EXPERIMENTAL)
#
# In all cases, the nodes setup overrides everything.
# Order is important, defdomain must be the last if used.
#
search field3
search field8
search field6
search defdomain
# The default searchdomain, will be prefixed with f1.n2.z3.fidonet or
# f33.n44.z55.othernet. Add other networks here.
# Node 3:2/1 will look like: f1.n2.z3.fidonet.net
#
# Zone Suffix (without leading dot!)
domsuffix 1 net
domsuffix 2 net
domsuffix 3 net
domsuffix 4 net
domsuffix 5 net
domsuffix 6 net
domsuffix 92 mbse.ym
# The IP prefixes for nodelist field 6 like 000-
#
ipprefix 000- # Standard
ipprefix DNS- # Used in skynet
ipprefix IPN- # Used in skynet

128
lib/nodelist.h Normal file
View File

@@ -0,0 +1,128 @@
/* $Id: nodelist.h,v 1.9 2007/03/03 14:28:41 mbse Exp $ */
#ifndef _NODELIST_H
#define _NODELIST_H
#include "../config.h"
#define MAXNAME 35
#define MAXUFLAGS 16
/*
* Nodelist entry
*/
typedef struct _node {
faddr addr; /* Node address */
unsigned short upnet; /* Uplink netnumber */
unsigned short upnode; /* Uplink nodenumber */
unsigned short region; /* Region belongin to */
unsigned char type;
unsigned char pflag;
char *name; /* System name */
char *location; /* System location */
char *sysop; /* Sysop name */
char *phone; /* Phone number */
unsigned speed; /* Baudrate */
unsigned int mflags; /* Modem flags */
unsigned int dflags; /* ISDN flags */
unsigned int iflags; /* TCP-IP flags */
unsigned int oflags; /* Online flags */
unsigned int xflags; /* Request flags */
char *uflags[MAXUFLAGS]; /* User flags */
int t1; /* T flag, first char */
int t2; /* T flag, second char */
char *url; /* URL for connection */
unsigned is_cm : 1; /* Node is CM */
unsigned is_icm : 1; /* Node is ICM */
unsigned can_pots : 1; /* Can do POTS or ISDN */
unsigned can_ip : 1; /* Can do TCP/IP */
} node;
/*
* Memory array structures read from nodelist.conf
*/
typedef struct _nodelist_flag {
struct _nodelist_flag *next;
char *name;
unsigned int value;
} nodelist_flag;
typedef struct _nodelist_modem {
struct _nodelist_modem *next;
char *name;
unsigned int mask;
unsigned int value;
} nodelist_modem;
typedef struct _nodelist_array {
struct _nodelist_array *next;
char *name;
} nodelist_array;
typedef struct _nodelist_domsuf {
struct _nodelist_domsuf *next;
unsigned short zone;
char *name;
} nodelist_domsuf;
typedef struct _nodelist_service {
struct _nodelist_service *next;
char *flag;
char *service;
unsigned int defport; /* Configured default port */
unsigned int tmpport; /* Override port for call */
} nodelist_service;
extern struct _nodelist {
char *domain;
FILE *fp;
} *nodevector;
struct _ixentry {
unsigned short zone;
unsigned short net;
unsigned short node;
unsigned short point;
};
extern struct _pkey {
char *key;
unsigned char type;
unsigned char pflag;
} pkey[];
nodelist_flag *nl_online;
nodelist_flag *nl_request;
nodelist_flag *nl_reqbits;
nodelist_modem *nl_pots;
nodelist_modem *nl_isdn;
nodelist_modem *nl_tcpip;
nodelist_array *nl_search;
nodelist_array *nl_dialer;
nodelist_array *nl_ipprefix;
nodelist_domsuf *nl_domsuffix;
nodelist_service *nl_service;
/*
* From nodelist.c
*/
int initnl(void);
void deinitnl(void);
node *getnlent(faddr *);
#endif

179
lib/nodelock.c Normal file
View File

@@ -0,0 +1,179 @@
/*****************************************************************************
*
* $Id: nodelock.c,v 1.13 2005/10/11 20:49:46 mbse Exp $
* Purpose ...............: Node locking
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
int nodelock(faddr *addr, pid_t mypid)
{
char *fn, *tfn, *p, tmp[16], *progname;
FILE *fp;
pid_t pid;
int tmppid, sverr, rc;
time_t ltime, now;
fn = bsyname(addr);
tfn = xstrcpy(fn);
if ((p=strrchr(tfn,'/')))
*++p='\0';
snprintf(tmp, 16, "aa%d", mypid);
tfn = xstrcat(tfn, tmp);
mkdirs(tfn, 0770);
if ((fp = fopen(tfn,"w")) == NULL) {
WriteError("$Can't open tmp file for bsy lock (%s) \"%s\"",ascfnode(addr, 0x1f), tfn);
free(tfn);
return 1;
}
fprintf(fp,"%10d\n", mypid);
fclose(fp);
chmod(tfn, 0440);
if (link(tfn, fn) == 0) {
unlink(tfn);
free(tfn);
return 0;
} else {
sverr = errno;
}
if (sverr != EEXIST) {
WriteError("$Could not link \"%s\" to \"%s\"",tfn,fn);
WriteError("Locking %s failed", ascfnode(addr, 0x1f));
unlink(tfn);
free(tfn);
return 1;
}
if ((fp = fopen(fn,"r")) == NULL) {
WriteError("$Could not open existing lock file \"%s\"",fn);
WriteError("Locking %s failed", ascfnode(addr, 0x1f));
unlink(tfn);
free(tfn);
return 1;
}
/*
* Lock exists, check owner. If rc <> 1 then the lock may have
* been created by another OS (zero bytes lock).
*/
rc = fscanf(fp, "%d", &tmppid);
pid = tmppid;
fclose(fp);
/*
* If lock is our own lock, then it's ok and we are ready.
*/
if (mypid == pid) {
unlink(tfn);
free(tfn);
return 0;
}
/*
* Stale or old lock tests
*/
ltime = file_time(fn);
now = time(NULL);
if (CFG.ZeroLocks && (rc != 1) && (((unsigned int)now - (unsigned int)ltime) > 21600)) {
Syslog('+', "Found zero byte lock older then 6 hours for %s, unlink", ascfnode(addr,0x1f));
unlink(fn);
} else if (CFG.ZeroLocks && (rc != 1)) {
Syslog('+', "Node %s is locked from another OS", ascfnode(addr, 0x1f));
unlink(tfn);
free(tfn);
return 1;
} else if (kill(pid, 0) && (errno == ESRCH)) {
Syslog('+', "Found stale bsy file for %s, unlink", ascfnode(addr,0x1f));
unlink(fn);
} else if (((unsigned int)now - (unsigned int)ltime) > 21600) {
Syslog('+', "Found lock older then 6 hours for %s, unlink", ascfnode(addr,0x1f));
unlink(fn);
} else {
progname = calloc(PATH_MAX, sizeof(char));
if (pid2prog(pid, progname, PATH_MAX) == 0)
Syslog('+', "Node %s is locked by pid %d (%s)", ascfnode(addr, 0x1f), pid, progname);
else
Syslog('+', "Node %s is locked by pid %d", ascfnode(addr, 0x1f), pid);
free(progname);
unlink(tfn);
free(tfn);
return 1;
}
if (link(tfn,fn) == 0) {
unlink(tfn);
free(tfn);
return 0;
} else {
WriteError("$Could not link \"%s\" to \"%s\"",tfn,fn);
WriteError("Locking %s failed", ascfnode(addr, 0x1f));
unlink(tfn);
free(tfn);
return 1;
}
}
int nodeulock(faddr *addr, pid_t mypid)
{
char *fn;
FILE *fp;
pid_t pid;
int tmppid = 0, rc;
fn = bsyname(addr);
if ((fp = fopen(fn, "r")) == NULL) {
Syslog('+', "Unlock %s failed, not locked", ascfnode(addr, 0x1f));
return 1;
}
rc = fscanf(fp, "%d", &tmppid);
pid = tmppid;
fclose(fp);
if (CFG.ZeroLocks && (rc != 1)) {
/*
* Zero byte lock from another OS, leave alone.
*/
return 0;
} else if (pid == mypid) {
unlink(fn);
return 0;
} else {
WriteError("Unlock (%s) file failed for process %u, we are %u", ascfnode(addr, 0x1f), pid,mypid);
return 1;
}
}

56
lib/noderecord.c Normal file
View File

@@ -0,0 +1,56 @@
/*****************************************************************************
*
* $Id: noderecord.c,v 1.7 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: Load noderecord
*
*****************************************************************************
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
int noderecord(faddr *addr)
{
fidoaddr fa;
memset(&fa, 0, sizeof(fa));
fa.zone = addr->zone;
fa.net = addr->net;
fa.node = addr->node;
fa.point = addr->point;
if (!(TestNode(fa)))
if (!SearchNode(fa)) {
return FALSE;
}
return TRUE;
}

189
lib/packet.c Normal file
View File

@@ -0,0 +1,189 @@
/*****************************************************************************
*
* $Id: packet.c,v 1.12 2005/08/28 13:34:43 mbse Exp $
* Purpose ...............: Fidonet mailer
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
static FILE *pktfp=NULL;
static faddr pktroute =
{
NULL,0,0,0,0,NULL
};
FILE *openpkt(FILE *pkt, faddr *addr, char flavor, int session)
{
off_t pos;
struct flock fl;
struct stat st;
char *Name;
struct tm *ptm;
time_t t;
int i;
faddr *bestaka;
unsigned char buffer[0x3a];
char str[9];
if (pkt == NULL) {
if (pktfp) {
if (metric(addr,&pktroute) == 0) {
if ((CFG.maxpktsize == 0L) || ((fstat(fileno(pktfp),&st) == 0) && (st.st_size < CFG.maxpktsize))) {
return pktfp;
}
closepkt();
} else {
closepkt();
}
}
pktroute.zone = addr->zone;
pktroute.net = addr->net;
pktroute.node = addr->node;
pktroute.point = addr->point;
pktroute.domain = xstrcpy(addr->domain);
pktroute.name = NULL;
Name = pktname(addr,flavor);
mkdirs(Name, 0770);
if ((pktfp = fopen(Name, "r+")) == NULL)
pktfp = fopen(Name,"w");
if (pktfp == NULL) {
WriteError("$Unable to open packet %s",MBSE_SS(Name));
return NULL;
}
fl.l_type = F_WRLCK;
fl.l_whence = 0;
fl.l_start = 0L;
fl.l_len = 0L;
if (fcntl(fileno(pktfp), F_SETLKW, &fl) < 0) {
WriteError("$Unable to lock packet %s", MBSE_SS(Name));
fclose(pktfp);
return NULL;
}
pkt = pktfp;
pos = fseek(pkt, -2L, SEEK_END);
}
pos = ftell(pkt);
if (pos <= 0L) {
/*
* Write .PKT header, see FSC-0039 rev. 4
*/
memset(&buffer, 0, sizeof(buffer));
t = time(NULL);
ptm = localtime(&t);
if (ptm->tm_sec > 59)
ptm->tm_sec = 59;
bestaka = bestaka_s(addr);
buffer[0x00] = (bestaka->node & 0x00ff);
buffer[0x01] = (bestaka->node & 0xff00) >> 8;
buffer[0x02] = (addr->node & 0x00ff);
buffer[0x03] = (addr->node & 0xff00) >> 8;
buffer[0x04] = ((ptm->tm_year + 1900) & 0x00ff);
buffer[0x05] = ((ptm->tm_year + 1900) & 0xff00) >> 8;
buffer[0x06] = ptm->tm_mon;
buffer[0x08] = ptm->tm_mday;
buffer[0x0a] = ptm->tm_hour;
buffer[0x0c] = ptm->tm_min;
buffer[0x0e] = ptm->tm_sec;
buffer[0x12] = 2;
buffer[0x14] = (bestaka->net & 0x00ff);
buffer[0x15] = (bestaka->net & 0xff00) >> 8;
buffer[0x16] = (addr->net & 0x00ff);
buffer[0x17] = (addr->net & 0xff00) >> 8;
buffer[0x18] = (PRODCODE & 0x00ff);
buffer[0x19] = (VERSION_MAJOR & 0x00ff);
memset(&str, 0, 8);
if (session) {
if (noderecord(addr) && strlen(nodes.Spasswd))
snprintf(str, 9, "%s", nodes.Spasswd);
} else {
if (noderecord(addr) && strlen(nodes.Epasswd))
snprintf(str, 9, "%s", nodes.Epasswd);
}
for (i = 0; i < 8; i++)
buffer[0x1a + i] = toupper(str[i]); /* FSC-0039 only talks about A-Z, 0-9, so force uppercase */
buffer[0x22] = (bestaka->zone & 0x00ff);
buffer[0x23] = (bestaka->zone & 0xff00) >> 8;
buffer[0x24] = (addr->zone & 0x00ff);
buffer[0x25] = (addr->zone & 0xff00) >> 8;
buffer[0x29] = 1;
buffer[0x2a] = (PRODCODE & 0xff00) >> 8;
buffer[0x2b] = (VERSION_MINOR & 0x00ff);
buffer[0x2c] = 1;
buffer[0x2e] = buffer[0x22];
buffer[0x2f] = buffer[0x23];
buffer[0x30] = buffer[0x24];
buffer[0x31] = buffer[0x25];
buffer[0x32] = (bestaka->point & 0x00ff);
buffer[0x33] = (bestaka->point & 0xff00) >> 8;
buffer[0x34] = (addr->point & 0x00ff);
buffer[0x35] = (addr->point & 0xff00) >> 8;
buffer[0x36] = 'm';
buffer[0x37] = 'b';
buffer[0x38] = 's';
buffer[0x39] = 'e';
fseek(pkt, 0L, SEEK_SET);
fwrite(buffer, 1, 0x3a, pkt);
}
return pkt;
}
void closepkt(void)
{
unsigned char buffer[2];
memset(&buffer, 0, sizeof(buffer));
if (pktfp) {
fwrite(buffer, 1, 2, pktfp);
fclose(pktfp); /* close also discards lock */
}
pktfp = NULL;
if (pktroute.domain)
free(pktroute.domain);
}

1781
lib/parsedate.c Normal file

File diff suppressed because it is too large Load Diff

119
lib/pidinfo.c Normal file
View File

@@ -0,0 +1,119 @@
/*****************************************************************************
*
* $Id: pidinfo.c,v 1.1 2005/10/09 13:37:11 mbse Exp $
* Purpose ...............: Pid utilities
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
/*
* Find the program name for a given pid. The progname buffer
* has te be allocated with size byte.
*/
int pid2prog(pid_t pid, char *progname, size_t size)
{
#if defined(__OpenBSD__)
#define ARG_SIZE 60
static char **s, buf[ARG_SIZE];
size_t siz = 100;
char **p;
int mib[4];
#elif defined(__NetBSD__)
#define ARG_SIZE 60
static char **s;
size_t siz = 100;
int mib[4];
#else
char temp[PATH_MAX];
FILE *fp;
#endif
#if defined(__OpenBSD__)
/*
* Systems that use sysctl to get process information
*/
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = pid;
mib[3] = KERN_PROC_ARGV;
if ((s = realloc(s, siz)) == NULL) {
WriteError("pid2prog(): no memory");
return -1;
}
if (sysctl(mib, 4, s, &siz, NULL, 0) == -1) {
WriteError("$pid2prog() sysctl call failed");
return -1;
}
buf[0] = '\0';
for (p = s; *p != NULL; p++) {
if (p != s)
strlcat(buf, " ", sizeof(buf));
strlcat(buf, *p, sizeof(buf));
}
strncpy(progname, buf, size);
return 0;
#elif defined(__NetBSD__)
/*
* Systems that use sysctl to get process information
*/
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = pid;
mib[3] = KERN_PROC_ARGV;
if ((s = realloc(s, siz)) == NULL) {
WriteError("pid2prog(): no memory");
return -1;
}
if (sysctl(mib, 4, s, &siz, NULL, 0) == -1) {
WriteError("$pid2prog() sysctl call failed");
return -1;
}
// parent = xstrcpy((char *)s);
strncpy(progname, (char *)s, size);
return 0;
#else
/*
* Systems with /proc filesystem like Linux, FreeBSD
*/
snprintf(temp, PATH_MAX, "/proc/%d/cmdline", pid);
if ((fp = fopen(temp, "r")) == NULL) {
WriteError("$Can't read %s", temp);
return -1;
}
fgets(temp, PATH_MAX-1, fp);
fclose(fp);
strncpy(progname, temp, size);
return 0;
#endif
}

291
lib/pktname.c Normal file
View File

@@ -0,0 +1,291 @@
/*****************************************************************************
*
* $Id: pktname.c,v 1.16 2007/02/03 12:18:42 mbse Exp $
* Purpose ...............: BinkleyTerm outbound naming
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
#include "users.h"
#include "mbsedb.h"
#ifndef PATH_MAX
#define PATH_MAX 512
#endif
#define ptyp "ut"
#define ftyp "lo"
#define ttyp "pk"
#define rtyp "req"
#define styp "spl"
#define btyp "bsy"
#define qtyp "sts"
#define ltyp "pol"
char *prepbuf(faddr *);
char *prepbuf(faddr *addr)
{
static char buf[PATH_MAX];
char *p, *domain=NULL, zpref[8];
int i;
snprintf(buf, PATH_MAX -1, "%s", CFG.outbound);
if (CFG.addr4d) {
Syslog('o', "Use 4d addressing, zone is %d", addr->zone);
if ((addr->zone == 0) || (addr->zone == CFG.aka[0].zone))
zpref[0] = '\0';
else
snprintf(zpref, 8, ".%03x", addr->zone);
} else {
/*
* If we got a 5d address we use the given domain, if
* we got a 4d address, we look for a matching domain name.
*/
if (addr && addr->domain && strlen(addr->domain)) {
domain = xstrcpy(addr->domain);
} else {
domain = xstrcpy(GetFidoDomain(addr->zone));
}
/*
* If we got a 2d address, add the default zone.
*/
if (addr->zone == 0 ) {
addr->zone = CFG.aka[0].zone;
}
if ((domain != NULL) && (strlen(CFG.aka[0].domain) != 0) && (strcasecmp(domain,CFG.aka[0].domain) != 0)) {
if ((p = strrchr(buf,'/')))
p++;
else
p = buf;
strcpy(p, domain);
for (; *p; p++)
*p = tolower(*p);
for (i = 0; i < 40; i++)
if ((strlen(CFG.aka[i].domain)) && (strcasecmp(CFG.aka[i].domain, domain) == 0))
break;
/*
* The default zone must be the first one in the
* setup, other zones get the hexadecimal zone
* number appended.
*/
if (CFG.aka[i].zone == addr->zone)
zpref[0] = '\0';
else
snprintf(zpref, 8, ".%03x", addr->zone);
} else {
/*
* this is our primary domain
*/
if ((addr->zone == 0) || (addr->zone == CFG.aka[0].zone))
zpref[0]='\0';
else
snprintf(zpref, 8, ".%03x",addr->zone);
}
}
p = buf + strlen(buf);
if (addr->point)
snprintf(p, PATH_MAX -1, "%s/%04x%04x.pnt/%08x.", zpref,addr->net,addr->node,addr->point);
else
snprintf(p, PATH_MAX -1, "%s/%04x%04x.",zpref,addr->net,addr->node);
if (domain)
free(domain);
return buf;
}
char *pktname(faddr *addr, char flavor)
{
static char *p, *q;
p = prepbuf(addr);
if (flavor == 'f')
flavor = 'o';
if (flavor == 'i')
flavor = 'd';
q = p + strlen(p);
snprintf(q, PATH_MAX -1, "%c%s", flavor, ptyp);
return p;
}
char *floname(faddr *addr, char flavor)
{
static char *p, *q;
p = prepbuf(addr);
if (flavor == 'o')
flavor = 'f';
if (flavor == 'i')
flavor = 'd';
q = p + strlen(p);
snprintf(q, PATH_MAX -1, "%c%s", flavor, ftyp);
return p;
}
char *reqname(faddr *addr)
{
static char *p, *q;
p = prepbuf(addr);
q = p + strlen(p);
snprintf(q, PATH_MAX -1, "%s", rtyp);
return p;
}
char *splname(faddr *addr)
{
static char *p, *q;
p = prepbuf(addr);
q = p + strlen(p);
snprintf(q, PATH_MAX -1, "%s", styp);
return p;
}
char *bsyname(faddr *addr)
{
static char *p, *q;
p = prepbuf(addr);
q = p + strlen(p);
snprintf(q, PATH_MAX -1, "%s", btyp);
return p;
}
char *stsname(faddr *addr)
{
static char *p, *q;
p = prepbuf(addr);
q = p + strlen(p);
snprintf(q, PATH_MAX -1, "%s", qtyp);
return p;
}
char *polname(faddr *addr)
{
static char *p, *q;
p = prepbuf(addr);
q = p + strlen(p);
snprintf(q, PATH_MAX -1, "%s", ltyp);
return p;
}
static char *dow[] = {(char *)"su", (char *)"mo", (char *)"tu", (char *)"we",
(char *)"th", (char *)"fr", (char *)"sa"};
char *dayname(void)
{
time_t tt;
struct tm *ptm;
static char buf[3];
tt = time(NULL);
ptm = localtime(&tt);
snprintf(buf, 3, "%s", dow[ptm->tm_wday]);
return buf;
}
char *arcname(faddr *addr, unsigned short Zone, int ARCmailCompat)
{
static char *buf;
char *p;
char *ext;
time_t tt;
struct tm *ptm;
faddr *bestaka;
tt = time(NULL);
ptm = localtime(&tt);
ext = dow[ptm->tm_wday];
bestaka = bestaka_s(addr);
buf = prepbuf(addr);
p = strrchr(buf, '/');
if (!ARCmailCompat && (Zone != addr->zone)) {
/*
* Generate ARCfile name from the CRC of the ASCII string
* of the node address.
*/
snprintf(p, PATH_MAX -1, "/%08x.%s0", StringCRC32(ascfnode(addr, 0x1f)), ext);
} else {
if (addr->point) {
snprintf(p, PATH_MAX -1, "/%04x%04x.%s0",
((bestaka->net) - (addr->net)) & 0xffff,
((bestaka->node) - (addr->node) + (addr->point)) & 0xffff,
ext);
} else if (bestaka->point) {
/*
* Inserted the next code for if we are a point,
* I hope this is ARCmail 0.60 compliant. 21-May-1999
*/
snprintf(p, PATH_MAX -1, "/%04x%04x.%s0", ((bestaka->net) - (addr->net)) & 0xffff,
((bestaka->node) - (addr->node) - (bestaka->point)) & 0xffff, ext);
} else {
snprintf(p, PATH_MAX -1, "/%04x%04x.%s0", ((bestaka->net) - (addr->net)) & 0xffff,
((bestaka->node) - (addr->node)) &0xffff, ext);
}
}
tidy_faddr(bestaka);
return buf;
}

199
lib/pop3.c Normal file
View File

@@ -0,0 +1,199 @@
/*****************************************************************************
*
* $Id: pop3.c,v 1.8 2007/08/25 15:29:14 mbse Exp $
* Purpose ...............: MBSE BBS Internet Library
*
*****************************************************************************
* 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 "mbselib.h"
#include "mbinet.h"
static int pop3sock = -1; /* TCP/IP socket */
struct hostent *php; /* Host info remote */
struct servent *psp; /* Service information */
struct sockaddr_in pop3_loc; /* For local socket address */
struct sockaddr_in pop3_rem; /* For remote socket address */
int pop3_connect(void)
{
socklen_t addrlen;
char *p;
if (!strlen(CFG.popnode)) {
WriteError("POP3: host not configured");
return -1;
}
Syslog('+', "POP3: connecting host: %s", CFG.popnode);
memset(&pop3_loc, 0, sizeof(struct sockaddr_in));
memset(&pop3_rem, 0, sizeof(struct sockaddr_in));
pop3_rem.sin_family = AF_INET;
if ((php = gethostbyname(CFG.popnode)) == NULL) {
WriteError("POP3: can't find host %s", CFG.popnode);
return -1;
}
pop3_rem.sin_addr.s_addr = ((struct in_addr *)(php->h_addr))->s_addr;
if ((psp = getservbyname("pop3", "tcp")) == NULL) {
/*
* RedHat doesn't follow IANA specs and uses pop-3 in /etc/services
*/
if ((psp = getservbyname("pop-3", "tcp")) == NULL) {
WriteError("POP3: can't find service port for pop3/tcp");
return -1;
}
}
pop3_rem.sin_port = psp->s_port;
if ((pop3sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
WriteError("$POP3: unable to create tcp socket");
return -1;
}
if (connect(pop3sock, (struct sockaddr *)&pop3_rem, sizeof(struct sockaddr_in)) == -1) {
WriteError("$POP3: cannot connect tcp socket");
return -1;
}
addrlen = sizeof(struct sockaddr_in);
if (getsockname(pop3sock, (struct sockaddr *)&pop3_loc, &addrlen) == -1) {
WriteError("$POP3: unable to read socket address");
return -1;
}
p = pop3_receive();
if (strlen(p) == 0) {
WriteError("POP3: no response from server");
pop3_close();
return -1;
}
if (strncmp(p, "+OK", 3)) {
WriteError("POP3: bad response: %s", p);
pop3_close();
return -1;
}
Syslog('+', "POP3: %s", p);
return pop3sock;
}
int pop3_send(char *buf)
{
if (pop3sock == -1)
return -1;
if (send(pop3sock, buf, strlen(buf), 0) != strlen(buf)) {
WriteError("$POP3: socket send failed");
return -1;
}
return 0;
}
/*
* Return empty buffer if something went wrong, else the complete
* dataline is returned
*/
char *pop3_receive(void)
{
static char buf[SS_BUFSIZE];
int i, j;
memset((char *)&buf, 0, SS_BUFSIZE);
i = 0;
while (TRUE) {
j = recv(pop3sock, &buf[i], 1, 0);
if (j == -1) {
WriteError("$POP3: error reading socket");
memset((char *)&buf, 0, SS_BUFSIZE);
return buf;
}
if (buf[i] == '\n')
break;
i += j;
}
for (i = 0; i < strlen(buf); i++) {
if (buf[i] == '\n')
buf[i] = '\0';
if (buf[i] == '\r')
buf[i] = '\0';
}
return buf;
}
int pop3_close(void)
{
if (pop3sock == -1)
return 0;
if (shutdown(pop3sock, 1) == -1) {
WriteError("$POP3: can't close socket");
return -1;
}
pop3sock = -1;
Syslog('+', "POP3: closed");
return 0;
}
int pop3_cmd(char *cmd)
{
char *p;
if (pop3_send(cmd) == -1)
return -1;
p = pop3_receive();
if (strncmp(p, "+OK", 3)) {
WriteError("POP3> %s", cmd);
WriteError("POP3< %s", p);
return -1;
}
return 0;
}

135
lib/proglock.c Normal file
View File

@@ -0,0 +1,135 @@
/*****************************************************************************
*
* $Id: proglock.c,v 1.6 2005/08/27 18:53:32 mbse Exp $
* Purpose ...............: Program Locking
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
extern int do_quiet; /* Quiet flag */
/*
* Put a lock on a program.
*/
int lockprogram(char *progname)
{
char *tempfile, *lockfile;
FILE *fp;
pid_t oldpid;
tempfile = calloc(PATH_MAX, sizeof(char));
lockfile = calloc(PATH_MAX, sizeof(char));
snprintf(tempfile, PATH_MAX -1, "%s/var/run/%s.tmp", getenv("MBSE_ROOT"), progname);
snprintf(lockfile, PATH_MAX -1, "%s/var/run/%s", getenv("MBSE_ROOT"), progname);
if ((fp = fopen(tempfile, "w")) == NULL) {
WriteError("$Can't create lockfile \"%s\"", tempfile);
free(tempfile);
free(lockfile);
return 1;
}
fprintf(fp, "%10u\n", getpid());
fclose(fp);
while (TRUE) {
if (link(tempfile, lockfile) == 0) {
unlink(tempfile);
free(tempfile);
free(lockfile);
return 0;
}
if ((fp = fopen(lockfile, "r")) == NULL) {
WriteError("$Can't open lockfile \"%s\"", lockfile);
unlink(tempfile);
free(tempfile);
free(lockfile);
return 1;
}
if (fscanf(fp, "%u", &oldpid) != 1) {
WriteError("$Can't read old pid from \"%s\"", tempfile);
fclose(fp);
unlink(tempfile);
free(tempfile);
free(lockfile);
return 1;
}
fclose(fp);
if (kill(oldpid,0) == -1) {
if (errno == ESRCH) {
Syslog('+', "Stale lock found for pid %u", oldpid);
unlink(lockfile);
/* no return, try lock again */
} else {
WriteError("$Kill for %u failed", oldpid);
unlink(tempfile);
free(tempfile);
free(lockfile);
return 1;
}
} else {
Syslog('+', "%s already running, pid=%u", progname, oldpid);
if (!do_quiet)
printf("Another %s is already running.\n", progname);
unlink(tempfile);
free(tempfile);
free(lockfile);
return 1;
}
}
}
void ulockprogram(char *progname)
{
char *lockfile;
FILE *fp;
pid_t oldpid;
lockfile = calloc(PATH_MAX, sizeof(char));
snprintf(lockfile, PATH_MAX -1, "%s/var/run/%s", getenv("MBSE_ROOT"), progname);
if ((fp = fopen(lockfile, "r")) == NULL) {
WriteError("$Can't open lockfile \"%s\"", lockfile);
free(lockfile);
return;
}
if (fscanf(fp, "%u", &oldpid) != 1) {
WriteError("$Can't read old pid from \"%s\"", lockfile);
}
fclose(fp);
unlink(lockfile);
free(lockfile);
lockfile = NULL;
}

334
lib/rawio.c Normal file
View File

@@ -0,0 +1,334 @@
/*****************************************************************************
*
* $Id: rawio.c,v 1.11 2005/10/11 20:49:46 mbse Exp $
* Purpose ...............: Raw I/O routines.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
int rawset = FALSE;
/*
* Sets raw mode and saves the terminal setup
*/
void mbse_Setraw()
{
int rc;
if ((rc = tcgetattr(ttyfd, &tbufs))) {
perror("");
printf("$tcgetattr(0, save) return %d\n", rc);
exit(MBERR_TTYIO_ERROR);
}
tbufsavs = tbufs;
tbufs.c_iflag &= ~(INLCR | ICRNL | ISTRIP | IXON ); /* IUCLC removed for FreeBSD */
/*
* Map CRNL modes strip control characters and flow control
*/
tbufs.c_oflag &= ~OPOST; /* Don't do ouput character translation */
tbufs.c_lflag &= ~(ICANON | ECHO); /* No canonical input and no echo */
tbufs.c_cc[VMIN] = 1; /* Receive 1 character at a time */
tbufs.c_cc[VTIME] = 0; /* No time limit per character */
if ((rc = tcsetattr(ttyfd, TCSADRAIN, &tbufs))) {
perror("");
printf("$tcsetattr(%d, TCSADRAIN, raw) return %d\n", ttyfd, rc);
exit(MBERR_TTYIO_ERROR);
}
rawset = TRUE;
}
/*
* Unsets raw mode and returns state of terminal
*/
void mbse_Unsetraw()
{
int rc;
/*
* Only unset the mode if it is set to raw mode
*/
if (rawset == TRUE) {
if ((rc = tcsetattr(ttyfd, TCSAFLUSH, &tbufsavs))) {
perror("");
printf("$tcsetattr(%d, TCSAFLUSH, save) return %d\n", ttyfd, rc);
exit(MBERR_TTYIO_ERROR);
}
}
rawset = FALSE;
}
/*
* This function is used to get a single character from a user ie for a
* menu option
*/
unsigned char mbse_Getone()
{
unsigned char c = 0;
if ((ttyfd = open ("/dev/tty", O_RDWR|O_NONBLOCK)) < 0) {
perror("open 8");
exit(MBERR_TTYIO_ERROR);
}
mbse_Setraw();
c = mbse_Readkey();
mbse_Unsetraw();
close(ttyfd);
return(c);
}
/*
* Read the (locked) speed from the tty
*/
int mbse_Speed(void)
{
speed_t mspeed;
mspeed = cfgetospeed(&tbufs);
#ifdef CBAUD
switch (mspeed & CBAUD) {
#else
switch (mspeed) {
#endif
case B0: return 0;
#if defined(B50)
case B50: return 50;
#endif
#if defined(B75)
case B75: return 75;
#endif
#if defined(B110)
case B110: return 110;
#endif
#if defined(B134)
case B134: return 134;
#endif
#if defined(B150)
case B150: return 150;
#endif
#if defined(B200)
case B200: return 200;
#endif
#if defined(B300)
case B300: return 300;
#endif
#if defined(B600)
case B600: return 600;
#endif
#if defined(B1200)
case B1200: return 1200;
#endif
#if defined(B1800)
case B1800: return 1800;
#endif
#if defined(B2400)
case B2400: return 2400;
#endif
#if defined(B4800)
case B4800: return 4800;
#endif
#if defined(B9600)
case B9600: return 9600;
#endif
#if defined(B19200)
case B19200: return 19200;
#endif
#if defined(B38400)
case B38400: return 38400;
#endif
#if defined(B57600)
case B57600: return 57600;
#endif
#if defined(B115200)
case B115200: return 115200;
#endif
#if defined(B230400)
case B230400: return 203400;
#endif
#if defined(B460800)
case B460800: return 460800;
#endif
#if defined(B500000)
case B500000: return 500000;
#endif
#if defined(B576000)
case B576000: return 576000;
#endif
#if defined(B921600)
case B921600: return 921600;
#endif
#if defined(B1000000)
case B1000000: return 1000000;
#endif
#if defined(B1152000)
case B1152000: return 1152000;
#endif
#if defined(B1500000)
case B1500000: return 1500000;
#endif
#if defined(B2000000)
case B2000000: return 2000000;
#endif
#if defined(B2500000)
case B2500000: return 2500000;
#endif
#if defined(B3000000)
case B3000000: return 3000000;
#endif
#if defined(B3500000)
case B3500000: return 3500000;
#endif
#if defined(B4000000)
case B4000000: return 4000000;
#endif
default: return 9600;
}
}
/*
* Wait for a character for a maximum of wtime * 10 mSec.
*/
int mbse_Waitchar(unsigned char *ch, int wtime)
{
int i, rc = -1;
for (i = 0; i < wtime; i++) {
rc = read(ttyfd, ch, 1);
if (rc == 1)
return rc;
msleep(10);
}
return rc;
}
int mbse_Escapechar(unsigned char *ch)
{
int rc;
unsigned char c;
/*
* Escape character, if nothing follows within
* 50 mSec, the user really pressed <esc>.
*/
if ((rc = mbse_Waitchar(ch, 5)) == -1)
return rc;
if (*ch == '[') {
/*
* Start of CSI sequence. If nothing follows,
* return immediatly.
*/
if ((rc = mbse_Waitchar(ch, 5)) == -1)
return rc;
/*
* Test for the most important keys. Note
* that only the cursor movement keys are
* guaranteed to work with PC-clients.
*/
c = *ch;
if (c == 'A')
c = KEY_UP;
if (c == 'B')
c = KEY_DOWN;
if (c == 'C')
c = KEY_RIGHT;
if (c == 'D')
c = KEY_LEFT;
if ((c == '1') || (c == 'H') || (c == 0))
c = KEY_HOME;
if ((c == '4') || (c == 'K') || (c == 101) || (c == 144))
c = KEY_END;
if (c == '2')
c = KEY_INS;
if (c == '3')
c = KEY_DEL;
if (c == '5')
c = KEY_PGUP;
if (c == '6')
c = KEY_PGDN;
memcpy(ch, &c, sizeof(unsigned char));
return rc;
}
return -1;
}
/*
* This next function will detect the grey keys on the keyboard for
* VT100, VT220, Xterm, PC-ANSI, and Linux console. Works with
* several terminals on serial lines (tested 1200 bps).
* If for example cursur keys are detected, this function returns
* a translated value.
*/
unsigned char mbse_Readkey(void)
{
unsigned char ch = 0;
int rc = -1;
while (rc == -1) {
rc = mbse_Waitchar(&ch, 5);
/*
* If the character is not an Escape character,
* then this function is finished.
*/
if ((rc == 1) && (ch != KEY_ESCAPE))
return ch;
if ((rc == 1) && (ch == KEY_ESCAPE)) {
rc = mbse_Escapechar(&ch);
if (rc == 1)
return ch;
else
return KEY_ESCAPE;
}
}
return(ch);
}

200
lib/rearc.c Normal file
View File

@@ -0,0 +1,200 @@
/*****************************************************************************
*
* $Id: rearc.c,v 1.7 2008/11/26 21:40:54 mbse Exp $
* Purpose ...............: ReArc an archive.
*
*****************************************************************************
* Copyright (C) 1997-2008
*
* 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 "mbselib.h"
/*
* Rearchive an archive, if successfull the filename is updated.
* If it fails, return -1.
*/
int rearc(char *filename, char *arctype, int do_quiet)
{
char *p, *uncmd = NULL, *arccmd = NULL, *unarc, *newname, *workpath, *oldpath, *temp;
int rc = 0;
Syslog('f', "rearc(%s, %s)", filename, arctype);
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" ReArc file %s ", filename);
fflush(stdout);
}
if (strchr(filename, '/') == NULL) {
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" no path in filename\n");
}
Syslog('+', "rearc(%s, %s), no path in filename", filename, arctype);
return -1;
}
if ((unarc = unpacker(filename)) == NULL) {
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" unknown archive type\n");
}
return -1;
}
if (!getarchiver(unarc)) {
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" no unarchiver available\n");
}
Syslog('+', "rearc(%s, %s), no unarchiver available", filename, arctype);
return -1;
}
if (strlen(archiver.funarc) == 0) {
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" no unarchive command available\n");
}
Syslog('+', "rearc(%s, %s), no unarchive command available", filename, arctype);
return -1;
}
uncmd = xstrcpy(archiver.funarc);
newname = calloc(PATH_MAX, sizeof(char));
strcpy(newname, filename);
p = strrchr(newname, '.');
*p++;
*p = '\0';
if (!getarchiver(arctype)) {
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" no archiver available\n");
}
Syslog('+', "rearc(%s, %s), no archiver available", filename, arctype);
free(uncmd);
free(newname);
return -1;
}
if (strcmp(unarc, archiver.name) == 0) {
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" already in %s format\n", arctype);
}
Syslog('+', "rearc(%s, %s), already in %s format", filename, arctype, arctype);
free(uncmd);
free(newname);
return -1;
}
snprintf(p, 6, "%s", archiver.name);
Syslog('f', "new filename %s", newname);
if (strlen(archiver.farc) == 0) {
if (!do_quiet) {
mbse_colour(LIGHTRED, BLACK);
printf(" no archive command available\n");
}
Syslog('+', "rearc(%s, %s), no archive command available", filename, arctype);
free(uncmd);
free(newname);
return -1;
}
arccmd = xstrcpy(archiver.farc);
/*
* unarchive and archive commands are available, create a temp directory to work in.
*/
workpath = calloc(PATH_MAX, sizeof(char));
oldpath = calloc(PATH_MAX, sizeof(char));
temp = calloc(PATH_MAX, sizeof(char));
getcwd(oldpath, PATH_MAX);
snprintf(workpath, PATH_MAX -1, "%s/tmp/rearc%d", getenv("MBSE_ROOT"), getpid());
snprintf(temp, PATH_MAX -1, "%s/%s", workpath, filename);
rc = mkdirs(temp, 0755) ? 0 : -1;
if (rc == 0) {
if ((rc = chdir(workpath)) == -1) {
WriteError("$Can't chdir to %s", workpath);
}
}
if (!do_quiet) {
mbse_colour(LIGHTCYAN, BLACK);
printf("\rUnpacking file %s ", filename);
fflush(stdout);
}
/*
* Unarchive
*/
if (rc == 0) {
if ((rc = execute_str(uncmd,filename,(char *)NULL,(char*)"/dev/null",(char*)"/dev/null",(char*)"/dev/null"))) {
WriteError("$Can't unpack %s", filename);
}
}
if (!do_quiet) {
mbse_colour(LIGHTGREEN, BLACK);
printf("\r Packing file %s ", newname);
}
/*
* Archive
*/
if (rc == 0) {
if ((rc = execute_str(arccmd,newname,(char *)".",(char*)"/dev/null",(char*)"/dev/null",(char*)"/dev/null"))) {
WriteError("$Can't pack %s", newname);
}
}
if (rc == 0)
unlink(filename);
if ((rc = chdir(oldpath)) == -1) {
WriteError("$Can't chdir to %s", oldpath);
}
/*
* Clean and remove workdir
*/
snprintf(temp, PATH_MAX -1, "-rf %s", workpath);
execute_pth((char *)"rm", temp, (char*)"/dev/null", (char*)"/dev/null", (char*)"/dev/null");
if (rc == 0)
snprintf(filename, PATH_MAX -1, "%s", newname);
free(workpath);
free(oldpath);
free(temp);
free(uncmd);
free(arccmd);
free(newname);
return rc;
}

84
lib/remask.c Normal file
View File

@@ -0,0 +1,84 @@
/*****************************************************************************
*
* $Id: remask.c,v 1.4 2007/03/03 14:28:41 mbse Exp $
* Purpose ...............: Regular Expression Mask
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
char *re_mask(char *nm, int forceupper)
{
char *p, *q;
static char mask[256];
memset(&mask, 0, sizeof(mask));
if (forceupper)
p = tl(nm);
else
p = nm;
q = mask;
*q++ = '^';
while ((*p) && (q < (mask + sizeof(mask) - 4))) {
switch (*p) {
case '\\': *q++ = '\\';
*q++ = '\\';
break;
case '?': *q++ = '.';
break;
case '.': *q++ = '\\';
*q++ = '.';
break;
case '+': *q++ = '\\';
*q++ = '+';
break;
case '*': *q++ = '.';
*q++ = '*';
break;
case '@': snprintf(q, 9, "[A-Za-z]");
while (*q)
q++;
break;
case '#': snprintf(q, 6, "[0-9]");
while (*q)
q++;
break;
default: if (forceupper)
*q++ = toupper(*p);
else
*q++ = *p;
break;
}
p++;
}
*q++ = '$';
*q++ = '\0';
return mask;
}

285
lib/rfcaddr.c Normal file
View File

@@ -0,0 +1,285 @@
/*****************************************************************************
*
* $Id: rfcaddr.c,v 1.7 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: MBSE BBS Common Library - RFC address functions
*
*****************************************************************************
* 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 "mbselib.h"
extern int addrerror;
static char *errname[] = {
(char *)"nested <>",
(char *)"multiple <>",
(char *)"unmatched <>""()",
(char *)"badtoken",
(char *)"badstructure",
};
char *addrerrstr(int err)
{
int i;
static char buf[128];
buf[0] = '\0';
for (i = 0; i < ADDR_ERRMAX; i++)
if (err & (1 << i)) {
if (buf[0])
strcat(buf,",");
strcat(buf, errname[i]);
}
if (buf[0] == '\0')
strcpy(buf,"none");
return buf;
}
void tidyrfcaddr(parsedaddr addr)
{
if (addr.target)
free(addr.target);
if (addr.remainder)
free(addr.remainder);
if (addr.comment)
free(addr.comment);
}
parsedaddr parserfcaddr(char *s)
{
parsedaddr result;
char *inbrackets = NULL, *outbrackets = NULL, *cleanbuf = NULL, *combuf = NULL;
char *t, *r, *c, *p, *q, **x;
int quotes, brackets, escaped, anglecomplete;
char *firstat, *lastat, *percent, *colon, *comma, *exclam;
result.target = NULL;
result.remainder = NULL;
result.comment = NULL;
addrerror = 0;
if ((s == NULL) || (*s == '\0'))
return result;
/*
* First check if there is an "angled" portion
*/
inbrackets = calloc(strlen(s)+1, sizeof(char));
outbrackets = calloc(strlen(s)+1, sizeof(char));
brackets = quotes = escaped = anglecomplete = 0;
for (p = s,q = inbrackets, r = outbrackets, x = &r; *p; p++) {
if (escaped)
escaped = FALSE;
else /* process all special chars */
switch (*p) {
case '\\': escaped = TRUE; break;
case '\"': quotes = !quotes; break;
case '<': if (quotes)
break;
if (brackets)
addrerror |= ADDR_NESTED;
if (anglecomplete)
addrerror |= ADDR_MULTIPLE;
brackets++;
x = &q;
break;
case '>': if (quotes)
break;
if (brackets)
brackets--;
else
addrerror |= ADDR_UNMATCHED;
if (!brackets)
anglecomplete = 1;
break;
}
*((*x)++) = *p;
if (!brackets)
x = &r;
}
*q = '\0';
*r = '\0';
if (brackets || quotes)
addrerror |= ADDR_UNMATCHED;
if (addrerror)
goto leave1;
cleanbuf = calloc(strlen(s)+1, sizeof(char));
combuf = calloc(strlen(s)+1, sizeof(char));
if (*inbrackets) { /* there actually is an angled portion */
strcpy(combuf, outbrackets);
c = combuf + strlen(combuf);
p = inbrackets + 1;
*(p+strlen(p)-1) = '\0';
} else {
c = combuf;
p = outbrackets;
}
/* OK, now we have result.comment filled with wat was outside
angle brackets, c pointing past the end of it,
p pointing to what is supposed to be address, with angle
brackets already removed */
quotes = brackets = escaped = 0;
for (r = cleanbuf, x = &r; *p; p++) {
if (escaped) {
escaped=0;
*((*x)++)=*p;
} else /* process all special chars */
if (isspace(*p)) {
if ((quotes) || (brackets))
*((*x)++) = *p;
} else
switch (*p) {
case '\\': escaped=1;
/* pass backslash itself only inside quotes
and comments, or for the special cases
\" and \\ otherwise eat it away */
if ((quotes) || (brackets))
*((*x)++) = *p;
else if ((*(p+1)=='"') || (*(p+1)=='\\'))
*((*x)++) = *p;
break;
case '\"': quotes = !quotes;
*((*x)++) = *p;
break;
case '(':
brackets++;
x = &c;
break;
case ')':
if (brackets)
brackets--;
else
addrerror |= ADDR_UNMATCHED;
if (!brackets)
x = &r;
break;
default:
*((*x)++) = *p;
break;
}
}
*r = '\0';
*c = '\0';
if (brackets || quotes)
addrerror |= ADDR_UNMATCHED;
if (addrerror)
goto leave2;
/* OK, now we have inangles buffer filled with the 'clean' address,
all comments removed, and result.comment is ready filled */
/* seach for special chars that are outside quotes */
firstat = lastat = percent = colon = comma = exclam = NULL;
quotes = 0; escaped = 0;
for (p = cleanbuf; *p; p++)
if (*p == '\\')
p++;
else if (*p == '\"')
quotes = !quotes;
else if (!quotes)
switch (*p) {
case '@':
if (!firstat)
firstat = p;
lastat = p;
break;
case '%':
percent = p;
break;
case ':':
colon = p;
break;
case ',':
comma = p;
break;
case '!':
if (!exclam)
exclam = p;
break;
}
if ((firstat == cleanbuf) && colon) {
if (comma && (comma < colon)) {
*comma = '\0';
r = comma + 1;
} else {
*colon = '\0';
r = colon + 1;
}
t = firstat + 1;
} else if (lastat) {
*lastat = '\0';
r = cleanbuf;
t = lastat + 1;
} else if (exclam) {
*exclam = '\0';
r = exclam + 1;
t = cleanbuf;
} else if (percent) {
*percent = '\0';
r = cleanbuf;
t = percent + 1;
} else {
/* unquote it if necessary */
if ((*cleanbuf == '\"') && (*(p = (cleanbuf+strlen(cleanbuf)-1)) == '\"')) {
*p = '\0';
r = cleanbuf + 1;
} else
r = cleanbuf;
t = NULL;
}
if (t && (*t != '\0'))
result.target = xstrcpy(t);
if (r && (*r != '\0'))
result.remainder = xstrcpy(r);
if (*combuf != '\0')
result.comment = xstrcpy(combuf);
leave1: /* this is also normal exit */
free(cleanbuf);
free(combuf);
free(inbrackets);
free(outbrackets);
return result;
leave2: /* if error found on second stage, free */
free(cleanbuf);
free(combuf);
return result;
}

189
lib/rfcdate.c Normal file
View File

@@ -0,0 +1,189 @@
/*****************************************************************************
*
* $Id: rfcdate.c,v 1.9 2005/10/11 20:49:46 mbse Exp $
* Purpose ...............: Date utilities
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
static char *wdays[]={(char *)"Sun",(char *)"Mon",(char *)"Tue",(char *)"Wed",
(char *)"Thu",(char *)"Fri",(char *)"Sat"};
static char *months[]={(char *)"Jan",(char *)"Feb",(char *)"Mar",
(char *)"Apr",(char *)"May",(char *)"Jun",
(char *)"Jul",(char *)"Aug",(char *)"Sep",
(char *)"Oct",(char *)"Nov",(char *)"Dec"};
time_t parsefdate(char *str, void *now)
{
struct tm tm, *pnow;
int i, rc;
time_t Now;
char *dummy, *pday, *pmon, *pyear, *phour, *pminute, *psecond;
char *buf;
Now = time(NULL);
pnow = localtime(&Now);
dummy = pday = pmon = pyear = phour = pminute = psecond = NULL;
if (str == NULL) {
WriteError("parsefdate entered NULL");
return (time_t)0;
}
buf = xstrcpy(str);
rc = 1;
memset(&tm, 0, sizeof(tm));
if ((strncasecmp(str,"Sun ",4) == 0) ||
(strncasecmp(str,"Mon ",4) == 0) ||
(strncasecmp(str,"Tue ",4) == 0) ||
(strncasecmp(str,"Wed ",4) == 0) ||
(strncasecmp(str,"Thu ",4) == 0) ||
(strncasecmp(str,"Fri ",4) == 0) ||
(strncasecmp(str,"Sat ",4) == 0)) {
/*
* SEAdog mode
*/
if ((dummy = strtok(str, " ")) != NULL)
if ((pday = strtok(NULL, " ")) != NULL)
if ((pmon = strtok(NULL, " ")) != NULL)
if ((pyear = strtok(NULL, " ")) != NULL)
if ((phour = strtok(NULL, ": ")) != NULL)
if ((pminute = strtok(NULL, ": ")) != NULL)
rc = 0;
psecond = xstrcpy((char *)"00");
} else {
/*
* FTS-0001 Standard mode
*/
if ((pday = strtok(str, " ")) != NULL)
if ((pmon = strtok(NULL, " ")) != NULL)
if ((pyear = strtok(NULL, " ")) != NULL)
if ((phour = strtok(NULL, ": ")) != NULL)
if ((pminute = strtok(NULL, ": ")) != NULL)
if ((psecond = strtok(NULL, ": ")) != NULL)
rc = 0;
}
if (rc == 1) {
WriteError("Could not parse date \"%s\"", str);
return (time_t)0;
}
tm.tm_sec = atoi(psecond);
tm.tm_min = atoi(pminute);
tm.tm_hour = atoi(phour);
tm.tm_mday = atoi(pday);
tm.tm_isdst = pnow->tm_isdst;
for (i = 0; i < 12; i++)
if (strncasecmp(months[i], pmon, 3) == 0)
break;
tm.tm_mon = i;
tm.tm_year = atoi(pyear);
if (tm.tm_year < 0) {
rc = 1;
} else if (tm.tm_year < 100) { /* Correct date field */
while (pnow->tm_year - tm.tm_year > 50) {
tm.tm_year +=100; /* Sliding window adaption */
}
} else if (tm.tm_year < 1900) { /* Field contains year like */
rc = 2; /* Timed/Netmgr bug */
} else {
tm.tm_year -= 1900; /* 4 Digit year field */
rc = 2;
}
/*
* Log if something isn't right
*/
if (rc)
Syslog('+', "fdate \"%s\" to %02d-%02d-%d %02d:%02d:%02d rc=%d", buf,
tm.tm_mday, tm.tm_mon+1, tm.tm_year+1900,
tm.tm_hour, tm.tm_min, tm.tm_sec, rc);
free(buf);
return mktime(&tm) - (gmt_offset((time_t)0) * 60);
}
char *rfcdate(time_t now)
{
static char buf[40];
struct tm ptm, gtm;
char sign;
int hr, min;
int offset;
if (!now)
now = time(NULL);
ptm = *localtime(&now);
/*
* To get the timezone, compare localtime with GMT.
*/
gtm = *gmtime(&now);
/*
* Assume we are never more than 24 hours away.
*/
offset = gtm.tm_yday - ptm.tm_yday;
if (offset > 1)
offset = -24;
else if (offset < -1)
offset = 24;
else
offset *= 24;
/*
* Scale in the hours and minutes; ignore seconds.
*/
offset += gtm.tm_hour - ptm.tm_hour;
offset *= 60;
offset += gtm.tm_min - ptm.tm_min;
if (offset <= 0) {
sign = '+';
offset = -offset;
} else
sign = '-';
hr = offset / 60L;
min = offset % 60L;
snprintf(buf, 40, "%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d", wdays[ptm.tm_wday], ptm.tm_mday, months[ptm.tm_mon],
ptm.tm_year + 1900, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, sign, hr, min);
return(buf);
}

141
lib/rfcmsg.c Normal file
View File

@@ -0,0 +1,141 @@
/*****************************************************************************
*
* $Id: rfcmsg.c,v 1.14 2007/03/03 14:28:41 mbse Exp $
* Purpose ...............: RFC msg
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
#ifndef BUFSIZ
#define BUFSIZ 512
#endif
#define KWDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."
/*
* Parse RFC message, extract headers and do some sanity checks.
*/
rfcmsg *parsrfc(FILE *fp)
{
int linecont=FALSE,newcont,firstline;
rfcmsg *start=NULL, *cur=NULL;
char buffer[BUFSIZ], *p;
while (bgets(buffer, BUFSIZ-1, fp) && strcmp(buffer,"\n")) {
newcont = (buffer[strlen(buffer)-1] != '\n');
if (linecont) {
cur->val=xstrcat(cur->val,buffer);
} else {
if (isspace(buffer[0])) {
if (strspn(buffer," \t\n") == strlen(buffer)) {
break;
}
if (!cur) {
cur = (rfcmsg *)malloc(sizeof(rfcmsg));
start = cur;
cur->next = NULL;
cur->key = xstrcpy((char *)"X-Body-Start");
cur->val = xstrcpy(buffer);
break;
} else
cur->val = xstrcat(cur->val,buffer);
} else {
if (cur) {
firstline=FALSE;
(cur->next) = (rfcmsg *)malloc(sizeof(rfcmsg));
cur = cur->next;
} else {
firstline = TRUE;
cur = (rfcmsg *)malloc(sizeof(rfcmsg));
start = cur;
}
cur->next = NULL;
cur->key = NULL;
cur->val = NULL;
if (firstline && !strncmp(buffer,"From ",5)) {
cur->key=xstrcpy((char *)"X-UUCP-From");
cur->val=xstrcpy(buffer+4);
} else if ((p=strchr(buffer,':')) && (p > buffer) && /* ':' isn't 1st chr */
isspace(*(p+1)) && /* space past ':' */
/* at least one non blank char */
(strspn(p+2, " \t\n") < strlen(p+2)) && (strspn(buffer,KWDCHARS) == (p-buffer))) {
*p='\0';
cur->key = xstrcpy(buffer);
cur->val = xstrcpy(p+1);
} else if ((p=strchr(buffer,':')) && (!strncasecmp(buffer, (char *)"X-MS-", 5))) {
/*
* It looks like M$ invented their own internet standard, these
* are header lines without a key. This one will be stored here
* and junked in the rfc2ftn function.
*/
cur->key = xstrcpy(buffer);
cur->val = xstrcpy((char *)" ");
} else if ((p=strchr(buffer,':')) && (p > buffer)) {
/*
* Header line without information, don't add this one but log.
*/
Syslog('!', "Header line \"%s\" without key value", buffer);
cur->key = xstrcpy(buffer);
cur->val = xstrcpy((char *)" ");
} else if ((p=strchr(buffer,':')) && (p > buffer) && isspace(*(p+1))) { /* space past ':' */
Syslog('!', "Header line \"%s\" without key value (but with a Space)", buffer);
cur->key = xstrcpy(buffer);
cur->val = xstrcpy((char *)" ");
} else {
cur->key = xstrcpy((char *)"X-Body-Start");
cur->val = xstrcpy(buffer);
break;
}
}
}
linecont = newcont;
}
return(start);
}
void tidyrfc(rfcmsg *msg)
{
rfcmsg *nxt;
for (; msg; msg=nxt) {
nxt = msg->next;
if (msg->key)
free(msg->key);
if (msg->val)
free(msg->val);
free(msg);
}
return;
}

72
lib/sectest.c Normal file
View File

@@ -0,0 +1,72 @@
/*****************************************************************************
*
* $Id: sectest.c,v 1.5 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: Security flags access test
*
*****************************************************************************
* 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 "mbselib.h"
/*
* Security Access Check
*/
int Access(securityrec us, securityrec ref)
{
if (us.level < ref.level)
return FALSE;
if ((ref.notflags & ~us.flags) != ref.notflags)
return FALSE;
if ((ref.flags & us.flags) != ref.flags)
return FALSE;
return TRUE;
}
/*
* The same test, for menus which are written in machine endian independant way.
* The second parameter MUST be the menu parameter.
*/
int Le_Access(securityrec us, securityrec ref)
{
if (us.level < le_int(ref.level))
return FALSE;
if ((ref.notflags & ~us.flags) != ref.notflags)
return FALSE;
if ((ref.flags & us.flags) != ref.flags)
return FALSE;
return TRUE;
}

70
lib/semafore.c Normal file
View File

@@ -0,0 +1,70 @@
/*****************************************************************************
*
* $Id: semafore.c,v 1.7 2005/08/28 13:34:43 mbse Exp $
* Purpose ...............: Create, test and remove semafore's
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
void CreateSema(char *sem)
{
char temp[40];
snprintf(temp, 40, "%s", SockR("SECR:1,%s;", sem));
if (strncmp(temp, "200", 3) == 0)
WriteError("Can't create semafore %s", sem);
}
void RemoveSema(char *sem)
{
char temp[40];
snprintf(temp, 40, "%s", SockR("SERM:1,%s;", sem));
if (strncmp(temp, "200", 3) == 0)
WriteError("Can't remove semafore %s", sem);
}
int IsSema(char *sem)
{
char temp[40];
snprintf(temp, 40, "%s", SockR("SEST:1,%s;", sem));
if (strncmp(temp, "200", 3) == 0) {
WriteError("Can't read semafore %s", sem);
return FALSE;
}
strtok(temp, ",");
return atoi(strtok(NULL, ";"));
}

90
lib/signame.c Normal file
View File

@@ -0,0 +1,90 @@
/*****************************************************************************
*
* $Id: signame.c,v 1.9 2007/08/22 21:09:24 mbse Exp $
* Purpose ...............: Signal names
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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 "mbselib.h"
/*
* Signal handler signal names.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
char SigName[32][16] = { "NOSIGNAL",
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL",
"SIGTRAP", "SIGIOT", "SIGBUS", "SIGFPE",
"SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2",
"SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT",
"SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP",
"SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU",
"SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH",
"SIGIO", "SIGPWR", "SIGUNUSED"};
#elif defined(__PPC__) || defined(__ppc__)
char SigName[32][16] = { "NOSIGNAL",
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL",
"SIGTRAP", "SIGIOT", "SIGBUS", "SIGFPE",
"SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2",
"SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT",
"SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP",
"SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU",
"SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH",
"SIGIO", "SIGPWR", "SIGUNUSED"};
#elif defined(__sparc__)
char SigName[32][16] = { "NOSIGNAL",
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL",
"SIGTRAP", "SIGIOT", "SIGEMT", "SIGFPE",
"SIGKILL", "SIGBUS", "SIGSEGV", "SIGSYS",
"SIGPIPE", "SIGALRM", "SIGTERM", "SIGURG",
"SIGSTOP", "SIGTSTP", "SIGCONT", "SIGCHLD",
"SIGTTIN", "SIGTTOU", "SIGIO", "SIGXCPU",
"SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH",
"SIGLOST", "SIGUSR1", "SIGUSR2"};
#elif defined(__alpha__) || defined(__hppa__)
char SigName[32][16] = { "NOSIGNAL",
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL",
"SIGTRAP", "SIGABRT", "SIGEMT", "SIGFPE",
"SIGKILL", "SIGBUS", "SIGSEGV", "SIGSYS",
"SIGPIPE", "SIGALRM", "SIGTERM", "SIGURG",
"SIGSTOP", "SIGTSTP", "SIGCONT", "SIGCHLD",
"SIGTTIN", "SIGTTOU", "SIGIO", "SIGXCPU",
"SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH",
"SIGINFO", "SIGUSR1", "SIGUSR2"};
#else
#error "Can't make signal names on this platform"
#endif

210
lib/smtp.c Normal file
View File

@@ -0,0 +1,210 @@
/*****************************************************************************
*
* $Id: smtp.c,v 1.10 2007/08/25 15:29:14 mbse Exp $
* Purpose ...............: MBSE BBS Internet Library
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
#include "mbinet.h"
static int smtpsock = -1; /* TCP/IP socket */
struct hostent *shp; /* Host info remote */
struct servent *ssp; /* Service information */
struct sockaddr_in smtp_loc; /* For local socket address */
struct sockaddr_in smtp_rem; /* For remote socket address */
int smtp_connect(void)
{
socklen_t addrlen;
char *p, temp[40];
if (smtpsock != -1)
return smtpsock;
if (!strlen(CFG.smtpnode)) {
WriteError("SMTP: host not configured");
return -1;
}
Syslog('+', "SMTP: connecting host: %s", CFG.smtpnode);
memset(&smtp_loc, 0, sizeof(struct sockaddr_in));
memset(&smtp_rem, 0, sizeof(struct sockaddr_in));
smtp_rem.sin_family = AF_INET;
if ((shp = gethostbyname(CFG.smtpnode)) == NULL) {
WriteError("SMTP: can't find host %s", CFG.smtpnode);
return -1;
}
smtp_rem.sin_addr.s_addr = ((struct in_addr *)(shp->h_addr))->s_addr;
if ((ssp = getservbyname("smtp", "tcp")) == NULL) {
WriteError("SMTP: can't find service port for smtp/tcp");
return -1;
}
smtp_rem.sin_port = ssp->s_port;
if ((smtpsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
WriteError("$SMTP: unable to create tcp socket");
return -1;
}
if (connect(smtpsock, (struct sockaddr *)&smtp_rem, sizeof(struct sockaddr_in)) == -1) {
WriteError("$SMTP: can't connect tcp socket");
return -1;
}
addrlen = sizeof(struct sockaddr_in);
if (getsockname(smtpsock, (struct sockaddr *)&smtp_loc, &addrlen) == -1) {
WriteError("$SMTP: unable to read socket address");
return -1;
}
p = smtp_receive();
if (strlen(p) == 0) {
WriteError("SMTP: no response");
smtp_close();
return -1;
}
if (strncmp(p, "220", 3)) {
WriteError("SMTP: bad response: %s", p);
smtp_close();
return -1;
}
Syslog('+', "SMTP: %s", p);
snprintf(temp, 40, "HELO %s\r\n", CFG.sysdomain);
if (smtp_cmd(temp, 250)) {
smtp_close();
return -1;
}
return smtpsock;
}
int smtp_send(char *buf)
{
if (smtpsock == -1)
return -1;
if (send(smtpsock, buf, strlen(buf), 0) != strlen(buf)) {
WriteError("$SMTP: socket send failed");
return -1;
}
return 0;
}
/*
* Return empty buffer if something went wrong, else the complete
* dataline is returned
*/
char *smtp_receive(void)
{
static char buf[SS_BUFSIZE];
int i, j;
memset((char *)&buf, 0, SS_BUFSIZE);
i = 0;
while ((strchr(buf, '\n')) == NULL) {
j = recv(smtpsock, &buf[i], SS_BUFSIZE-i, 0);
if (j == -1) {
WriteError("$SMTP: error reading socket");
memset((char *)&buf, 0, SS_BUFSIZE);
return buf;
}
i += j;
}
for (i = 0; i < strlen(buf); i++) {
if (buf[i] == '\n')
buf[i] = '\0';
if (buf[i] == '\r')
buf[i] = '\0';
}
return buf;
}
int smtp_close(void)
{
if (smtpsock == -1)
return 0;
smtp_cmd((char *)"QUIT\r\n", 221);
if (shutdown(smtpsock, 1) == -1) {
WriteError("$SMTP: can't close socket");
return -1;
}
smtpsock = -1;
Syslog('+', "SMTP: closed");
return 0;
}
/*
* Send command to the SMTP service. On error return the
* received error number, else return zero.
*/
int smtp_cmd(char *cmd, int resp)
{
char *p, rsp[6];
if (smtp_send(cmd) == -1)
return -1;
snprintf(rsp, 6, "%d", resp);
p = smtp_receive();
if (strncmp(p, rsp, strlen(rsp))) {
WriteError("SMTP> %s", cmd);
WriteError("SMTP< %s", p);
memset(&resp, 0, sizeof(rsp));
strncpy(rsp, p, 3);
return atoi(rsp);
}
return 0;
}

26
lib/strcasestr.c Normal file
View File

@@ -0,0 +1,26 @@
#include "../config.h"
#include "mbselib.h"
#ifndef HAVE_STRCASESTR
char *strcasestr(char *a, char *b)
{
char *p,*max;
int l;
if (a && b) {
l=strlen(b);
max=a+strlen(a)-l;
for (p=a;p<=max;p++)
if (!strncasecmp(p,b,l)) return(p);
return((char *)0);
}
else {
return ((char *) 0);
}
}
#endif

417
lib/strutil.c Normal file
View File

@@ -0,0 +1,417 @@
/*****************************************************************************
*
* $Id: strutil.c,v 1.16 2007/08/22 21:09:24 mbse Exp $
* Purpose ...............: Common string functions
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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.
*
* MB 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 MB 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 "mbselib.h"
char *padleft(char *str, int size, char pad)
{
static char stri[256];
static char temp[256];
strcpy(stri, str);
memset(temp, pad, (size_t)size);
temp[size] = '\0';
if (strlen(stri) <= size)
memmove(temp, stri, (size_t)strlen(stri));
else
memmove(temp, stri, (size_t)size);
return temp;
}
/*
* Small function to convert String to LowerCase
*/
char *tl(char *str)
{
char *p = str;
while (*p != '\0') {
*p = (char)tolower(*p);
p++;
}
return str;
}
void Striplf(char *String)
{
int i;
for(i = 0; i < strlen(String); i++) {
if(*(String + i) == '\0')
break;
if(*(String + i) == '\n')
*(String + i) = '\0';
}
}
void mbse_CleanSubject(char *String)
{
int i, fixed = FALSE;
i = strlen(String) -1;
while ((isspace(String[i])) && i) {
String[i] = '\0';
i--;
fixed = TRUE;
}
if ((strncasecmp(String, "Re: ", 4) == 0) && (strncmp(String, "Re: ", 4))) {
/*
* Fix Re:
*/
String[0] = 'R';
String[1] = 'e';
String[2] = ':';
String[3] = ' ';
fixed = TRUE;
}
if (fixed)
Syslog('m', "Fixed subj: \"%s\"", printable(String, 0));
}
/*
* Converts first letter to UpperCase
*/
void tlf(char *str)
{
*(str) = toupper(*(str));
}
/*
* Small function to convert String to UpperCase
*/
char *tu(char *str)
{
char *p = str;
while (*p != '\0') {
*p = (char)toupper(*p);
p++;
}
return str;
}
/*
* Converts the first letter in every word in a string to uppercase,
* all other character will be lowercase. Will handle the notation
* Bob Ten.Dolle as well
*/
char *tlcap(char *String)
{
static char stri[256];
int Loop, Strlen;
strcpy(stri, String);
Strlen = strlen(stri);
/*
* Automatic do the first character
*/
stri[0] = toupper(stri[0]);
for(Loop = 1; Loop < Strlen; Loop++) {
stri[Loop] = tolower(stri[Loop]);
if (( stri[Loop] == ' ') || (stri[Loop] == '.')) {
/*
* This is a space charracter, increase the counter
* and convert the next character to uppercase.
*/
Loop++;
stri[Loop] = toupper(stri[Loop]);
}
}
return stri;
}
/*
* Hilite "Word" in string, this is done by inserting ANSI
* Hilite characters in the string.
*/
char *Hilite(char *str, char *Word)
{
char *pos;
char *new;
char *old;
int t;
new = strdup(str);
old = strdup(str);
tl(new);
if ((pos = strstr(new,Word)) == NULL)
return(str);
str = realloc(str,strlen(new)+200);
strcpy(str,"\0");
while (( pos = strstr(new,Word)) != NULL) {
*pos = '\0';
t = strlen(new);
strncat(str,old,t);
strcat(str,"");
old+=t;
strncat(str,old,strlen(Word));
strcat(str,"");
old+=strlen(Word);
new = new+t+strlen(Word);
}
strcat(str,old);
return(str);
}
/*
* Replace spaces is a string with underscore characters.
*/
void Addunderscore(char *temp)
{
int i;
for(i = 0; i < strlen(temp); i++) {
if (*(temp + i) == '\0')
break;
if (*(temp + i) == ' ')
*(temp + i) = '_';
}
}
/*
* Find & Replace string in a string
*/
void strreplace(char *sStr, char *sFind, char *sReplace)
{
char sNewstr[81]="";
char *posStr, *posFind;
int iPos, iLen, iCounter;
posStr=sStr;
if(( posFind = strstr(sStr, sFind)) != NULL) {
iPos = (int)(posFind - posStr);
strncpy(sNewstr, sStr, iPos);
strcat(sNewstr, sReplace);
iPos+= strlen(sFind);
iLen = strlen(sNewstr);
for (iCounter=0; iCounter < (strlen(sStr) - iPos); iCounter++)
sNewstr[iCounter + iLen] = sStr[iCounter + iPos];
sNewstr[iCounter+1+iLen] = '\0';
strcpy(sStr, sNewstr);
}
}
/*
* Converts to HH:MM
*/
char *StrTimeHM(time_t date)
{
static char ttime[6];
struct tm *l_d;
l_d = localtime(&date);
snprintf(ttime, 6, "%02d:%02d", l_d->tm_hour, l_d->tm_min);
return ttime;
}
/*
* Returns HH:MM:SS
*/
char *StrTimeHMS(time_t date)
{
static char ttime[9];
struct tm *l_d;
l_d = localtime(&date);
snprintf(ttime, 9, "%02d:%02d:%02d", l_d->tm_hour, l_d->tm_min, l_d->tm_sec);
return ttime;
}
/*
* Get the current local time, returns HH:MM
*/
char *GetLocalHM()
{
static char gettime[15];
time_t T_Now;
T_Now = time(NULL);
snprintf(gettime, 15, "%s", StrTimeHM(T_Now));
return(gettime);
}
/*
* Get the current local time, returns HH:MM:SS
*/
char *GetLocalHMS()
{
static char gettime[15];
time_t T_Now;
T_Now = time(NULL);
snprintf(gettime, 15, "%s", StrTimeHMS(T_Now));
return(gettime);
}
/*
* Returns date as MM-DD-YYYY
*/
char *StrDateMDY(time_t *Clock)
{
struct tm *tm;
static char cdate[12];
tm = localtime(Clock);
snprintf(cdate, 12, "%02d-%02d-%04d", tm->tm_mon+1, tm->tm_mday, tm->tm_year+1900);
return(cdate);
}
/*
* Returns DD-MM-YYYY
*/
char *StrDateDMY(time_t date)
{
static char tdate[15];
struct tm *l_d;
l_d = localtime(&date);
snprintf(tdate, 15, "%02d-%02d-%04d", l_d->tm_mday, l_d->tm_mon+1, l_d->tm_year+1900);
return tdate;
}
/*
* This function returns the date for today, to test against other functions
* DD-MM-YYYY (DAY-MONTH-YEAR)
*/
char *GetDateDMY()
{
static char tdate[15];
struct tm *l_d;
time_t T_Now;
T_Now = time(NULL);
l_d = localtime(&T_Now);
snprintf(tdate, 15, "%02d-%02d-%04d", l_d->tm_mday,l_d->tm_mon+1,l_d->tm_year+1900);
return(tdate);
}
char *OsName()
{
#ifdef __linux__
return (char *)"GNU/Linux";
#elif __FreeBSD__
return (char *)"FreeBSD";
#elif __NetBSD__
return (char *)"NetBSD";
#elif __OpenBSD__
return (char *)"OpenBSD";
#else
#error "Unknown target OS"
#endif
}
char *OsCPU()
{
#ifdef __i386__
return (char *)"i386";
#elif __x86_64__
return (char *)"x86_64";
#elif __PPC__
return (char *)"PPC";
#elif __sparc__
return (char *)"Sparc";
#elif __alpha__
return (char *)"Alpha";
#elif __hppa__
return (char *)"HPPA";
#elif __arm__
return (char *)"ARM";
#else
#error "Unknown CPU"
#endif
}
/*
* Return universal tearline, note if OS and CPU are
* unknown, the tearline is already 39 characters.
*/
char *TearLine()
{
static char tearline[41];
snprintf(tearline, 41, "--- MBSE BBS v%s (%s-%s)", VERSION, OsName(), OsCPU());
return tearline;
}

153
lib/term.c Normal file
View File

@@ -0,0 +1,153 @@
/*****************************************************************************
*
* $Id: term.c,v 1.13 2005/08/28 13:34:43 mbse Exp $
* Purpose ...............: Terminal output routines.
*
*****************************************************************************
* 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 "mbselib.h"
#include "users.h"
int termmode; /* 0 = tty, 1 = ANSI */
int termx = 80;
int termy = 24;
void mbse_TermInit(int mode, int x, int y)
{
termmode = mode;
termx = x;
termy = y;
}
/*
* Changes ansi background and foreground color
*/
void mbse_colour(int fg, int bg)
{
if (termmode == 1) {
int att=0, fore=37, back=40;
if (fg<0 || fg>31 || bg<0 || bg>7) {
fprintf(stdout, "ANSI: Illegal colour specified: %i, %i\n", fg, bg);
fflush(stdout);
return;
}
fprintf(stdout, "[");
if ( fg > WHITE) {
fprintf(stdout, "5;");
fg-= 16;
}
if (fg > LIGHTGRAY) {
att=1;
fg=fg-8;
}
if (fg == BLACK) fore=30;
else if (fg == BLUE) fore=34;
else if (fg == GREEN) fore=32;
else if (fg == CYAN) fore=36;
else if (fg == RED) fore=31;
else if (fg == MAGENTA) fore=35;
else if (fg == BROWN) fore=33;
else fore=37;
if (bg == BLUE) back=44;
else if (bg == GREEN) back=42;
else if (bg == CYAN) back=46;
else if (bg == RED) back=41;
else if (bg == MAGENTA) back=45;
else if (bg == BROWN) back=43;
else if (bg == LIGHTGRAY) back=47;
else back=40;
fprintf(stdout, "%d;%d;%dm", att, fore, back);
fflush(stdout);
}
}
void mbse_clear()
{
if (termmode == 1) {
mbse_colour(LIGHTGRAY, BLACK);
fprintf(stdout, ANSI_HOME);
fprintf(stdout, ANSI_CLEAR);
} else {
fprintf(stdout, "\n");
}
fflush(stdout);
}
/*
* Moves cursor to specified position
*/
void mbse_locate(int y, int x)
{
if (termmode > 0) {
if (y > termy || x > termx) {
fprintf(stdout, "ANSI: Invalid screen coordinates: %i, %i\n", y, x);
fflush(stdout);
return;
}
fprintf(stdout, "\x1B[%i;%iH", y, x);
fflush(stdout);
}
}
/*
* curses compatible functions
*/
void mbse_mvprintw(int y, int x, const char *format, ...)
{
char *outputstr;
va_list va_ptr;
outputstr = calloc(2048, sizeof(char));
va_start(va_ptr, format);
vsnprintf(outputstr, 2048, format, va_ptr);
va_end(va_ptr);
mbse_locate(y, x);
fprintf(stdout, outputstr);
free(outputstr);
fflush(stdout);
}

163
lib/timers.c Normal file
View File

@@ -0,0 +1,163 @@
/*****************************************************************************
*
* $Id: timers.c,v 1.3 2004/02/21 14:24:04 mbroek Exp $
* Purpose ...............: General Purpose Timers
*
*****************************************************************************
* 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 "mbselib.h"
/*
* Number of timers
*/
#define GENTIMERS 3
static time_t gentimer[GENTIMERS];
/*
* Reset a timer
*/
int gpt_resettimer(int tno)
{
if (tno >= GENTIMERS) {
errno = EINVAL;
WriteError("invalid timer number for gpt_resettimer(%d)", tno);
return -1;
}
gentimer[tno] = (time_t) 0;
return 0;
}
void gpt_resettimers(void)
{
int i;
for (i = 0; i < GENTIMERS; i++)
gpt_resettimer(i);
}
/*
* Set timer
*/
int gpt_settimer(int tno, int interval)
{
if (tno >= GENTIMERS) {
errno = EINVAL;
WriteError("invalid timer number for gpt_settimer(%d)", tno);
return -1;
}
gentimer[tno] = time((time_t*)NULL) + interval;
return 0;
}
/*
* Check if timer is expired
*/
int gpt_expired(int tno)
{
time_t now;
if (tno >= GENTIMERS) {
errno = EINVAL;
WriteError("invalid timer number for gpt_expired(%d)", tno);
return -1;
}
/*
* Check if timer is running
*/
if (gentimer[tno] == (time_t) 0)
return 0;
now = time(NULL);
return (now >= gentimer[tno]);
}
int gpt_running(int tno)
{
if (tno >= GENTIMERS) {
errno = EINVAL;
WriteError("invalid timer number for gpt_running(%d)", tno);
return -1;
}
if (gentimer[tno] == (time_t) 0)
return 0;
else
return 1;
}
/*
* Milliseconds timer, returns 0 on success.
*/
int msleep(int msecs)
{
int rc;
struct timespec req, rem;
rem.tv_sec = 0;
rem.tv_nsec = 0;
req.tv_sec = msecs / 1000;
req.tv_nsec = (msecs % 1000) * 1000000;
while (TRUE) {
rc = nanosleep(&req, &rem);
if (rc == 0)
break;
if ((errno == EINVAL) || (errno == EFAULT)) {
WriteError("$msleep(%d)", msecs);
break;
}
/*
* Error was EINTR, run timer again to complete.
*/
req.tv_sec = rem.tv_sec;
req.tv_nsec = rem.tv_nsec;
rem.tv_sec = 0;
rem.tv_nsec = 0;
}
return rc;
}

87
lib/tmpwork.c Normal file
View File

@@ -0,0 +1,87 @@
/*****************************************************************************
*
* $Id: tmpwork.c,v 1.3 2005/12/04 11:46:07 mbse Exp $
* Purpose ...............: temp workdirectory
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
static int is_tmpwork = FALSE;
void clean_tmpwork(void)
{
char *buf, *temp, *arc;
if (is_tmpwork) {
buf = calloc(PATH_MAX, sizeof(char));
temp = calloc(PATH_MAX, sizeof(char));
arc = calloc(PATH_MAX, sizeof(char));
getcwd(buf, PATH_MAX);
snprintf(temp, PATH_MAX, "%s/tmp", getenv("MBSE_ROOT"));
snprintf(arc, PATH_MAX, "-r -f arc%d", (int)getpid());
if (chdir(temp) == 0) {
Syslog('f', "clean_tmpwork %s/arc%d", temp, (int)getpid());
execute_pth((char *)"rm", arc, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null");
} else {
WriteError("$Can't chdir to %s", temp);
}
chdir(buf);
free(temp);
free(buf);
free(arc);
is_tmpwork = FALSE;
}
}
int create_tmpwork(void)
{
char *temp;
int rc = 0;
if (! is_tmpwork) {
temp = calloc(PATH_MAX, sizeof(char));
snprintf(temp, PATH_MAX, "%s/tmp/arc%d/foobar", getenv("MBSE_ROOT"), (int)getpid());
if (! mkdirs(temp, 0755))
rc = 1;
else
is_tmpwork = TRUE;
Syslog('f', "create_tmpwork %s rc=%d", temp, rc);
free(temp);
}
return rc;
}

115
lib/unpacker.c Normal file
View File

@@ -0,0 +1,115 @@
/*****************************************************************************
*
* $Id: unpacker.c,v 1.13 2005/08/27 18:53:33 mbse Exp $
* Purpose ...............: Archive unpacker
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* 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 "mbselib.h"
char *unpacker(char *fn)
{
FILE *fp;
unsigned char buf[8];
if ((fp = fopen(fn,"r")) == NULL) {
WriteError("$Could not open file %s", fn);
return NULL;
}
if (fread(buf,1,sizeof(buf),fp) != sizeof(buf)) {
WriteError("$Could not read head of the file %s", fn);
fclose(fp);
return NULL;
}
fclose(fp);
if (memcmp(buf,"PK\003\004",4) == 0) return (char *)"ZIP";
if (*buf == 0x1a) return (char *)"ARC";
if (memcmp(buf+2,"-l",2) == 0) return (char *)"LHA";
if (memcmp(buf,"ZOO",3) == 0) return (char *)"ZOO";
if (memcmp(buf,"`\352",2) == 0) return (char *)"ARJ";
if (memcmp(buf,"Rar!",4) == 0) return (char *)"RAR";
if (memcmp(buf,"HA",2) == 0) return (char *)"HA";
if (memcmp(buf,"UC2\0x1a",4) == 0) return (char *)"UC2";
if (memcmp(buf,"BZ",2) == 0) return (char *)"BZIP";
if (memcmp(buf,"MSCF",4) == 0) return (char *)"CAB"; /* M$ CAB files */
if (memcmp(buf,"\037\213",2) == 0) return (char *)"GZIP"; /* gzip compressed data */
if (memcmp(buf,"\037\235",2) == 0) return (char *)"CMP"; /* unix compressed data */
if ((fp = fopen(fn,"r"))) {
fseek(fp, 257, SEEK_SET);
if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) {
/*
* Here we don't complain about a read error, the file may be
* smaller then 257 bytes so it is not a tar file anyway.
*/
fclose(fp);
return NULL;
}
fclose(fp);
}
if (memcmp(buf,"ustar",5) == 0) return (char *)"TAR"; /* GNU/Posix tar */
return NULL;
}
int getarchiver(char *unarc)
{
FILE *fp;
char *filename;
memset(&archiver, 0, sizeof(archiver));
filename = calloc(PATH_MAX, sizeof(char));
snprintf(filename, PATH_MAX -1, "%s/etc/archiver.data", getenv("MBSE_ROOT"));
if ((fp = fopen(filename, "r")) == NULL) {
WriteError("$Can't open %s", filename);
free(filename);
return FALSE;
}
free(filename);
fread(&archiverhdr, sizeof(archiverhdr), 1, fp);
while (fread(&archiver, archiverhdr.recsize, 1, fp) == 1) {
if ((archiver.available) && (strcmp(archiver.name, unarc) == 0)) {
fclose(fp);
return TRUE;
}
}
fclose(fp);
return FALSE;
}

161
lib/users.h Normal file
View File

@@ -0,0 +1,161 @@
/*****************************************************************************
*
* $Id: users.h,v 1.10 2007/02/25 20:28:07 mbse Exp $
* Purpose ...............: MBSE BBS Users Database structure
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* 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.
*****************************************************************************/
#ifndef _USERRECS_H
#define _USERRECS_H
#define Max_passlen 14 /* Define maximum passwd length */
typedef enum {X_LINEEDIT, FSEDIT, EXTEDIT} MSGEDITOR;
/************************************************************************
*
* Other BBS structures
*
*/
#ifndef _SECURITYSTRUCT
#define _SECURITYSTRUCT
/*
* Security structure
*/
typedef struct _security {
unsigned int level; /* Security level */
unsigned int flags; /* Access flags */
unsigned int notflags; /* No Access flags */
} securityrec;
#endif
/****************************************************************************
*
* Datafile records structure in $MBSE_ROOT/etc
*
*/
/*
* Users Control Structures (users.data)
*/
struct userhdr {
int hdrsize; /* Size of header */
int recsize; /* Size of records */
};
struct userrec {
char sUserName[36]; /* User First and Last Name */
char Name[9]; /* Unix name */
unsigned int xPassword;
char sVoicePhone[20]; /* Voice Number */
char sDataPhone[20]; /* Data/Business Number */
char sLocation[28]; /* Users Location */
char address[3][41]; /* Users address */
char sDateOfBirth[12]; /* Date of Birth */
int32_t tFirstLoginDate; /* Date of First Login */
int32_t tLastLoginDate; /* Date of Last Login */
securityrec Security; /* User Security Level */
char sComment[81]; /* User Comment */
char sExpiryDate[12]; /* User Expiry Date */
securityrec ExpirySec; /* Expiry Security Level */
char sSex[8]; /* Users Sex */
unsigned Hidden : 1; /* Hide User from Lists */
unsigned HotKeys : 1; /* Hot-Keys ON/OFF */
unsigned xGraphMode : 1;
unsigned Deleted : 1; /* Deleted Status */
unsigned NeverDelete : 1; /* Never Delete User */
unsigned xChat : 1;
unsigned LockedOut : 1; /* User is locked out */
unsigned DoNotDisturb : 1; /* DoNot disturb */
unsigned Cls : 1; /* CLS on/off */
unsigned More : 1; /* More prompt */
unsigned xFsMsged : 1;
unsigned MailScan : 1; /* New Mail scan */
unsigned Guest : 1; /* Is guest account */
unsigned OL_ExtInfo : 1; /* OLR extended msg info */
int iTotalCalls; /* Total number of calls */
int iTimeLeft; /* Time left today */
int iConnectTime; /* Connect time this call */
int iTimeUsed; /* Time used today */
int xScreenLen;
int32_t tLastPwdChange; /* Date last password chg */
unsigned xHangUps;
int Credit; /* Users credit */
int Paged; /* Times paged today */
int MsgEditor; /* Message Editor to use */
int LastPktNum; /* Todays Last packet number*/
char Archiver[6]; /* Archiver to use */
int iLastFileArea; /* Number of last file area */
int iLastFileGroup; /* Number of last file group*/
char sProtocol[21]; /* Users default protocol */
unsigned int Downloads; /* Total number of d/l's */
unsigned int Uploads; /* Total number of uploads */
unsigned int UploadK; /* Upload KiloBytes */
unsigned int DownloadK; /* Download KiloBytes */
int DownloadKToday; /* KB Downloaded today */
int UploadKToday; /* KB Uploaded today */
int iTransferTime; /* Last file transfer time */
int iLastMsgArea; /* Number of last msg area */
int iLastMsgGroup; /* Number of last msg group */
int iPosted; /* Number of msgs posted */
int iLanguage; /* Current Language */
char sHandle[36]; /* Users Handle */
int iStatus; /* WhosDoingWhat status */
int DownloadsToday; /* Downloads today */
int CrtDef; /* IEMSI Terminal emulation */
int Protocol; /* IEMSI protocol */
unsigned IEMSI : 1; /* Is this a IEMSI session */
unsigned ieMNU : 1; /* Can do ASCII download */
unsigned ieTAB : 1; /* Can handle TAB character */
unsigned ieASCII8 : 1; /* Can handle 8-bit IBM-PC */
unsigned ieNEWS : 1; /* Show bulletins */
unsigned ieFILE : 1; /* Check for new files */
unsigned Email : 1; /* Has private email box */
unsigned FSemacs : 1; /* FSedit uses emacs keys */
char Password[Max_passlen+1];/* Plain password */
int Charset; /* Character set */
};
struct userhdr usrconfighdr; /* Users database */
struct userrec usrconfig;
struct userrec exitinfo; /* Users online data */
#endif

385
lib/virscan.c Normal file
View File

@@ -0,0 +1,385 @@
/*****************************************************************************
*
* $Id: virscan.c,v 1.3 2008/02/25 12:11:42 mbse Exp $
* Purpose ...............: Scan a file for virusses
*
*****************************************************************************
* Copyright (C) 1997-2008
*
* 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 "mbselib.h"
extern pid_t mypid;
/*
* ClamAV stream check.
* Original written bu Laurent Wacrenier as part of the
* clamd-stream-client.
* Returns: 0 = Ok, no virus found.
* 1 = Virus found.
* 2 = Internal error.
*/
int clam_stream_check(char *server, char *port, char *filename)
{
struct sockaddr_in sa_in;
struct addrinfo hints, *res;
int s, ss, buf_len = 0, err;
char buf[1024], *buf_c, *port_s;
FILE *fp;
Syslog('f', "clam_stream_check(%s, %s, %s)", server, port, filename);
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo(server, port, &hints, &res)) != 0) {
WriteError("getaddrinfo(%s:%s): %s\n", server, port, gai_strerror(err));
return 2;
}
while (res) {
s = socket(PF_INET, SOCK_STREAM, 0);
if (s == -1) {
WriteError("$socket()");
return 2;
}
if (connect(s, res->ai_addr, sizeof(struct sockaddr)) == -1) {
struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr;
WriteError("$connect(%s:%d)", inet_ntoa(sa->sin_addr), (int)ntohs(sa->sin_port));
res = res->ai_next;
close(s);
} else {
break;
}
}
if (res == NULL) {
WriteError("unable to connect to %s", server);
return 2;
}
#define COMMAND "STREAM\r\n"
Syslog('f', "snd: %s", printable((char *)COMMAND, 0));
if (write(s, COMMAND, sizeof(COMMAND)-1) == -1) {
WriteError("$write()");
return 2;
}
if ((buf_len = read(s, buf, sizeof(buf)-1)) == -1) {
WriteError("$read()");
return 2;
}
Syslog('f', "got: %s", printable(buf, 0));
buf[buf_len] = 0;
if (strncasecmp(buf, "PORT ", sizeof("PORT ") -1) != 0) {
return 2;
}
port_s = buf + sizeof("PORT ") -1;
while(*port_s == ' ') port_s ++;
memcpy(&sa_in, res->ai_addr, sizeof(sa_in));
sa_in.sin_port = htons(strtoul(port_s, NULL, 10));
sa_in.sin_family = AF_INET;
ss = socket(PF_INET, SOCK_STREAM, 0);
if (ss == -1) {
WriteError("$socket()");
return 2;
}
sa_in.sin_port = htons(strtoul(port_s, NULL, 10));
if (connect(ss, (struct sockaddr *)&sa_in, sizeof(struct sockaddr_in)) == -1) {
WriteError("$connect2()");
return 2;
}
if ((fp = fopen(filename, "r")) == NULL) {
WriteError("$can't open %s", filename);
return 2;
}
while ((buf_len = fread(buf, 1, sizeof(buf), fp)) > 0) {
if (write(ss, buf, buf_len) == -1) {
if (errno == EPIPE)
break;
WriteError("$write2()");
fclose(fp);
return 2;
}
}
if (buf_len == 0 && ferror(fp)) {
WriteError("$read2()");
return 2;
}
close(ss);
fclose(fp);
if ((buf_len = read(s, buf, sizeof(buf)-1)) == -1) {
WriteError("$read3()");
return 2;
}
buf[buf_len] = 0;
Syslog('f', "res: %s", printable(buf, 0));
/* fwrite(buf, 1, buf_len, stderr); */
buf_c = buf + buf_len;
while(*buf_c=='\r' || *buf_c == '\r' || *buf_c == ' ')
*buf_c --;
if (buf_c - buf >= sizeof(" FOUND") && strncasecmp(buf_c - sizeof(" FOUND"), " FOUND", sizeof(" FOUND")-1) == 0) {
char *buf_s = buf;
buf_c -= sizeof(" FOUND");
if (strncasecmp(buf_s, "stream:", sizeof("stream:")-1) == 0) {
buf_s += sizeof("stream:")-1;
while(*buf_s == ' ')
buf_s ++;
WriteError("ClamAV stream check, virus found: %.*s", (int)(buf_c - buf_s), buf_s);
}
return 1;
}
close(s);
Syslog('f', "clam_stream_check(): no virus found");
return 0;
}
/*
* F-Prot stream check.
* Returns: 0 = Ok, no virus found.
* 1 = Virus found.
* 2 = Internal error.
*
* telnet localhost 10200
* SCAN FILE /path/to/file SIZE n
* stream data
* --
* receive:
* n <descriptive text> <name of the scanned object>
* n -= result code, 0 s clean.
*/
int fp_stream_check(char *server, char *port, char *filename)
{
struct addrinfo hints, *res;
int filesize = 0, buf_len = 0, s, err;
char *cmd, buf[1024], *str1, *str2;
FILE *fp;
Syslog('f', "fp_stream_check(%s, %s, %s)", server, port, filename);
filesize = file_size(filename);
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo(server, port, &hints, &res)) != 0) {
WriteError("getaddrinfo(%s:%s): %s\n", server, port, gai_strerror(err));
return 2;
}
while (res) {
s = socket(PF_INET, SOCK_STREAM, 0);
if (s == -1) {
WriteError("$socket()");
return 2;
}
if (connect(s, res->ai_addr, sizeof(struct sockaddr)) == -1) {
struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr;
WriteError("$connect(%s:%d)", inet_ntoa(sa->sin_addr), (int)ntohs(sa->sin_port));
res = res->ai_next;
close(s);
} else {
break;
}
}
if (res == NULL) {
WriteError("unable to connect to %s", server);
return 2;
}
cmd = calloc(PATH_MAX, sizeof(char));
snprintf(cmd, PATH_MAX-1, "SCAN STREAM %s SIZE %d\n", filename, filesize);
Syslog('f', "snd: %s", printable(cmd, 0));
if (write(s, cmd, strlen(cmd)) == -1) {
WriteError("$write()");
return 2;
}
free(cmd);
/*
* Stream the data
*/
if ((fp = fopen(filename, "r")) == NULL) {
WriteError("$can't open %s", filename);
return 2;
}
while ((buf_len = fread(buf, 1, sizeof(buf), fp)) > 0) {
if (write(s, buf, buf_len) == -1) {
if (errno == EPIPE)
break;
WriteError("$write2()");
fclose(fp);
return 2;
}
}
fclose(fp);
if ((buf_len = read(s, buf, sizeof(buf)-1)) == -1) {
WriteError("$read()");
return 2;
}
buf[buf_len] = '\0';
Syslog('f', "got: %s", printable(buf, 0));
cmd = xstrcpy(buf);
str1 = strtok(cmd, "<");
str1[strlen(str1)-1] = '\0';
str2 = strtok(NULL, ">");
err = atoi(str1);
if (err) {
// Message looks like: 'contains infected objects: EICAR_Test_File'
WriteError("F-Prot stream check %s, rc=%d", str2, err);
return 1;
}
close(s);
Syslog('f', "fp_stream_check(): no virus found");
return 0;
}
/*
* Virusscan on a file.
*/
int VirScanFile(char *filename)
{
char *temp, *stdlog, *errlog, buf[256], *port;
FILE *fp, *lp;
int vrc, rc = FALSE, has_scan = FALSE;
temp = calloc(PATH_MAX, sizeof(char));
snprintf(temp, PATH_MAX, "%s/etc/virscan.data", getenv("MBSE_ROOT"));
if ((fp = fopen(temp, "r")) == NULL) {
WriteError("No virus scanners defined");
free(temp);
return FALSE;
}
fread(&virscanhdr, sizeof(virscanhdr), 1, fp);
while (fread(&virscan, virscanhdr.recsize, 1, fp) == 1) {
if (virscan.available && (virscan.scantype == SCAN_EXTERN)) {
if (file_exist(virscan.scanner, X_OK) == 0) {
has_scan = TRUE;
} else {
Syslog('+', "Warning: virusscanner %s marked active but not present", virscan.comment);
}
}
if (virscan.available && (virscan.scantype != SCAN_EXTERN)) {
has_scan = TRUE;
}
}
if (!has_scan) {
Syslog('+', "No active virus scanners, skipping scan");
fclose(fp);
free(temp);
return FALSE;
}
stdlog = calloc(PATH_MAX, sizeof(char));
errlog = calloc(PATH_MAX, sizeof(char));
snprintf(stdlog, PATH_MAX, "%s/tmp/stdlog%d", getenv("MBSE_ROOT"), mypid);
snprintf(errlog, PATH_MAX, "%s/tmp/errlog%d", getenv("MBSE_ROOT"), mypid);
fseek(fp, virscanhdr.hdrsize, SEEK_SET);
while (fread(&virscan, virscanhdr.recsize, 1, fp) == 1) {
if (virscan.available) {
Syslog('+', "Scanning %s with %s", filename, virscan.comment);
Altime(3600);
switch (virscan.scantype) {
case SCAN_EXTERN: if (file_exist(virscan.scanner, X_OK) ==0) {
vrc = execute_str(virscan.scanner, virscan.options, filename, (char *)"/dev/null", stdlog, errlog);
if (file_size(stdlog)) {
if ((lp = fopen(stdlog, "r"))) {
while (fgets(buf, sizeof(buf) -1, lp)) {
Striplf(buf);
Syslog('+', "stdout: \"%s\"", printable(buf, 0));
}
fclose(lp);
}
}
if (file_size(errlog)) {
if ((lp = fopen(errlog, "r"))) {
while (fgets(buf, sizeof(buf) -1, lp)) {
Striplf(buf);
Syslog('+', "stderr: \"%s\"", printable(buf, 0));
}
fclose(lp);
}
}
unlink(stdlog);
unlink(errlog);
if (vrc != virscan.error) {
WriteError("Virus found by %s", virscan.comment);
rc = TRUE;
}
}
break;
case CLAM_STREAM: port = calloc(21, sizeof(char));
snprintf(port, 20, "%d", virscan.port);
if ((clam_stream_check(virscan.host, port, filename) == 1)) {
rc = TRUE;
}
free(port);
break;
case FP_STREAM: port = calloc(21, sizeof(char));
snprintf(port, 20, "%d", virscan.port);
if ((fp_stream_check(virscan.host, port, filename) == 1)) {
rc = TRUE;
}
free(port);
break;
}
Altime(0);
Nopper();
}
}
fclose(fp);
free(temp);
free(stdlog);
free(errlog);
return rc;
}