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: gmofido2.cpp,v 1.8 2006/05/14 11:45:05 ssianky Exp $
23 //  ------------------------------------------------------------------
24 //  Fido/Opus/FTSC (*.MSG) type handling
25 //  ------------------------------------------------------------------
26 
27 #include <cstdlib>
28 #include <gdbgtrk.h>
29 #include <gdirposx.h>
30 #include <gstrall.h>
31 #include <gmofido.h>
32 
33 
34 //  ------------------------------------------------------------------
35 
raw_scan(bool __scanpm)36 void FidoArea::raw_scan(bool __scanpm) {
37 
38   GFTRK("FidoArea::raw_scan");
39 
40   int _wasopen = isopen;
41   if(not _wasopen) {
42     isopen++;
43     if(ispacked()) {
44       Path tmp;
45       strxcpy(tmp, path(), sizeof(Path));
46       StripBackslash(tmp);
47       const char* newpath = Unpack(tmp);
48       if(newpath == NULL)
49         packed(false);
50       else {
51         strcpy(tmp, newpath);
52         AddBackslash(tmp);
53       }
54       set_real_path(newpath ? tmp : path());
55     }
56   }
57 
58   uint _active = 0;
59   uint32_t* _msgnoptr = NULL;
60   uint32_t* _msgndx = Msgn->tag;
61 
62   gposixdir d(real_path());
63   if(d.ok) {
64     if(WideDebug)
65       WideLog->printf("- %s/*.msg", d.fullpath());
66     const gdirentry *de;
67     while((de = d.nextentry("*.msg", true)) != NULL) {
68       if(WideDebug)
69         WideLog->printf("- %s", de->name.c_str());
70       uint _msgno = (uint)atol(de->name.c_str());
71       if(_msgno) {
72         if((_active % FIDO_SCANBUFSIZE) == 0) {
73           _msgndx = Msgn->Resize(_active+FIDO_SCANBUFSIZE);
74           _msgnoptr = _msgndx + _active;
75         }
76         *_msgnoptr++ = _msgno;
77         _active++;
78       }
79     }
80   }
81   else {
82     if(WideDebug)
83       WideLog->printf("- Invalid path: %s", real_path());
84   }
85 
86   // Sort the index
87   Msgn->SetCount(_active);
88   Msgn->Sort();
89 
90   // Get the lastread msgno
91   word _lastread = 0;
92   int _fh = ::sopen(AddPath(real_path(), wide->fidolastread), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
93   if(_fh != -1) {
94     lseekset(_fh, wide->userno, sizeof(word));
95     read(_fh, &_lastread, sizeof(word));
96     ::close(_fh);
97   }
98 
99   _msgnoptr = _msgndx;
100 
101   uint _count = 1;
102   uint _lastread_reln = 0;
103   uint _firstmsgno = 0;
104   uint _lastmsgno = 0;
105   uint _lastreadfound = 0;
106   FidoHdr _hdr;
107 
108   if(_active) {
109 
110     _firstmsgno = Msgn->at(0);
111     _lastmsgno = Msgn->at(_active-1);
112 
113     while(1) {
114 
115       // Set lastread pointer
116       if((*_msgnoptr >= _lastread) and (_lastread_reln == 0)) {
117         _lastreadfound = *_msgnoptr;
118         _lastread_reln = _count - (*_msgnoptr != _lastread ? 1 : 0);
119         break;
120       }
121       if((++_count) > _active)
122         break;
123       _msgnoptr++;
124     }
125   }
126 
127   // If the exact lastread was not found
128   if(_active and (_lastreadfound != _lastread)) {
129 
130     // Higher than highest or lower than lowest?
131     if(_lastread > _lastmsgno)
132       _lastread_reln = _active;
133     else if(_lastread < _firstmsgno)
134       _lastread_reln = 0;
135   }
136 
137   // Read highwater mark
138   data->highwatermark = 0;
139   if(isecho() and wide->fidohwmarks) {
140     _fh = test_open(AddPath(real_path(), "1.msg"), O_RDONLY|O_BINARY, WideSharemode);
141     if(_fh != -1) {
142       read(_fh, &_hdr, sizeof(FidoHdr));
143       data->highwatermark = _hdr.replyto;
144       ::close(_fh);
145     }
146   }
147 
148   // Update area data
149   Msgn->SetCount(_active);
150   lastread = _lastread_reln;
151   lastreadentry = _lastreadfound;
152 
153   if(__scanpm) {
154     char hdr_by[37];
155     int umax = (WidePersonalmail & PM_ALLNAMES) ? WideUsernames : 1;
156     bool gotpm = false;
157 
158     PMrk->ResetAll();
159 
160     for(uint i = lastread+1; i<=Msgn->Count(); i++) {
161       // Build message filename
162       Path _msgfile;
163       uint msgno = Msgn->CvtReln(i);
164       build_msgname(_msgfile, msgno);
165 
166       // Open the message file
167       int _fh = test_open(_msgfile, O_RDONLY|O_BINARY, WideSharemode);
168       if(_fh >= 0) {
169         read(_fh, &_hdr, sizeof(FidoHdr));
170         strxcpy(hdr_by, _hdr.to, 36);
171 
172         for(int u=0; u<umax; u++) {
173           if(strieql(WideUsername[u], hdr_by)) {
174             gotpm = true;
175             break;
176           }
177         }
178         if(gotpm) {
179           if(not(_hdr.attr & FIDO_RECEIVED))
180             PMrk->Append(msgno);
181 
182           gotpm = false;
183         }
184         ::close(_fh);
185       }
186     }
187   }
188 
189   if(WideDebug) {
190     WideLog->printf("- %s: t:%u, l:%u, fm:%u, hm:%u, lr:%u, u:%u, pm: %i",
191       echoid(),
192       Msgn->Count(),
193       lastread,
194       _firstmsgno,
195       _lastmsgno,
196       _lastread,
197       fidowide->userno,
198       __scanpm ? (int)PMrk->Count() : -1
199     );
200   }
201 
202   if(not _wasopen) {
203     if(ispacked()) {
204       CleanUnpacked(real_path());
205     }
206     isopen--;
207   }
208 
209   GFTRK(0);
210 }
211 
212 
213 //  ------------------------------------------------------------------
214 
scan()215 void FidoArea::scan() {
216 
217   GFTRK("FidoArea::scan");
218 
219   scan_area();
220 
221   GFTRK(0);
222 }
223 
224 
225 //  ------------------------------------------------------------------
226 
scan_area()227 void FidoArea::scan_area() {
228 
229   GFTRK("FidoArea::scan_area");
230 
231   bool was_open = make_bool(data);
232   if(not was_open)
233     data_open();
234   raw_scan(false);
235   if(not was_open)
236     data_close();
237 
238   GFTRK(0);
239 }
240 
241 
242 //  ------------------------------------------------------------------
243 
scan_area_pm()244 void FidoArea::scan_area_pm() {
245 
246   GFTRK("FidoArea::scan_area_pm");
247 
248   bool was_open = make_bool(data);
249   if(not was_open)
250     data_open();
251   raw_scan(true);
252   if(not was_open)
253     data_close();
254 
255   GFTRK(0);
256 }
257 
258 
259 //  ------------------------------------------------------------------
260 
set_highwater_mark()261 void FidoArea::set_highwater_mark() {
262 
263   if(isecho()) {
264     open();
265     gmsg hmsg;
266     hmsg.msgno = 1;
267     if(load_hdr(&hmsg)) {
268       hmsg.link.to_set(Msgn->CvtReln(Msgn->Count()));
269       save_hdr(GMSG_UPDATE, &hmsg);
270     }
271     close();
272   }
273 }
274 
275 
276 //  ------------------------------------------------------------------
277 
reset_highwater_mark()278 void FidoArea::reset_highwater_mark() {
279 
280   if(isecho()) {
281     open();
282     gmsg hmsg;
283     hmsg.msgno = 1;
284     if(load_hdr(&hmsg)) {
285       hmsg.link.to_set(Msgn->CvtReln(1));
286       save_hdr(GMSG_UPDATE, &hmsg);
287     }
288     close();
289   }
290 }
291 
292 
293 //  ------------------------------------------------------------------
294