1 //  This may look like C code, but it is really -*- C++ -*-
2 
3 //  ------------------------------------------------------------------
4 //  The Goldware Library
5 //  Copyright (C) 1990-1999 Odinn Sorensen
6 //  ------------------------------------------------------------------
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Library General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Library General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Library General Public
18 //  License along with this program; if not, write to the Free
19 //  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 //  MA 02111-1307, USA
21 //  ------------------------------------------------------------------
22 //  $Id: gmofido4.cpp,v 1.5 2006/05/14 11:45:05 ssianky Exp $
23 //  ------------------------------------------------------------------
24 //  Fido/Opus/FTSC (*.MSG) type handling
25 //  ------------------------------------------------------------------
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #if defined(__WATCOMC__) || defined(__MINGW32__) || defined(_MSC_VER)
30 #include <sys/utime.h>
31 #else
32 #include <utime.h>
33 #endif
34 #include <gdbgtrk.h>
35 #include <gstrall.h>
36 #include <gmofido.h>
37 
38 
39 //  ------------------------------------------------------------------
40 
lock()41 void FidoArea::lock() {
42 
43   GFTRK("FidoLock");
44 
45   GFTRK(0);
46 }
47 
48 
49 //  ------------------------------------------------------------------
50 
unlock()51 void FidoArea::unlock() {
52 
53   GFTRK("FidoUnlock");
54 
55   GFTRK(0);
56 }
57 
58 
59 //  ------------------------------------------------------------------
60 
save_message(int __mode,gmsg * __msg,FidoHdr & __hdr)61 void FidoArea::save_message(int __mode, gmsg* __msg, FidoHdr& __hdr) {
62 
63   // Build message filename
64   Path _msgfile;
65   if(__mode & GMSG_NEW) {
66 
67     // Get a new message number
68     uint _cnt = 0;
69     do {
70       __msg->msgno = Msgn->CvtReln(Msgn->Count()) + (++_cnt);
71     } while(fexist(build_msgname(_msgfile, __msg->msgno)));
72 
73     // Never create a new 1.MSG in echo or local areas.
74     if(__msg->msgno == 1) {
75       if(not isnet()) {
76         __msg->msgno = 2;
77         build_msgname(_msgfile, __msg->msgno);
78       }
79     }
80 
81     // Avoid collision with an existing msg
82     while(fexist(_msgfile)) {
83       build_msgname(_msgfile, ++__msg->msgno);
84       // here we should signal that a rescan is needed
85     }
86   }
87   else {
88     build_msgname(_msgfile, __msg->msgno);
89   }
90 
91   // Delete message, if so ordered
92   if(__mode & GMSG_DELETE) {
93     if(remove(_msgfile)) {
94       chmod(_msgfile, S_STDRW);
95       remove(_msgfile);
96     }
97     GFTRK(0);
98     return;
99   }
100 
101   // Get message file attributes
102   struct stat st;
103   if(stat(_msgfile, &st) == 0) {
104     bool readonly = not (st.st_mode & S_IWUSR);
105 
106     // If the file is read-only, make it read-write-able
107     if(readonly)
108       chmod(_msgfile, S_STDRW);
109   }
110 
111   // Determine file open mode
112   int _omode = O_RDWR|O_CREAT|O_BINARY;
113   if(__mode & GMSG_TXT) {
114 
115     // Add truncate, in case a changed msg is shorter
116     _omode |= O_TRUNC;
117   }
118 
119   // Open the message file
120   int _fh = test_open(_msgfile, _omode, WideSharemode, YES);
121 
122   // Get date/time of message file
123   if(not (__mode & GMSG_NEW) and not __msg->attr.upd()) {
124     fstat(_fh, &st);
125   }
126 
127   memset(&__hdr, 0, sizeof(FidoHdr));
128 
129   // Transfer attributes
130   __hdr.attr |= (word)(__msg->attr.pvt() ? FIDO_PVT       : 0);
131   __hdr.attr |= (word)(__msg->attr.cra() ? FIDO_CRASH     : 0);
132   __hdr.attr |= (word)(__msg->attr.rcv() ? FIDO_RECEIVED  : 0);
133   __hdr.attr |= (word)(__msg->attr.snt() ? FIDO_SENT      : 0);
134   __hdr.attr |= (word)(__msg->attr.att() ? FIDO_ATTACH    : 0);
135   __hdr.attr |= (word)(__msg->attr.trs() ? FIDO_TRANSIT   : 0);
136   __hdr.attr |= (word)(__msg->attr.orp() ? FIDO_ORPHAN    : 0);
137   __hdr.attr |= (word)(__msg->attr.k_s() ? FIDO_KILLSENT  : 0);
138   __hdr.attr |= (word)(__msg->attr.loc() ? FIDO_LOCAL     : 0);
139   __hdr.attr |= (word)(__msg->attr.hld() ? FIDO_HOLD      : 0);
140   __hdr.attr |= (word)(__msg->attr.rsv() ? FIDO_RESERVED  : 0);
141   __hdr.attr |= (word)(__msg->attr.frq() ? FIDO_FREQ      : 0);
142   __hdr.attr |= (word)(__msg->attr.rrq() ? FIDO_RETRECREQ : 0);
143   __hdr.attr |= (word)(__msg->attr.rrc() ? FIDO_RETREC    : 0);
144   __hdr.attr |= (word)(__msg->attr.arq() ? FIDO_AUDITREQ  : 0);
145   __hdr.attr |= (word)(__msg->attr.urq() ? FIDO_UPDREQ    : 0);
146 
147   strxcpy(__hdr.to, __msg->to, 36);
148   strxcpy(__hdr.by, __msg->by, 36);
149   strxcpy(__hdr.re, __msg->re, 72);
150 
151   __hdr.ftsc.origzone  = __msg->oorig.zone;
152   __hdr.orignet        = __msg->oorig.net;
153   __hdr.orignode       = __msg->oorig.node;
154   __hdr.ftsc.origpoint = __msg->oorig.point;
155 
156   __hdr.ftsc.destzone  = __msg->odest.zone;
157   __hdr.destnet        = __msg->odest.net;
158   __hdr.destnode       = __msg->odest.node;
159   __hdr.ftsc.destpoint = __msg->odest.point;
160 
161   __hdr.replyto   = (word)__msg->link.to();
162   __hdr.reply1st  = (word)__msg->link.first();
163 
164   __hdr.cost      = (word)__msg->cost;
165   __hdr.timesread = (word)__msg->timesread;
166 
167   if(isopus()) {
168     __hdr.opus.written = TimeToFTime(__msg->written);
169     __hdr.opus.arrived = TimeToFTime(__msg->arrived);
170   }
171 
172   struct tm _tm; ggmtime(&_tm, &__msg->written);
173   sprintf(__hdr.datetime, "%02d %3s %02d  %02d:%02d:%02d",
174       _tm.tm_mday, gmonths[_tm.tm_mon + 1], _tm.tm_year % 100,
175       _tm.tm_hour, _tm.tm_min, _tm.tm_sec
176     );
177 
178   // Write message header
179   write(_fh, &__hdr, sizeof(FidoHdr));
180 
181   // If message text is used
182   if(__mode & GMSG_TXT) {
183 
184     // Write the message text
185     write(_fh, __msg->txt, strlen(__msg->txt)+1);
186   }
187 
188   // Close the message file
189   ::close(_fh);
190 
191   // Reset date/time of message file
192   if(not (__mode & GMSG_NEW) and not __msg->attr.upd()) {
193     struct utimbuf t;
194     t.actime = st.st_atime;
195     t.modtime = st.st_mtime;
196     utime(_msgfile, &t);
197   }
198 
199   // If the message has locked status, make it read-only
200   if(__msg->attr.lok())
201     chmod(_msgfile, S_STDRD);
202 
203   // Update internal array if the msg is new
204   if(__mode & GMSG_NEW) {
205 
206     // Add the msgno to the index
207     Msgn->Append(__msg->msgno);
208   }
209 
210   GFTRK(0);
211 }
212 
213 
214 //  ------------------------------------------------------------------
215 
save_hdr(int __mode,gmsg * __msg)216 void FidoArea::save_hdr(int __mode, gmsg* __msg) {
217 
218   GFTRK("FidoSaveHdr");
219 
220   FidoHdr _hdr;
221   save_message(__mode|GMSG_HDR, __msg, _hdr);
222 }
223 
224 
225 //  ------------------------------------------------------------------
226 
save_msg(int __mode,gmsg * __msg)227 void FidoArea::save_msg(int __mode, gmsg* __msg) {
228 
229   GFTRK("FidoSaveMsg");
230 
231   FidoHdr _hdr;
232   save_message(__mode|GMSG_HDRTXT, __msg, _hdr);
233 }
234 
235 
236 //  ------------------------------------------------------------------
237 
del_msg(gmsg * __msg)238 void FidoArea::del_msg(gmsg* __msg) {
239 
240   GFTRK("FidoDelMsg");
241 
242   FidoHdr _hdr;
243   save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
244 }
245 
246 
247 //  ------------------------------------------------------------------
248 
new_msgno(gmsg * __msg)249 void FidoArea::new_msgno(gmsg* __msg) {
250 
251   GFTRK("FidoNewMsgno");
252 
253   uint n = 0;
254   Path _buf;
255   do {
256     __msg->msgno = Msgn->CvtReln(Msgn->Count()) + (++n);
257   } while(fexist(build_msgname(_buf, __msg->msgno)));
258 
259   GFTRK(0);
260 }
261 
262 
263 //  ------------------------------------------------------------------
264 
update_timesread(gmsg * msg)265 void FidoArea::update_timesread(gmsg* msg) {
266 
267   GFTRK("FidoArea::update_timesread");
268 
269   Path filename;
270   build_msgname(filename, msg->msgno);
271 
272   // If it has Lok attribute set, remove READ_ONLY attribute
273   // and later add it again
274   struct stat st;
275   bool readonly = false;
276 
277   if(stat(filename, &st) == 0) {
278     readonly = not (st.st_mode & S_IWUSR);
279 
280     if(readonly)
281       chmod(filename, S_STDRW);
282   }
283 
284   int fh = test_open(filename, O_RDWR|O_BINARY, WideSharemode);
285   if(fh != -1) {
286     FidoHdr hdr;
287     ::read(fh, &hdr, sizeof(FidoHdr));
288     hdr.timesread = (word)msg->timesread;
289     ::lseekset(fh, 0);
290     ::write(fh, &hdr, sizeof(FidoHdr));
291     ::close(fh);
292   }
293 
294   // If file was read_only before, make it again read_only
295   if(readonly)
296     chmod(filename,S_STDRD);
297 
298   GFTRK(0);
299 }
300 
301 
302 //  ------------------------------------------------------------------
303