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