// 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 #include #if defined(__WATCOMC__) || defined(__MINGW32__) || defined(_MSC_VER) #include #else #include #endif #include #include #include // ------------------------------------------------------------------ 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); } // ------------------------------------------------------------------