Rewrote binkp inbound handling and error recovery
This commit is contained in:
parent
a25c4267df
commit
c1dc37321d
@ -14,10 +14,12 @@ v0.71.6 02-Sep-2005
|
||||
Due to lack of maintainers italian language support is dropped.
|
||||
|
||||
mbcico:
|
||||
Changed compression state logic.
|
||||
Changed binkp compression state logic.
|
||||
Record previous session state so we can better react on failed
|
||||
sessions.
|
||||
Added detection of remote options NR, ND and NDA.
|
||||
Rewrote inbound handling for binkp sessions so that recovery
|
||||
from failed sessions works, even with compressed transfers.
|
||||
|
||||
mbfido:
|
||||
If some newsarticles are not accepted for post, don't treat
|
||||
|
@ -9,8 +9,8 @@ SRCS = zmmisc.c zmrle.c zmrecv.c zmsend.c binkp.c md5b.c \
|
||||
answer.c chat.c dial.c dietifna.c emsidat.c filelist.c \
|
||||
openfile.c openport.c opentcp.c rdoptions.c yoohoo.c \
|
||||
recvbark.c respfreq.c sendbark.c tcp.c tcpproto.c wazoo.c \
|
||||
filetime.c ftsc.c atoul.c portsel.c telnet.c \
|
||||
ttyio.c lutil.c scanout.c emsi.c ulock.c \
|
||||
filetime.c ftsc.c atoul.c portsel.c telnet.c bopenfile.c \
|
||||
ttyio.c lutil.c scanout.c emsi.c ulock.c dirlock.c \
|
||||
callstat.c session.c call.c mbcico.c \
|
||||
outstat.c nlinfo.c mbout.c
|
||||
HDRS = zmodem.h binkp.h config.h statetbl.h md5b.h \
|
||||
@ -18,8 +18,8 @@ HDRS = zmodem.h binkp.h config.h statetbl.h md5b.h \
|
||||
answer.h chat.h dial.h dietifna.h emsidat.h filelist.h \
|
||||
openfile.h openport.h opentcp.h rdoptions.h yoohoo.h \
|
||||
recvbark.h respfreq.h sendbark.h tcp.h tcpproto.h wazoo.h \
|
||||
filetime.h ftsc.h atoul.h portsel.h telnet.h \
|
||||
ttyio.h lutil.h scanout.h emsi.h ulock.h \
|
||||
filetime.h ftsc.h atoul.h portsel.h telnet.h bopenfile.h \
|
||||
ttyio.h lutil.h scanout.h emsi.h ulock.h dirlock.h \
|
||||
callstat.h session.h call.h mbcico.h \
|
||||
outstat.h nlinfo.h
|
||||
MBCICO_OBJS = zmmisc.o zmrle.o zmrecv.o zmsend.o binkp.o md5b.o \
|
||||
@ -27,8 +27,8 @@ MBCICO_OBJS = zmmisc.o zmrle.o zmrecv.o zmsend.o binkp.o md5b.o \
|
||||
answer.o chat.o dial.o dietifna.o emsidat.o filelist.o \
|
||||
openfile.o openport.o opentcp.o rdoptions.o yoohoo.o \
|
||||
recvbark.o respfreq.o sendbark.o tcp.o tcpproto.o wazoo.o \
|
||||
filetime.o ftsc.o atoul.o portsel.o telnet.o \
|
||||
ttyio.o lutil.o scanout.o emsi.o ulock.o \
|
||||
filetime.o ftsc.o atoul.o portsel.o telnet.o bopenfile.o \
|
||||
ttyio.o lutil.o scanout.o emsi.o ulock.o dirlock.o \
|
||||
callstat.o session.o call.o mbcico.o
|
||||
MBOUT_OBJS = outstat.o nlinfo.o mbout.o scanout.o callstat.o
|
||||
SLIBS = ../lib/libmbse.a ../lib/libmsgbase.a ../lib/libdbase.a ../lib/libnodelist.a
|
||||
@ -90,14 +90,14 @@ zmmisc.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmode
|
||||
zmrle.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmodem.h
|
||||
zmrecv.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h lutil.h ttyio.h session.h zmodem.h config.h emsi.h openfile.h filelist.h openport.h
|
||||
zmsend.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h session.h zmodem.h lutil.h emsi.h filelist.h
|
||||
binkp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h ttyio.h session.h statetbl.h config.h emsi.h openfile.h respfreq.h filelist.h opentcp.h rdoptions.h lutil.h binkp.h config.h md5b.h inbound.h callstat.h
|
||||
binkp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h ttyio.h session.h statetbl.h config.h emsi.h bopenfile.h respfreq.h filelist.h opentcp.h rdoptions.h lutil.h binkp.h config.h md5b.h inbound.h callstat.h mbcico.h
|
||||
md5b.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h lutil.h md5b.h
|
||||
xmsend.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetbl.h xmsend.h m7send.h filelist.h filetime.h
|
||||
xmrecv.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetbl.h config.h lutil.h openfile.h m7recv.h xmrecv.h filelist.h filetime.h
|
||||
m7recv.o: ../config.h ../lib/mbselib.h statetbl.h ttyio.h m7recv.h
|
||||
m7send.o: ../config.h ../lib/mbselib.h statetbl.h ttyio.h m7send.h
|
||||
hydra.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h filelist.h filetime.h ttyio.h statetbl.h config.h emsi.h openfile.h lutil.h respfreq.h mbcico.h hydra.h
|
||||
inbound.o: ../config.h ../lib/mbselib.h inbound.h
|
||||
inbound.o: ../config.h ../lib/mbselib.h dirlock.h inbound.h
|
||||
answer.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h lutil.h session.h config.h answer.h openport.h portsel.h dial.h rdoptions.h mbcico.h
|
||||
chat.o: ../config.h ../lib/mbselib.h config.h chat.h ttyio.h
|
||||
dial.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h config.h chat.h ttyio.h session.h dial.h
|
||||
@ -120,15 +120,17 @@ ftsc.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h session.h ttyio.h statetb
|
||||
atoul.o: ../config.h ../lib/mbselib.h atoul.h
|
||||
portsel.o: ../config.h ../lib/mbselib.h portsel.h
|
||||
telnet.o: ../config.h ../lib/mbselib.h telnet.h
|
||||
bopenfile.o: ../config.h ../lib/mbselib.h config.h lutil.h bopenfile.h
|
||||
ttyio.o: ../config.h ../lib/mbselib.h ttyio.h lutil.h
|
||||
lutil.o: ../config.h ../lib/mbselib.h lutil.h
|
||||
scanout.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h config.h scanout.h lutil.h
|
||||
emsi.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h ttyio.h session.h statetbl.h config.h emsi.h emsidat.h hydra.h rdoptions.h tcp.h wazoo.h inbound.h callstat.h
|
||||
ulock.o: ../config.h ../lib/mbselib.h
|
||||
dirlock.o: ../config.h ../lib/mbselib.h dirlock.h
|
||||
callstat.o: ../config.h ../lib/mbselib.h callstat.h
|
||||
session.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h statetbl.h emsi.h ftsc.h session.h yoohoo.h mbcico.h binkp.h callstat.h inbound.h opentcp.h telnet.h
|
||||
call.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/nodelist.h ../lib/mbsedb.h session.h callstat.h call.h config.h dial.h lutil.h portsel.h openport.h opentcp.h rdoptions.h inbound.h
|
||||
mbcico.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h config.h answer.h call.h lutil.h mbcico.h session.h
|
||||
mbcico.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h config.h answer.h call.h lutil.h mbcico.h session.h binkp.h
|
||||
outstat.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h scanout.h callstat.h outstat.h
|
||||
nlinfo.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h nlinfo.h
|
||||
mbout.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ../lib/users.h ../lib/mbsedb.h outstat.h nlinfo.h
|
||||
|
101
mbcico/binkp.c
101
mbcico/binkp.c
@ -39,7 +39,7 @@
|
||||
#include "statetbl.h"
|
||||
#include "config.h"
|
||||
#include "emsi.h"
|
||||
#include "openfile.h"
|
||||
#include "bopenfile.h"
|
||||
#include "respfreq.h"
|
||||
#include "filelist.h"
|
||||
#include "opentcp.h"
|
||||
@ -50,6 +50,7 @@
|
||||
#include "md5b.h"
|
||||
#include "inbound.h"
|
||||
#include "callstat.h"
|
||||
#include "mbcico.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -74,6 +75,9 @@ extern pid_t mypid;
|
||||
extern struct sockaddr_in peeraddr;
|
||||
extern int most_debug;
|
||||
extern int laststat;
|
||||
extern int crashme;
|
||||
|
||||
int gotblock = 0;
|
||||
|
||||
|
||||
extern unsigned long sentbytes;
|
||||
@ -171,7 +175,6 @@ struct binkprec {
|
||||
#endif
|
||||
|
||||
struct timezone tz; /* Timezone */
|
||||
int DidSendGET; /* Receiver send GET status */
|
||||
|
||||
char *txbuf; /* Transmitter buffer */
|
||||
int txlen; /* Transmitter file length */
|
||||
@ -246,7 +249,6 @@ void parse_m_nul(char *); /* Parse M_NUL message */
|
||||
int binkp_poll_frame(void); /* Poll for a frame */
|
||||
void binkp_add_message(char *frame); /* Add cmd frame to queue */
|
||||
int binkp_process_messages(void); /* Process the queue */
|
||||
int binkp_resync(off_t); /* File resync */
|
||||
char *unix2binkp(char *); /* Binkp -> Unix escape */
|
||||
char *binkp2unix(char *); /* Unix -> Binkp escape */
|
||||
void fill_binkp_list(binkp_list **, file_list *, off_t); /* Build pending files */
|
||||
@ -281,7 +283,6 @@ int binkp(int role)
|
||||
bp.rname = calloc(512, sizeof(char));
|
||||
bp.ropts = calloc(512, sizeof(char));
|
||||
bp.rxfp = NULL;
|
||||
bp.DidSendGET = FALSE;
|
||||
bp.local_EOB = FALSE;
|
||||
bp.remote_EOB = FALSE;
|
||||
bp.msgs_on_queue = 0;
|
||||
@ -317,7 +318,6 @@ int binkp(int role)
|
||||
#endif
|
||||
#endif
|
||||
bp.buggyIrex = FALSE;
|
||||
laststat = 0;
|
||||
bp.NRwe = No;
|
||||
bp.NRthey = No;
|
||||
bp.NDwe = No;
|
||||
@ -653,7 +653,6 @@ SM_STATE(WaitOk)
|
||||
|
||||
SM_STATE(Opts)
|
||||
|
||||
Syslog('b', "Binkp: last session was %d", laststat);
|
||||
IsDoing("Binkp to %s", ascfnode(remote->addr, 0xf));
|
||||
binkp_set_comp_state();
|
||||
SM_SUCCESS;
|
||||
@ -924,7 +923,7 @@ SM_STATE(PwdAck)
|
||||
}
|
||||
free(pw);
|
||||
Syslog('+', "Binkp: %s%sprotected session", bp.CRAMflag ? "MD5 ":"", bp.Secure ? "":"un");
|
||||
inbound_open(remote->addr, bp.Secure);
|
||||
inbound_open(remote->addr, bp.Secure, TRUE);
|
||||
binkp_send_command(MM_OK, "%ssecure", bp.Secure ? "":"non-");
|
||||
SM_PROCEED(Opts)
|
||||
|
||||
@ -952,7 +951,6 @@ SM_STATE(Opts)
|
||||
|
||||
binkp_send_comp_opts();
|
||||
binkp_set_comp_state();
|
||||
Syslog('b', "Binkp: last session status %d", laststat);
|
||||
|
||||
SM_SUCCESS;
|
||||
|
||||
@ -982,6 +980,7 @@ int file_transfer(void)
|
||||
bp.TxState = TxGNF;
|
||||
bp.FtState = Switch;
|
||||
bp.messages = 0;
|
||||
Syslog('b', "Binkp: last session was %d", laststat);
|
||||
break;
|
||||
|
||||
case Switch: if ((bp.RxState == RxDone) && (bp.TxState == TxDone)) {
|
||||
@ -1184,21 +1183,24 @@ TrType binkp_receiver(void)
|
||||
#endif
|
||||
(void)binkp2unix(bp.rname);
|
||||
rxbytes = bp.rxbytes;
|
||||
bp.rxfp = openfile(binkp2unix(bp.rname), bp.rtime, bp.rsize, &rxbytes, binkp_resync);
|
||||
|
||||
/*
|
||||
* Open file if M_FILE frame has offset 0
|
||||
* Else the file is already open.
|
||||
*/
|
||||
if (bp.roffs && (bp.roffs == rxbytes)) {
|
||||
Syslog('b', "Binkp: offset == rxbytes, don't open file again");
|
||||
if (fseek(bp.rxfp, bp.roffs, SEEK_SET) == 0)
|
||||
Syslog('b', "Binkp: file position set to %ld", bp.roffs);
|
||||
else
|
||||
WriteError("$Binkp: can't fseek to %ld", bp.roffs);
|
||||
} else {
|
||||
bp.rxfp = bopenfile(binkp2unix(bp.rname), bp.rtime, bp.rsize, &rxbytes);
|
||||
}
|
||||
|
||||
bp.rxbytes = rxbytes;
|
||||
bp.rxcompressed = 0;
|
||||
|
||||
if (bp.DidSendGET) {
|
||||
Syslog('b', "Binkp: DidSendGET is set");
|
||||
/*
|
||||
* The file was partly received, via the openfile the resync function
|
||||
* has send a GET command to start this file with a offset. This means
|
||||
* we will get a new FILE command to open this file with a offset.
|
||||
*/
|
||||
bp.RxState = RxWaitF;
|
||||
return Ok;
|
||||
}
|
||||
|
||||
gettimeofday(&rxtvstart, &bp.tz);
|
||||
bp.rxpos = bp.roffs;
|
||||
|
||||
@ -1215,7 +1217,7 @@ TrType binkp_receiver(void)
|
||||
if ((bp.rsize / (sfs.f_bsize + 1)) >= sfs.f_bfree) {
|
||||
Syslog('!', "Binkp: only %lu blocks free (need %lu) in %s for this file", sfs.f_bfree,
|
||||
(unsigned long)(bp.rsize / (sfs.f_bsize + 1)), tempinbound);
|
||||
closefile();
|
||||
bclosefile(FALSE);
|
||||
bp.rxfp = NULL; /* Force SKIP command */
|
||||
}
|
||||
}
|
||||
@ -1233,6 +1235,14 @@ TrType binkp_receiver(void)
|
||||
return Failure;
|
||||
else
|
||||
return Ok;
|
||||
} else if ((bp.rxbytes < bp.rsize) && (bp.roffs == 0) && bp.rxbytes) {
|
||||
Syslog('+', "Binkp: partial file present, resync");
|
||||
rc = binkp_send_command(MM_GET, "%s %ld %ld %ld", bp.rname, bp.rsize, bp.rtime, bp.rxbytes);
|
||||
bp.RxState = RxWaitF;
|
||||
if (rc)
|
||||
return Failure;
|
||||
else
|
||||
return Ok;
|
||||
} else if (!bp.rxfp) {
|
||||
/*
|
||||
* Some error, request to skip it
|
||||
@ -1245,7 +1255,7 @@ TrType binkp_receiver(void)
|
||||
else
|
||||
return Ok;
|
||||
} else {
|
||||
Syslog('b', "rsize=%d, rxbytes=%d, roffs=%d", bp.rsize, bp.rxbytes, bp.roffs);
|
||||
Syslog('b', "Binkp: rsize=%d, rxbytes=%d, roffs=%d, goto RxReceD", bp.rsize, bp.rxbytes, bp.roffs);
|
||||
bp.RxState = RxReceD;
|
||||
return Ok;
|
||||
}
|
||||
@ -1278,7 +1288,7 @@ TrType binkp_receiver(void)
|
||||
return Ok;
|
||||
} else if (bcmd == MM_FILE) {
|
||||
Syslog('+', "Binkp: partial received file, saving");
|
||||
closefile();
|
||||
bclosefile(FALSE);
|
||||
bp.rxfp = NULL;
|
||||
bp.RxState = RxAccF;
|
||||
return Continue;
|
||||
@ -1371,7 +1381,7 @@ TrType binkp_receiver(void)
|
||||
|
||||
if (bp.rxpos == bp.rsize) {
|
||||
rc = binkp_send_command(MM_GOT, "%s %ld %ld", bp.rname, bp.rsize, bp.rtime);
|
||||
closefile();
|
||||
bclosefile(TRUE);
|
||||
bp.rxpos = bp.rxpos - bp.rxbytes;
|
||||
gettimeofday(&rxtvend, &bp.tz);
|
||||
#if defined(HAVE_ZLIB_H) || defined(HAVE_BZLIB_H)
|
||||
@ -2383,6 +2393,11 @@ int binkp_poll_frame(void)
|
||||
}
|
||||
} else {
|
||||
Syslog('b', "Binkp: rcvd data (%d)", bp.rxlen -1);
|
||||
gotblock++;
|
||||
if (crashme && (gotblock > 10)) {
|
||||
Syslog('b', "Binkp: will crash now");
|
||||
die(SIGHUP);
|
||||
}
|
||||
}
|
||||
binkp_settimer(BINKP_TIMEOUT);
|
||||
Nopper();
|
||||
@ -2648,26 +2663,6 @@ int binkp_pendingfiles(void)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This function is called two times if a partial file exists from openfile.
|
||||
* 1. A partial file is detected, send a GET to the remote, set DidSendGET flag.
|
||||
* 2. DidSendGET is set, return 0 and let openfile open the file in append mode.
|
||||
*/
|
||||
int binkp_resync(off_t off)
|
||||
{
|
||||
Syslog('b', "Binkp: resync(%d) DidSendGET=%s", off, bp.DidSendGET ?"TRUE":"FALSE");
|
||||
if (!bp.DidSendGET) {
|
||||
binkp_send_command(MM_GET, "%s %ld %ld %ld", bp.rname, bp.rsize, bp.rtime, off);
|
||||
bp.DidSendGET = TRUE;
|
||||
Syslog('+', "Binkp: already %lu bytes received, requested restart with offset", (unsigned long)off);
|
||||
return -1; /* Signal openfile not to open the file */
|
||||
}
|
||||
bp.DidSendGET = FALSE;
|
||||
return 0; /* Signal openfile to open the file in append mode */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Translate string to binkp escaped string, unsafe characters are escaped.
|
||||
*/
|
||||
@ -3142,3 +3137,21 @@ int decompress_abort(int type, void *data)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Abort, called from die in case there were errors.
|
||||
* This will reconstruct file data that is still in
|
||||
* compressed state in memory so that resync works.
|
||||
*/
|
||||
void binkp_abort(void)
|
||||
{
|
||||
Syslog('b', "Binkp: abort");
|
||||
#ifdef USE_EXPERIMENT
|
||||
if ((bp.rmode != CompNone) && z_idata)
|
||||
decompress_abort(bp.rmode, z_idata);
|
||||
if ((bp.tmode != CompNone) && z_odata)
|
||||
compress_abort(bp.tmode, z_odata);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,7 @@ typedef struct _the_queue {
|
||||
|
||||
|
||||
|
||||
int binkp(int);
|
||||
int binkp(int);
|
||||
void binkp_abort(void);
|
||||
|
||||
#endif
|
||||
|
@ -163,7 +163,7 @@ int bclosefile(int success)
|
||||
* Remove state file.
|
||||
*/
|
||||
temp = calloc(PATH_MAX, sizeof(char));
|
||||
snprintf(temp, PATH_MAX, "%s.state", infpath, basename(infpath));
|
||||
snprintf(temp, PATH_MAX, "%s.state", infpath);
|
||||
if (unlink(temp))
|
||||
WriteError("$Binkp: can't unlink %s", temp);
|
||||
else
|
||||
|
9
mbcico/bopenfile.h
Normal file
9
mbcico/bopenfile.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef _BOPENFILE_H
|
||||
#define _BOPENFILE_H
|
||||
|
||||
FILE *bopenfile(char *, time_t, off_t, off_t *);
|
||||
int bclosefile(int);
|
||||
|
||||
#endif
|
@ -207,7 +207,7 @@ int call(faddr *addr)
|
||||
Syslog('?', "Warning: calling non-CM system outside ZMH");
|
||||
}
|
||||
|
||||
inbound_open(addr, TRUE); /* master sessions are secure */
|
||||
inbound_open(addr, TRUE, (tcp_mode == TCPMODE_IBN)); /* master sessions are secure */
|
||||
|
||||
/*
|
||||
* Call when:
|
||||
|
149
mbcico/dirlock.c
Normal file
149
mbcico/dirlock.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
* Purpose ...............: Lock a directory
|
||||
*
|
||||
*****************************************************************************
|
||||
* 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 "../lib/mbselib.h"
|
||||
#include "dirlock.h"
|
||||
|
||||
#define TMPNAME "TMP."
|
||||
#define LCKNAME "LOCKFILE"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Put a lock on a directory.
|
||||
*/
|
||||
int lockdir(char *directory)
|
||||
{
|
||||
char *Tmpfile, *lockfile;
|
||||
FILE *fp;
|
||||
pid_t oldpid;
|
||||
|
||||
Tmpfile = calloc(PATH_MAX, sizeof(char));
|
||||
lockfile = calloc(PATH_MAX, sizeof(char));
|
||||
snprintf(Tmpfile, PATH_MAX, "%s/", directory);
|
||||
strcpy(lockfile, Tmpfile);
|
||||
snprintf(Tmpfile + strlen(Tmpfile), PATH_MAX, "%s%u", TMPNAME, getpid());
|
||||
snprintf(lockfile + strlen(lockfile), PATH_MAX - strlen(lockfile), "%s", LCKNAME);
|
||||
|
||||
if ((fp = fopen(Tmpfile, "w")) == NULL) {
|
||||
WriteError("$Can't create lockfile \"%s\"", Tmpfile);
|
||||
free(Tmpfile);
|
||||
free(lockfile);
|
||||
return FALSE;
|
||||
}
|
||||
fprintf(fp, "%10u\n", getpid());
|
||||
fclose(fp);
|
||||
|
||||
while (TRUE) {
|
||||
if (link(Tmpfile, lockfile) == 0) {
|
||||
unlink(Tmpfile);
|
||||
free(Tmpfile);
|
||||
free(lockfile);
|
||||
return TRUE;
|
||||
}
|
||||
if ((fp = fopen(lockfile, "r")) == NULL) {
|
||||
WriteError("$Can't open lockfile \"%s\"", Tmpfile);
|
||||
unlink(Tmpfile);
|
||||
free(Tmpfile);
|
||||
free(lockfile);
|
||||
return FALSE;
|
||||
}
|
||||
if (fscanf(fp, "%u", &oldpid) != 1) {
|
||||
WriteError("$Can't read old pid from \"%s\"", Tmpfile);
|
||||
fclose(fp);
|
||||
unlink(Tmpfile);
|
||||
free(Tmpfile);
|
||||
free(lockfile);
|
||||
return FALSE;
|
||||
}
|
||||
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(Tmpfile);
|
||||
free(Tmpfile);
|
||||
free(lockfile);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
Syslog('+', "Already locked by, pid=%u", oldpid);
|
||||
unlink(Tmpfile);
|
||||
free(Tmpfile);
|
||||
free(lockfile);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Unlock directory, make extra check to see if it is our own lock.
|
||||
*/
|
||||
void ulockdir(char *directory)
|
||||
{
|
||||
char *lockfile;
|
||||
FILE *fp;
|
||||
pid_t oldpid;
|
||||
|
||||
lockfile = calloc(PATH_MAX, sizeof(char));
|
||||
snprintf(lockfile, PATH_MAX, "%s/", directory);
|
||||
snprintf(lockfile + strlen(lockfile), PATH_MAX - strlen(lockfile), "%s", LCKNAME);
|
||||
|
||||
if ((fp = fopen(lockfile, "r")) == NULL) {
|
||||
/*
|
||||
* No lockfile found, so not removed.
|
||||
*/
|
||||
free(lockfile);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fscanf(fp, "%u", &oldpid) != 1) {
|
||||
WriteError("$Can't read old pid from \"%s\"", lockfile);
|
||||
} else {
|
||||
if (getpid() != oldpid) {
|
||||
WriteError("Attempt to remove lock %s of pid %d", lockfile, oldpid);
|
||||
} else {
|
||||
/*
|
||||
* Only remove our own lock.
|
||||
*/
|
||||
unlink(lockfile);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
free(lockfile);
|
||||
}
|
||||
|
9
mbcico/dirlock.h
Normal file
9
mbcico/dirlock.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef _DIRLOCK_H
|
||||
#define _DIRLOCK_H
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
int lockdir(char *);
|
||||
void ulockdir(char *);
|
||||
|
||||
#endif
|
@ -175,7 +175,7 @@ int rx_emsi(char *data)
|
||||
Syslog('?', "Unexpected remote password \"%s\"", MBSE_SS(emsi_local_password));
|
||||
}
|
||||
|
||||
inbound_open(remote->addr, protect);
|
||||
inbound_open(remote->addr, protect, FALSE);
|
||||
Syslog('i', "local lcodes 0x%04x, protos 0x%04x, opts 0x%04x", emsi_local_lcodes,emsi_local_protos,emsi_local_opts);
|
||||
|
||||
if ((rc=txemsi()))
|
||||
|
@ -461,10 +461,10 @@ SM_STATE(scan_packet)
|
||||
|
||||
if (ghc == 0) {
|
||||
Syslog('+', "Password correct, protected FTS-0001 session");
|
||||
inbound_open(remote->addr, TRUE);
|
||||
inbound_open(remote->addr, TRUE, FALSE);
|
||||
} else {
|
||||
Syslog('+', "Unsecure FTS-0001 session");
|
||||
inbound_open(remote->addr, FALSE);
|
||||
inbound_open(remote->addr, FALSE, FALSE);
|
||||
}
|
||||
/*
|
||||
* Move the packet to the temp inbound so the we can later
|
||||
|
@ -1,7 +1,6 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
* File ..................: mbcico/inbound.c
|
||||
* Purpose ...............: Fidonet mailer, inbound functions
|
||||
*
|
||||
*****************************************************************************
|
||||
@ -31,28 +30,27 @@
|
||||
|
||||
#include "../config.h"
|
||||
#include "../lib/mbselib.h"
|
||||
#include "dirlock.h"
|
||||
#include "inbound.h"
|
||||
|
||||
|
||||
extern char *inbound;
|
||||
extern char *tempinbound;
|
||||
extern int gotfiles;
|
||||
extern int laststat;
|
||||
|
||||
|
||||
/*
|
||||
* Open the inbound directory, set the temp inbound for the node
|
||||
* so that this is true multiline safe. All files received from
|
||||
* the node during the session are stored here.
|
||||
* For binkp we add one extra directory to queue incoming files.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int inbound_open(faddr *addr, int protected)
|
||||
int inbound_open(faddr *addr, int protected, int binkp_mode)
|
||||
{
|
||||
char *temp;
|
||||
|
||||
DIR *dp;
|
||||
|
||||
if (inbound)
|
||||
free(inbound);
|
||||
inbound = NULL;
|
||||
@ -63,8 +61,22 @@ int inbound_open(faddr *addr, int protected)
|
||||
|
||||
temp = calloc(PATH_MAX, sizeof(char));
|
||||
snprintf(temp, PATH_MAX -1, "%s/tmp.%d.%d.%d.%d", inbound, addr->zone, addr->net, addr->node, addr->point);
|
||||
|
||||
/*
|
||||
* Check if this directory already exist, it should not unless the previous
|
||||
* session with this node failed for some reason.
|
||||
*/
|
||||
if ((dp = opendir(temp))) {
|
||||
Syslog('s', "Binkp: dir %s already exists, previous session failed", temp);
|
||||
laststat++;
|
||||
closedir(dp);
|
||||
}
|
||||
|
||||
tempinbound = xstrcpy(temp);
|
||||
snprintf(temp, PATH_MAX -1, "%s/foobar", tempinbound);
|
||||
if (binkp_mode)
|
||||
snprintf(temp, PATH_MAX, "%s/tmp/foobar", tempinbound);
|
||||
else
|
||||
snprintf(temp, PATH_MAX, "%s/foobar", tempinbound);
|
||||
mkdirs(temp, 0700);
|
||||
free(temp);
|
||||
|
||||
@ -86,7 +98,7 @@ int inbound_close(int success)
|
||||
struct dirent *de;
|
||||
char *source, *dest;
|
||||
struct stat stb;
|
||||
int rc;
|
||||
int i, rc;
|
||||
|
||||
Syslog('s', "Closing temp inbound after a %s session", success?"good":"failed");
|
||||
if (! success) {
|
||||
@ -100,6 +112,24 @@ int inbound_close(int success)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to lock the inbound so we can safely move the files
|
||||
* to the inbound.
|
||||
*/
|
||||
i = 30;
|
||||
while (TRUE) {
|
||||
if (lockdir(inbound))
|
||||
break;
|
||||
i--;
|
||||
if (! i) {
|
||||
WriteError("Can't lock %s", inbound);
|
||||
return 1;
|
||||
}
|
||||
sleep(20);
|
||||
Nopper();
|
||||
}
|
||||
Syslog('s', "inbound_close(): %s locked", inbound);
|
||||
|
||||
if ((dp = opendir(tempinbound)) == NULL) {
|
||||
WriteError("$Can't open %s", tempinbound);
|
||||
return 1;
|
||||
@ -109,8 +139,8 @@ int inbound_close(int success)
|
||||
dest = calloc(PATH_MAX, sizeof(char));
|
||||
|
||||
while ((de = readdir(dp))) {
|
||||
snprintf(source, PATH_MAX -1, "%s/%s", tempinbound, de->d_name);
|
||||
snprintf(dest, PATH_MAX -1, "%s/%s", inbound, de->d_name);
|
||||
snprintf(source, PATH_MAX, "%s/%s", tempinbound, de->d_name);
|
||||
snprintf(dest, PATH_MAX, "%s/%s", inbound, de->d_name);
|
||||
if ((lstat(source, &stb) == 0) && (S_ISREG(stb.st_mode))) {
|
||||
if (file_exist(dest, F_OK) == 0) {
|
||||
Syslog('!', "Cannot move %s to %s, file exists", de->d_name, inbound);
|
||||
@ -126,19 +156,35 @@ int inbound_close(int success)
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
free(source);
|
||||
free(dest);
|
||||
ulockdir(inbound);
|
||||
Syslog('s', "inbound_close(): %s unlocked", inbound);
|
||||
|
||||
/*
|
||||
* Try to remove binkp tmp queue. Only log if not empty, else
|
||||
* don't log anything, this directory doesn't exist for normal
|
||||
* sessions.
|
||||
*/
|
||||
snprintf(source, PATH_MAX, "%s/tmp", tempinbound);
|
||||
if ((rc = rmdir(source))) {
|
||||
if (errno == ENOTEMPTY) {
|
||||
Syslog('+', "Keep binkp temp incoming directory, partial file");
|
||||
}
|
||||
} else {
|
||||
Syslog('s', "inbound_close(): removed %s", source);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to clean the temp inbound, if it fails log this, maybe the
|
||||
* next time it will work.
|
||||
*/
|
||||
if ((rc = rmdir(tempinbound))) {
|
||||
WriteError("Can't remove %s: %s", tempinbound, strerror(rc));
|
||||
WriteError("$Can't remove %s", tempinbound);
|
||||
} else {
|
||||
Syslog('s', "inbound_close(): removed %s", tempinbound);
|
||||
}
|
||||
|
||||
free(source);
|
||||
free(dest);
|
||||
free(tempinbound);
|
||||
tempinbound = NULL;
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
* File ..................: mbcico/inbound.h
|
||||
* Purpose ...............: Fidonet mailer, inbound functions
|
||||
*
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1997-2003
|
||||
* Copyright (C) 1997-2005
|
||||
*
|
||||
* Michiel Broek FIDO: 2:280/2802
|
||||
* Beekmansbos 10
|
||||
@ -33,8 +32,8 @@
|
||||
#define _INBOUND_H
|
||||
|
||||
|
||||
int inbound_open(faddr *, int); /* Open temp inbound */
|
||||
int inbound_close(int); /* Close temp inbound */
|
||||
long inbound_space(void); /* Get free inbound space */
|
||||
int inbound_open(faddr *, int, int); /* Open temp inbound */
|
||||
int inbound_close(int); /* Close temp inbound */
|
||||
long inbound_space(void); /* Get free inbound space */
|
||||
|
||||
#endif
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include "lutil.h"
|
||||
#include "mbcico.h"
|
||||
#include "session.h"
|
||||
#include "binkp.h"
|
||||
|
||||
|
||||
#define IEMSI 1
|
||||
|
||||
@ -59,6 +61,7 @@ unsigned long rcvdbytes = 0;
|
||||
int tcp_mode = TCPMODE_NONE;
|
||||
int Loaded = FALSE;
|
||||
int telnet = FALSE;
|
||||
int crashme = FALSE;
|
||||
|
||||
|
||||
extern char *myname;
|
||||
@ -116,6 +119,7 @@ void die(int onsig)
|
||||
WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]);
|
||||
else
|
||||
Syslog('+', "Terminated with error %d", onsig);
|
||||
binkp_abort();
|
||||
}
|
||||
|
||||
if (sentbytes || rcvdbytes) {
|
||||
@ -232,7 +236,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
setmyname(argv[0]);
|
||||
|
||||
while ((c = getopt(argc,argv,"r:n:l:t:a:I:h")) != -1) {
|
||||
while ((c = getopt(argc,argv,"r:n:l:t:a:ch")) != -1) {
|
||||
switch (c) {
|
||||
case 'r': WriteError("commandline option -r is obsolete");
|
||||
break;
|
||||
@ -265,6 +269,10 @@ int main(int argc, char *argv[])
|
||||
case 'n': forcedphone = optarg;
|
||||
break;
|
||||
|
||||
case 'c': crashme = TRUE;
|
||||
Syslog('+', "crashme is set");
|
||||
break;
|
||||
|
||||
default: usage();
|
||||
die(MBERR_COMMANDLINE);
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ int rx_yoohoo(void)
|
||||
} else
|
||||
Syslog('s', "No YooHoo password check");
|
||||
|
||||
inbound_open(remote->addr, protect);
|
||||
inbound_open(remote->addr, protect, FALSE);
|
||||
|
||||
fillhello(localcaps,pwd);
|
||||
|
||||
|
Reference in New Issue
Block a user