303 lines
7.9 KiB
C++
303 lines
7.9 KiB
C++
// This may look like C code, but it is really -*- C++ -*-
|
|
|
|
// ------------------------------------------------------------------
|
|
// The Goldware Library
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
// ------------------------------------------------------------------
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Library General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Library General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Library General Public
|
|
// License along with this program; if not, write to the Free
|
|
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
// MA 02111-1307, USA
|
|
// ------------------------------------------------------------------
|
|
// $Id$
|
|
// ------------------------------------------------------------------
|
|
// Fido/Opus/FTSC (*.MSG) type handling
|
|
// ------------------------------------------------------------------
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#if defined(__WATCOMC__) || defined(__MINGW32__) || defined(_MSC_VER)
|
|
#include <sys/utime.h>
|
|
#else
|
|
#include <utime.h>
|
|
#endif
|
|
#include <gdbgtrk.h>
|
|
#include <gstrall.h>
|
|
#include <gmofido.h>
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::lock() {
|
|
|
|
GFTRK("FidoLock");
|
|
|
|
GFTRK(0);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::unlock() {
|
|
|
|
GFTRK("FidoUnlock");
|
|
|
|
GFTRK(0);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::save_message(int __mode, gmsg* __msg, FidoHdr& __hdr) {
|
|
|
|
// Build message filename
|
|
Path _msgfile;
|
|
if(__mode & GMSG_NEW) {
|
|
|
|
// Get a new message number
|
|
uint _cnt = 0;
|
|
do {
|
|
__msg->msgno = Msgn->CvtReln(Msgn->Count()) + (++_cnt);
|
|
} while(fexist(build_msgname(_msgfile, __msg->msgno)));
|
|
|
|
// Never create a new 1.MSG in echo or local areas.
|
|
if(__msg->msgno == 1) {
|
|
if(not isnet()) {
|
|
__msg->msgno = 2;
|
|
build_msgname(_msgfile, __msg->msgno);
|
|
}
|
|
}
|
|
|
|
// Avoid collision with an existing msg
|
|
while(fexist(_msgfile)) {
|
|
build_msgname(_msgfile, ++__msg->msgno);
|
|
// here we should signal that a rescan is needed
|
|
}
|
|
}
|
|
else {
|
|
build_msgname(_msgfile, __msg->msgno);
|
|
}
|
|
|
|
// Delete message, if so ordered
|
|
if(__mode & GMSG_DELETE) {
|
|
if(remove(_msgfile)) {
|
|
chmod(_msgfile, S_STDRW);
|
|
remove(_msgfile);
|
|
}
|
|
GFTRK(0);
|
|
return;
|
|
}
|
|
|
|
// Get message file attributes
|
|
struct stat st;
|
|
if(stat(_msgfile, &st) == 0) {
|
|
bool readonly = not (st.st_mode & S_IWUSR);
|
|
|
|
// If the file is read-only, make it read-write-able
|
|
if(readonly)
|
|
chmod(_msgfile, S_STDRW);
|
|
}
|
|
|
|
// Determine file open mode
|
|
int _omode = O_RDWR|O_CREAT|O_BINARY;
|
|
if(__mode & GMSG_TXT) {
|
|
|
|
// Add truncate, in case a changed msg is shorter
|
|
_omode |= O_TRUNC;
|
|
}
|
|
|
|
// Open the message file
|
|
int _fh = test_open(_msgfile, _omode, WideSharemode, YES);
|
|
|
|
// Get date/time of message file
|
|
if(not (__mode & GMSG_NEW) and not __msg->attr.upd()) {
|
|
fstat(_fh, &st);
|
|
}
|
|
|
|
memset(&__hdr, 0, sizeof(FidoHdr));
|
|
|
|
// Transfer attributes
|
|
__hdr.attr |= (word)(__msg->attr.pvt() ? FIDO_PVT : 0);
|
|
__hdr.attr |= (word)(__msg->attr.cra() ? FIDO_CRASH : 0);
|
|
__hdr.attr |= (word)(__msg->attr.rcv() ? FIDO_RECEIVED : 0);
|
|
__hdr.attr |= (word)(__msg->attr.snt() ? FIDO_SENT : 0);
|
|
__hdr.attr |= (word)(__msg->attr.att() ? FIDO_ATTACH : 0);
|
|
__hdr.attr |= (word)(__msg->attr.trs() ? FIDO_TRANSIT : 0);
|
|
__hdr.attr |= (word)(__msg->attr.orp() ? FIDO_ORPHAN : 0);
|
|
__hdr.attr |= (word)(__msg->attr.k_s() ? FIDO_KILLSENT : 0);
|
|
__hdr.attr |= (word)(__msg->attr.loc() ? FIDO_LOCAL : 0);
|
|
__hdr.attr |= (word)(__msg->attr.hld() ? FIDO_HOLD : 0);
|
|
__hdr.attr |= (word)(__msg->attr.rsv() ? FIDO_RESERVED : 0);
|
|
__hdr.attr |= (word)(__msg->attr.frq() ? FIDO_FREQ : 0);
|
|
__hdr.attr |= (word)(__msg->attr.rrq() ? FIDO_RETRECREQ : 0);
|
|
__hdr.attr |= (word)(__msg->attr.rrc() ? FIDO_RETREC : 0);
|
|
__hdr.attr |= (word)(__msg->attr.arq() ? FIDO_AUDITREQ : 0);
|
|
__hdr.attr |= (word)(__msg->attr.urq() ? FIDO_UPDREQ : 0);
|
|
|
|
strxcpy(__hdr.to, __msg->to, 36);
|
|
strxcpy(__hdr.by, __msg->by, 36);
|
|
strxcpy(__hdr.re, __msg->re, 72);
|
|
|
|
__hdr.ftsc.origzone = __msg->oorig.zone;
|
|
__hdr.orignet = __msg->oorig.net;
|
|
__hdr.orignode = __msg->oorig.node;
|
|
__hdr.ftsc.origpoint = __msg->oorig.point;
|
|
|
|
__hdr.ftsc.destzone = __msg->odest.zone;
|
|
__hdr.destnet = __msg->odest.net;
|
|
__hdr.destnode = __msg->odest.node;
|
|
__hdr.ftsc.destpoint = __msg->odest.point;
|
|
|
|
__hdr.replyto = (word)__msg->link.to();
|
|
__hdr.reply1st = (word)__msg->link.first();
|
|
|
|
__hdr.cost = (word)__msg->cost;
|
|
__hdr.timesread = (word)__msg->timesread;
|
|
|
|
if(isopus()) {
|
|
__hdr.opus.written = TimeToFTime(__msg->written);
|
|
__hdr.opus.arrived = TimeToFTime(__msg->arrived);
|
|
}
|
|
|
|
struct tm _tm; ggmtime(&_tm, &__msg->written);
|
|
sprintf(__hdr.datetime, "%02d %3s %02d %02d:%02d:%02d",
|
|
_tm.tm_mday, gmonths[_tm.tm_mon + 1], _tm.tm_year % 100,
|
|
_tm.tm_hour, _tm.tm_min, _tm.tm_sec
|
|
);
|
|
|
|
// Write message header
|
|
write(_fh, &__hdr, sizeof(FidoHdr));
|
|
|
|
// If message text is used
|
|
if(__mode & GMSG_TXT) {
|
|
|
|
// Write the message text
|
|
write(_fh, __msg->txt, strlen(__msg->txt)+1);
|
|
}
|
|
|
|
// Close the message file
|
|
::close(_fh);
|
|
|
|
// Reset date/time of message file
|
|
if(not (__mode & GMSG_NEW) and not __msg->attr.upd()) {
|
|
struct utimbuf t;
|
|
t.actime = st.st_atime;
|
|
t.modtime = st.st_mtime;
|
|
utime(_msgfile, &t);
|
|
}
|
|
|
|
// If the message has locked status, make it read-only
|
|
if(__msg->attr.lok())
|
|
chmod(_msgfile, S_STDRD);
|
|
|
|
// Update internal array if the msg is new
|
|
if(__mode & GMSG_NEW) {
|
|
|
|
// Add the msgno to the index
|
|
Msgn->Append(__msg->msgno);
|
|
}
|
|
|
|
GFTRK(0);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::save_hdr(int __mode, gmsg* __msg) {
|
|
|
|
GFTRK("FidoSaveHdr");
|
|
|
|
FidoHdr _hdr;
|
|
save_message(__mode|GMSG_HDR, __msg, _hdr);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::save_msg(int __mode, gmsg* __msg) {
|
|
|
|
GFTRK("FidoSaveMsg");
|
|
|
|
FidoHdr _hdr;
|
|
save_message(__mode|GMSG_HDRTXT, __msg, _hdr);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::del_msg(gmsg* __msg) {
|
|
|
|
GFTRK("FidoDelMsg");
|
|
|
|
FidoHdr _hdr;
|
|
save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::new_msgno(gmsg* __msg) {
|
|
|
|
GFTRK("FidoNewMsgno");
|
|
|
|
uint n = 0;
|
|
Path _buf;
|
|
do {
|
|
__msg->msgno = Msgn->CvtReln(Msgn->Count()) + (++n);
|
|
} while(fexist(build_msgname(_buf, __msg->msgno)));
|
|
|
|
GFTRK(0);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void FidoArea::update_timesread(gmsg* msg) {
|
|
|
|
GFTRK("FidoArea::update_timesread");
|
|
|
|
Path filename;
|
|
build_msgname(filename, msg->msgno);
|
|
|
|
// If it has Lok attribute set, remove READ_ONLY attribute
|
|
// and later add it again
|
|
struct stat st;
|
|
bool readonly = false;
|
|
|
|
if(stat(filename, &st) == 0) {
|
|
readonly = not (st.st_mode & S_IWUSR);
|
|
|
|
if(readonly)
|
|
chmod(filename, S_STDRW);
|
|
}
|
|
|
|
int fh = test_open(filename, O_RDWR|O_BINARY, WideSharemode);
|
|
if(fh != -1) {
|
|
FidoHdr hdr;
|
|
::read(fh, &hdr, sizeof(FidoHdr));
|
|
hdr.timesread = (word)msg->timesread;
|
|
::lseekset(fh, 0);
|
|
::write(fh, &hdr, sizeof(FidoHdr));
|
|
::close(fh);
|
|
}
|
|
|
|
// If file was read_only before, make it again read_only
|
|
if(readonly)
|
|
chmod(filename,S_STDRD);
|
|
|
|
GFTRK(0);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|