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: gmopcbd1.cpp,v 1.9 2006/05/14 11:45:05 ssianky Exp $
23 //  ------------------------------------------------------------------
24 //  PCBoard msgbase handling.
25 //  ------------------------------------------------------------------
26 
27 #include <gdbgerr.h>
28 #include <gmemdbg.h>
29 #include <gdbgtrk.h>
30 #include <gstrall.h>
31 #include <gutlmisc.h>
32 #include <gmoprot.h>
33 #include <gmopcbd.h>
34 
35 
36 //  ------------------------------------------------------------------
37 
38 PcbData* pcbdata = NULL;
39 PcbWide* pcbwide = NULL;
40 int      pcbdatano = 0;
41 
42 
43 // ------------------------------------------------------------------
44 
PcbExit()45 void PcbExit() {
46 
47   if(pcbwide) {
48     throw_free(pcbwide->lastread);
49     delete pcbwide->user;
50   }
51   throw_xrelease(pcbwide);
52   throw_xrelease(pcbdata);
53 }
54 
55 
56 // ------------------------------------------------------------------
57 
PcbInit(const char * path,int userno)58 void PcbInit(const char* path, int userno) {
59 
60   pcbdata = (PcbData*)throw_calloc(3, sizeof(PcbData));
61   pcbwide = (PcbWide*)throw_calloc(1, sizeof(PcbWide));
62 
63   pcbwide->path = path;
64   pcbwide->userno = userno;
65 
66   pcbwide->fhusr = pcbwide->fhinf = -1;
67 
68   pcbwide->user = new PcbUser;
69   throw_new(pcbwide->user);
70 
71   // Get PCBoard path
72   Path _path;
73   char* _ptr = getenv("PCBOARD");
74   if(_ptr)
75     AddBackslash(strcpy(_path, _ptr));
76   else
77     strcpy(_path, path);
78 
79   Path _cnamespath;
80   *_cnamespath = NUL;
81 
82   // Open PCBOARD.DAT
83   const char* _file = AddPath(_path, "PCBOARD.DAT");
84   gfile fp(_file, "rt", WideSharemode);
85   if (fp.isopen())
86   {
87     // Get some paths/filenames
88     int _line = 0;
89     char _buf[256];
90     fp.SetvBuf(NULL, _IOFBF, 8192);
91     while (fp.Fgets(_buf, sizeof(_buf)))
92     {
93       _line++;
94       if(_line == 28)
95         strxcpy(pcbwide->usersidxpath, strbtrim(_buf), sizeof(Path));
96       else if(_line == 29)
97         strxcpy(pcbwide->users, strbtrim(_buf), sizeof(Path));
98       else if(_line == 31)
99         strxcpy(_cnamespath, strbtrim(_buf), sizeof(Path));
100       else if(_line == 180)
101         strxcpy(pcbwide->usersinf, strbtrim(_buf), sizeof(Path));
102       else if(_line == 208)
103         pcbwide->foreign = atoi(_buf);
104     }
105     fp.Fclose();
106 
107     // Open CNAMES.@@@
108     _file = AddPath(_cnamespath, ".@@@");
109     fp.Fopen(_file, "rb", WideSharemode);
110 
111     // Get board numbers for lastread indexing in the userfiles
112     word _recsize = 0;
113     fp.SetvBuf(NULL, _IOFBF, 8192);
114     fp.Fread(&_recsize, 2);
115     if (_recsize)
116     {
117       PcbConf* _cnames = (PcbConf*)throw_calloc(1, _recsize);
118       int _rec = 0;
119       pcbwide->numareas = (int)((fp.FileLength()-2)/_recsize);
120       pcbwide->confbytelen = (pcbwide->numareas/8) + ((pcbwide->numareas%8) != 0 ? 1 : 0);
121       if(pcbwide->confbytelen < 5)
122         pcbwide->confbytelen = 5;
123       pcbwide->extconflen = pcbwide->confbytelen - 5;
124       pcbwide->lastread = (int32_t*)throw_calloc(pcbwide->numareas, sizeof(int32_t));
125       while (fp.Fread(_cnames, _recsize) == 1)
126       {
127         PcbAdjustArea((uint)_rec, _cnames->msgfile);
128         _rec++;
129       }
130       throw_free(_cnames);
131     }
132     fp.Fclose();
133 
134     const char* _username = WideUsername[0];
135     pcbwide->user->gufh = ::sopen(AddPath(_path, pcbwide->users), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
136     if (pcbwide->user->gufh != -1)
137     {
138       pcbwide->user->fhinf = ::sopen(AddPath(_path, pcbwide->usersinf), O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
139       if(pcbwide->user->fhinf != -1) {
140         ::read(pcbwide->user->fhinf, &pcbwide->usershdr, sizeof(PcbUsersInfHdr));
141         pcbwide->usershdrsize = sizeof(PcbUsersInfHdr) + (pcbwide->usershdr.numofapps*sizeof(PcbUsersInfApp));
142         pcbwide->user->usershdr = &pcbwide->usershdr;
143         pcbwide->user->usershdrsize = pcbwide->usershdrsize;
144         if(pcbwide->userno == -1) {
145           pcbwide->user->find(_username);
146           if(not pcbwide->user->found) {
147             pcbwide->userno = 0;
148             //WideLog->printf("* User \"%s\" not found in %sUSERS.", _username, _path);
149             //pcbwide->user->add(_username);
150             //WideLog->printf("* Now added with user number %u.", pcbwide->user->index);
151           }
152         }
153         close(pcbwide->user->fhinf);
154       }
155       close(pcbwide->user->gufh);
156     }
157     pcbwide->userno = pcbwide->user->index;
158   }
159   else {
160 
161     WideLog->ErrOpen();
162     WideLog->printf("! Configured for PCBoard, but can't find it.");
163     WideLog->printf(": %s.", _file);
164     WideLog->printf("+ Advice: Add or correct the PCBOARDPATH keyword.");
165     WideLog->ErrOSInfo();
166     OpenErrorExit();
167   }
168 }
169 
170 
171 // ------------------------------------------------------------------
172 
open()173 void PcbArea::open() {
174 
175   GFTRK("PcbOpen");
176 
177   isopen++;
178   if(isopen > 2) {
179     WideLog->ErrTest();
180     WideLog->printf("! Trying to open a PCBoard msgbase more than twice.");
181     WideLog->printf(": %s, %s.", echoid(), path());
182     WideLog->printf("+ Info: This indicates a serious bug.");
183     WideLog->printf("+ Advice: Report to the Author immediately.");
184     TestErrorExit();
185   }
186   if(isopen == 1) {
187     if(ispacked()) {
188       isopen--;
189       const char* newpath = Unpack(path());
190       if(newpath == NULL)
191         packed(false);
192       set_real_path(newpath ? newpath : path());
193       isopen++;
194     }
195     PcbWideOpen();
196     data_open();
197     raw_open();
198     scan();
199   }
200 
201   GFTRK(0);
202 }
203 
204 
205 // ------------------------------------------------------------------
206 
save_lastread()207 void PcbArea::save_lastread() {
208 
209   GFTRK("PcbSaveLastread");
210 
211   dword tmplr = Msgn->CvtReln(lastread);
212   if(board() < 40) {
213     // Write lastreads to USERS file
214     lseekset(wide->fhusr, wide->userno*sizeof(PcbUsers));
215     read(wide->fhusr, &wide->usersrec, sizeof(PcbUsers));
216     wide->usersrec.lastmsgread[board()] = L2B(tmplr);
217     lseekset(wide->fhusr, wide->userno*sizeof(PcbUsers));
218     write(wide->fhusr, &wide->usersrec, sizeof(PcbUsers));
219   }
220   else {
221     // Write lastreads to USERS.INF file
222     if(wide->extconflen) {
223       int32_t _offset = (wide->usersrec.usersinfrec-1)*wide->usershdr.totalrecsize;
224       _offset +=     wide->usershdrsize;
225       _offset +=     wide->usershdr.sizeofrec;
226       _offset += 2 * wide->confbytelen;
227       _offset += 3 * wide->extconflen;
228       _offset += sizeof(dword) * (board() - 40);
229       lseekset(wide->fhinf, _offset);
230       write(wide->fhinf, &tmplr, sizeof(dword));
231     }
232   }
233 
234   GFTRK(0);
235 }
236 
237 
238 // ------------------------------------------------------------------
239 
close()240 void PcbArea::close() {
241 
242   GFTRK("PcbClose");
243 
244   if(isopen) {
245     if(isopen == 1) {
246       save_lastread();
247       raw_close();
248       Msgn->Reset();
249       data_close();
250       PcbWideClose();
251       if(ispacked()) {
252         CleanUnpacked(real_path());
253       }
254     }
255     isopen--;
256   }
257   else {
258     WideLog->ErrTest();
259     WideLog->printf("! Trying to close an already closed PCBoard msgbase.");
260     WideLog->printf(": %s, %s.", echoid(), path());
261     WideLog->printf("+ Info: This indicates a potentially serious bug.");
262     WideLog->printf("+ Advice: Report to the Author immediately.");
263     TestErrorExit();
264   }
265 
266   GFTRK(0);
267 }
268 
269 
270 // ------------------------------------------------------------------
271 
suspend()272 void PcbArea::suspend() {
273 
274   GFTRK("PcbSuspend");
275 
276   save_lastread();
277   raw_close();
278   PcbWideClose();
279 
280   GFTRK(0);
281 }
282 
283 
284 // ------------------------------------------------------------------
285 
resume()286 void PcbArea::resume() {
287 
288   GFTRK("PcbResume");
289 
290   PcbWideOpen();
291   raw_open();
292 
293   GFTRK(0);
294 }
295 
296 
297 // ------------------------------------------------------------------
298