1 /*
2  *  SMAPI; Modified Squish MSGAPI
3  *
4  *  Squish MSGAPI0 is copyright 1991 by Scott J. Dudley.  All rights reserved.
5  *  Modifications released to the public domain.
6  *
7  *  Use of this file is subject to the restrictions contain in the Squish
8  *  MSGAPI0 licence agreement.  Please refer to licence.txt for complete
9  *  details of the licencing restrictions.  If you do not find the text
10  *  of this agreement in licence.txt, or if you do not have this file,
11  *  you should contact Scott Dudley at FidoNet node 1:249/106 or Internet
12  *  e-mail Scott.Dudley@f106.n249.z1.fidonet.org.
13  *
14  *  In no event should you proceed to use any of the source files in this
15  *  archive without having accepted the terms of the MSGAPI0 licensing
16  *  agreement, or such other agreement as you are able to reach with the
17  *  author.
18  */
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #ifndef MSGAPI
25 #define MSGAPI
26 
27 //#include "cvtdate.h"
28 #include "progprot.h"
29 #include "stamp.h"
30 #include "typedefs.h"
31 #include "memory.h"
32 #include "ftnaddr.h"
33 
34 
35 #ifdef __BEOS__
36 #include <OS.h>
37 #endif
38 
39 #define MSGAREA_NORMAL  0x00
40 #define MSGAREA_CREATE  0x01
41 #define MSGAREA_CRIFNEC 0x02
42 
43 /* Message & messagebase types (FIDO/OPUS, jam, squish, passthrough, ...) */
44 /*  - types by storage type */
45 #define MSGTYPE_STORAGES    0x0F /* MSGTYPE_SDM | MSGTYPE_SQUISH | MSGTYPE_PASSTHROUGH | MSGTYPE_JAM */
46 #define MSGTYPE_SDM         0x01
47 #define MSGTYPE_SQUISH      0x02
48 #define MSGTYPE_PASSTHROUGH 0x04
49 #define MSGTYPE_JAM         0x08
50 /*  - types by area type (echo, net, ...) */
51 #define MSGTYPE_AREAS       0x1C0  /* MSGTYPE_ECHO | ... */
52 #define MSGTYPE_ECHO        0x80
53 #define MSGTYPE_NOTH        0x0100 /* What is it ?... unknown... */
54 
55 /* Special message number values */
56 #define MSGNUM_CUR      ((dword)-1L)
57 #define MSGNUM_PREV     ((dword)-2L)
58 #define MSGNUM_NEXT     ((dword)-3L)
59 
60 #define MSGNUM_current  MSGNUM_CUR
61 #define MSGNUM_previous MSGNUM_PREV
62 #define MSGNUM_next     MSGNUM_NEXT
63 
64 #define MOPEN_CREATE    0
65 #define MOPEN_READ      1
66 #define MOPEN_WRITE     2
67 #define MOPEN_RW        3
68 
69 #ifdef __UNIX__
70 #define FILEMODE_NETMAIL (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
71 #define FILEMODE_ECHOMAIL (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
72 #else
73 #define FILEMODE_NETMAIL (S_IREAD | S_IWRITE)
74 #define FILEMODE_ECHOMAIL (S_IREAD | S_IWRITE)
75 #endif
76 #define FILEMODE(a) ((a) ? FILEMODE_ECHOMAIL : FILEMODE_NETMAIL)
77 
78 struct _msgapi;
79 struct _msgh;
80 struct _xmsg;
81 //struct _netaddr;
82 
83 typedef struct _msgapi MSGA;
84 typedef struct _msgapi *HAREA;
85 typedef struct _msgh MSGH;
86 typedef struct _msgh *HMSG;
87 typedef struct _xmsg *PXMSG;
88 typedef struct _netaddr NETADDR;
89 typedef NETADDR *PNETADDR;
90 typedef dword UMSGID;
91 
92 #define MSGAPI_VERSION    2
93 #define MSGAPI_SUBVERSION 0x251
94 #define SMAPI_VERSION   "2.5.1"
95 
96 struct _minf
97 {
98     word req_version;
99     word def_zone;
100     word haveshare;  /* filled in by msgapi routines - no need to set this */
101 
102     /* Version 2 Information */
103     word smapi_version;
104     word smapi_subversion;
105 };
106 
107 /*
108  *  The eXtended message structure.  Translation between this structure,
109  *  and the structure used by the individual message base formats, is done
110  *  on-the-fly by the API routines.
111  */
112 
113 typedef struct _xmsg
114 {
115     /* Bitmasks for 'attr' */
116 
117 #define MSGPRIVATE 0x0001
118 #define MSGCRASH   0x0002
119 #define MSGREAD    0x0004
120 #define MSGSENT    0x0008
121 #define MSGFILE    0x0010
122 #define MSGFWD     0x0020     /* is also called intransit flag */
123 #define MSGORPHAN  0x0040
124 #define MSGKILL    0x0080
125 #define MSGLOCAL   0x0100
126 #define MSGHOLD    0x0200
127 #define MSGXX2     0x0400     /* you can use this flag as "Direct" attribute */
128 #define MSGFRQ     0x0800
129 #define MSGRRQ     0x1000
130 #define MSGCPT     0x2000
131 #define MSGARQ     0x4000
132 #define MSGURQ     0x8000
133 #define MSGSCANNED 0x00010000L
134 #define MSGUID     0x00020000L /* xmsg.uid field contains umsgid of msg */
135 #define MSGIMM     0x00040000L /* Use only if msgtype == MSGTYPE_JAM !
136                                   Used to map the Jam "immediate" attribute. */
137 #define MSGLOCKED  0x40000000L /* this seems to be a feature of golded  */
138 #define MSGREADTMR 0x80000000L /* Taimyr */
139 
140 
141     dword attr;
142 #define XMSG_FROM_SIZE  36
143 #define XMSG_TO_SIZE    36
144 #define XMSG_SUBJ_SIZE  72
145 
146     byte from[XMSG_FROM_SIZE];
147     byte to[XMSG_TO_SIZE];
148     byte subj[XMSG_SUBJ_SIZE];
149 
150     NETADDR orig;               /* Origination and destination addresses */
151     NETADDR dest;
152 
153     struct _stamp date_written; /* When user wrote the msg (UTC) */
154     struct _stamp date_arrived; /* When msg arrived on-line (UTC) */
155     sword utc_ofs;              /* Offset from UTC of message writer, in
156                                  * minutes. */
157 
158 #define MAX_REPLY 9            /* Max number of stored replies to one msg */
159 
160     UMSGID replyto;
161     UMSGID replies[MAX_REPLY];
162     dword umsgid;               /* UMSGID of this message, if (attr&MSGUID) */
163     /* This field is only stored on disk -- it  *
164      * is not read into memory.                 */
165 
166     byte __ftsc_date[20];       /* Obsolete date information.  If it weren't
167                                  * for the fact that FTSC standards say that
168                                  * one cannot modify an in-transit message,
169                                  * I'd be VERY tempted to axe this field
170                                  * entirely, and recreate an FTSC-compatible
171                                  * date field using the information in
172                                  * 'date_written' upon export.  Nobody should
173                                  * use this field, except possibly for tossers
174                                  * and scanners.  All others should use one
175                                  * of the two binary datestamps, above. */
176 
177 }
178 XMSG;
179 
180 /* XMSG_SIZE is not sizeof(XMSG) but size of squish message header.
181  * This value used for disk i/o operations with squish messagebase.
182  */
183 #define XMSG_SIZE (94 + XMSG_FROM_SIZE + XMSG_TO_SIZE + XMSG_SUBJ_SIZE)
184 
185 #define xmreply1st replies[0]
186 #define xmreplynext replies[MAX_REPLY-1]
187 #define xmtimesread replies[MAX_REPLY-2]
188 #define xmcost replies[MAX_REPLY-3]
189 #define getHAREA(x) ((HAREA) x)
190 
191 /*
192  *  This is a 'message area handle', as returned by MsgOpenArea(), and
193  *  required by calls to all other message functions.  This structure must
194  *  always be accessed through the API functions, and never modified
195  *  directly.
196  */
197 
198 struct _msgapi
199 {
200 #define MSGAPI_ID   0x0201414DL
201 
202     dword id;                   /* Must always equal MSGAPI_ID */
203 
204     word len;                   /* LENGTH OF THIS STRUCTURE! */
205     word type;
206 
207     dword num_msg;
208     dword cur_msg;
209     dword high_msg;
210     dword high_water;
211 
212     word sz_xmsg;
213 
214     byte locked;                /* Base is locked from use by other tasks */
215     byte isecho;                /* Is this an EchoMail area?              */
216 
217     /* Function pointers for manipulating messages within this area. */
218 
219     struct _apifuncs
220     {
221         sword(_XPENTRY * CloseArea) (HAREA mh);
222         MSGH *(_XPENTRY * OpenMsg) (HAREA mh, word mode, dword n);
223         sword(_XPENTRY * CloseMsg) (MSGH * msgh);
224         dword(_XPENTRY * ReadMsg) (MSGH * msgh, XMSG * msg, dword ofs, dword bytes, byte * text, dword cbyt, byte * ctxt);
225         sword(_XPENTRY * WriteMsg) (MSGH * msgh, word append, XMSG * msg, byte * text, dword textlen, dword totlen, dword clen, byte * ctxt);
226         sword(_XPENTRY * KillMsg) (HAREA mh, dword msgnum);
227         sword(_XPENTRY * Lock) (HAREA mh);
228         sword(_XPENTRY * Unlock) (HAREA mh);
229         sword(_XPENTRY * SetCurPos) (MSGH * msgh, dword pos);
230         dword(_XPENTRY * GetCurPos) (MSGH * msgh);
231         UMSGID(_XPENTRY * MsgnToUid) (HAREA mh, dword msgnum);
232         dword(_XPENTRY * UidToMsgn) (HAREA mh, UMSGID umsgid, word type);
233         dword(_XPENTRY * GetHighWater) (HAREA mh);
234         sword(_XPENTRY * SetHighWater) (HAREA mh, dword hwm);
235         dword(_XPENTRY * GetTextLen) (MSGH * msgh);
236         dword(_XPENTRY * GetCtrlLen) (MSGH * msgh);
237         /* Version 1 Functions */
238         UMSGID (_XPENTRY * GetNextUid)(HAREA harea);
239         /* Version 2 Functions */
240         dword  (_XPENTRY * GetHash)(HAREA harea, dword msgnum);
241     } *api;
242 
243     /*
244      *  Pointer to application-specific data.  API_SQ.C and API_SDM.C use
245      *  this for different things, so again, no applications should muck
246      *  with anything in here.
247      */
248 
249     void *apidata;
250 
251 
252 #ifdef ALTLOCKING
253     char  *lck_path;
254     int    lck_handle;
255 #endif
256 };
257 
258 
259 /*
260  *  This is a 'dummy' message handle.  The other message handlers (contained
261  *  in API_SQ.C and API_SDM.C) will define their own structures, with some
262  *  application-specified variables instead of other[].  Applications should
263  *  not mess with anything inside the _msgh (or MSGH) structure.
264  */
265 
266 #define MSGH_ID  0x0302484DL
267 
268 #if !defined(MSGAPI_HANDLERS) /*&& !defined(NO_MSGH_DEF) */ /* NO_MSGH_DEF unused */
269 struct _msgh
270 {
271     MSGA *sq;
272     dword id;
273 
274     dword bytes_written;
275     dword cur_pos;
276 };
277 #endif
278 
279 /* #include "api_brow.h" */
280 
281 /*
282  *  This variable is modified whenever an error occurs with the MsgXxx()
283  *  functions.  If msgapierr == 0, then no error occurred.
284  */
285 SMAPI_EXT word _stdc msgapierr;
286 
287 extern struct _minf _stdc mi;
288 
289 #define palloc(s)     malloc(s)
290 #define pfree(s)      { if (s) { free(s); s = NULL; } }
291 #define farpalloc(s)  farmalloc(s)
292 #define farpfree(s)   { if (s) { farfree(s); s = NULL; } }
293 
294 /* Constants for 'type' argument of MsgUidToMsgn() */
295 
296 #define UID_EXACT     0x00
297 #define UID_NEXT      0x01
298 #define UID_PREV      0x02
299 
300 /* Values for 'msgapierr', above. */
301 
302 #define MERR_NONE   0           /* No error  */
303 #define MERR_BADH   1           /* Invalid handle passed to function */
304 #define MERR_BADF   2           /* Invalid or corrupted file */
305 #define MERR_NOMEM  3           /* Not enough memory for specified operation */
306 #define MERR_NODS   4           /* Maybe not enough disk space for operation */
307 #define MERR_NOENT  5           /* File/message does not exist */
308 #define MERR_BADA   6           /* Bad argument passed to msgapi function */
309 #define MERR_EOPEN  7           /* Couldn't close - messages still open */
310 #define MERR_NOLOCK 8     /* Base needs to be locked to perform operation   */
311 #define MERR_SHARE  9     /* Resource in use by other process               */
312 #define MERR_EACCES 10    /* Access denied (can't write to read-only, etc)  */
313 #define MERR_BADMSG 11    /* Bad message frame (Squish)                     */
314 #define MERR_TOOBIG 12    /* Too much text/ctrlinfo to fit in frame (Squish)*/
315 #define MERR_BADNAME 13   /* Bad area name or file name */
316 #define MERR_LIMIT  14    /* Messagebase limit is reached */
317 
318 /*
319  *  Now, a set of macros, which call the specified API function.  These
320  *  will map calls for 'MsgOpenMsg()' into 'SquishOpenMsg()', 'SdmOpenMsg()',
321  *  or '<insert fave message type here>'.  Applications should always call
322  *  these macros, instead of trying to call the manipulation functions
323  *  directly.
324  */
325 
326 #define MsgCloseArea(mh)                    (*(mh)->api->CloseArea) (mh)
327 #define MsgOpenMsg(mh,mode,n)               (*(mh)->api->OpenMsg)(mh,mode,n)
328 #define MsgCloseMsg(msgh)                   ((*(((struct _msgh *)msgh)->sq->api->CloseMsg))(msgh))
329 #define MsgReadMsg(msgh,msg,ofs,b,t,cl,ct)  (*(((struct _msgh *)msgh)->sq->api->ReadMsg))(msgh,msg,ofs,b,t,cl,ct)
330 #define MsgWriteMsg(gh,a,m,t,tl,ttl,cl,ct)  (*(((struct _msgh *)gh)->sq->api->WriteMsg))(gh,a,m,t,tl,ttl,cl,ct)
331 #define MsgKillMsg(mh,msgnum)               (*(mh)->api->KillMsg)(mh,msgnum)
332 #define MsgLock(mh)                         (*(mh)->api->Lock)(mh)
333 #define MsgUnlock(mh)                       (*(mh)->api->Unlock)(mh)
334 #define MsgGetCurPos(msgh)                  (*(((struct _msgh *)msgh)->sq->api->GetCurPos))(msgh)
335 #define MsgSetCurPos(msgh,pos)              (*(((struct _msgh *)msgh)->sq->api->SetCurPos))(msgh,pos)
336 #define MsgMsgnToUid(mh,msgn)               (*(mh)->api->MsgnToUid)(mh,msgn)
337 #define MsgUidToMsgn(mh,umsgid,t)           (*(mh)->api->UidToMsgn)(mh,umsgid,t)
338 #define MsgGetHighWater(mh)                 (*(mh)->api->GetHighWater)(mh)
339 #define MsgSetHighWater(mh,n)               (*(mh)->api->SetHighWater)(mh,n)
340 #define MsgGetTextLen(msgh)                 (*(((struct _msgh *)msgh)->sq->api->GetTextLen))(msgh)
341 #define MsgGetCtrlLen(msgh)                 (*(((struct _msgh *)msgh)->sq->api->GetCtrlLen))(msgh)
342 #define MsgGetNextUid(ha)                   (*(ha)->api->GetNextUid)(ha)
343 
344 /*
345  *  These don't actually call any functions, but are macros used to access
346  *  private data inside the _msgh structure.
347  */
348 
349 #define MsgCurMsg(mh)      ((mh)->cur_msg)
350 #define MsgNumMsg(mh)      ((mh)->num_msg)
351 #define MsgHighMsg(mh)     ((mh)->high_msg)
352 #define MsgGetCurMsg(mh)   ((mh)->cur_msg)
353 #define MsgGetNumMsg(mh)   ((mh)->num_msg)
354 #define MsgGetHighMsg(mh)  ((mh)->high_msg)
355 
356 #define MsgStripDebris(str)          StripNasties(str)
357 #define MsgCreateCtrlBuf(t, n, l)    CopyToControlBuf(t, n, l)
358 #define MsgGetCtrlToken(where, what) GetCtrlToken(where, what)
359 #define MsgCvt4D(c, o, d)            ConvertControlInfo(c, o, d)
360 #define MsgCvtCtrlToKludge(ctrl)     CvtCtrlToKludge(ctrl)
361 #define MsgRemoveToken(c, w)         RemoveFromCtrl(c, w)
362 #define MsgGetNumKludges(txt)        NumKludges(txt)
363 #define MsgWrite4D(msg, wf, ctrl)    WriteZPInfo(msg, wf, ctrl)
364 #define MsgInvalidHmsg(mh)           InvalidMsgh(mh)
365 #define MsgInvalidHarea(mh)          InvalidMh(mh)
366 
367 #define MsgCvtFTSCDateToBinary(a, b) ASCII_Date_To_Binary(a,b)
368 
369 const char *  _XPENTRY smapi_cvs_date();
370 SMAPI_EXT sword _XPENTRY MsgOpenApi(struct _minf *minf);
371 SMAPI_EXT sword _XPENTRY MsgCloseApi(void);
372 
373 SMAPI_EXT MSGA *_XPENTRY MsgOpenArea(byte * name, word mode, word type);
374 int MsgDeleteBase(char * name, word type);
375 SMAPI_EXT sword _XPENTRY MsgValidate(word type, byte * name);
376 /* sword _XPENTRY MsgBrowseArea(BROWSE * b);  // used nowhere */
377 
378 sword MSGAPI InvalidMsgh(MSGH * msgh);
379 sword MSGAPI InvalidMh(MSGA * mh);
380 sword MSGAPI InvalidMsg(XMSG * msg);
381 
382 void _XPENTRY SquishSetMaxMsg(MSGA * sq, dword max_msgs, dword skip_msgs, dword age);
383 dword _XPENTRY SquishHash(byte * f);
384 
385 MSGA *MSGAPI SdmOpenArea(byte * name, word mode, word type);
386 sword MSGAPI SdmValidate(byte * name);
387 int SdmDeleteBase(char * name);
388 
389 MSGA *MSGAPI SquishOpenArea(byte * name, word mode, word type);
390 sword MSGAPI SquishValidate(byte * name);
391 int SquishDeleteBase(char * name);
392 
393 MSGA *MSGAPI JamOpenArea(byte * name, word mode, word type);
394 sword MSGAPI JamValidate(byte * name);
395 int JamDeleteBase(char * name);
396 int JamCloseOpenAreas();
397 
398 byte *_XPENTRY CvtCtrlToKludge(byte * ctrl);
399 byte *_XPENTRY GetCtrlToken(byte * where, byte * what);
400 byte *_XPENTRY CopyToControlBuf(byte * txt, byte ** newtext, unsigned *length);
401 SMAPI_EXT void _XPENTRY ConvertControlInfo(byte * ctrl, NETADDR * orig, NETADDR * dest);
402 word _XPENTRY NumKludges(char *txt);
403 void _XPENTRY RemoveFromCtrl(byte * ctrl, byte * what);
404 
405 /* Check version of fidoconfig library
406  * return zero if test passed
407  * test cvs need for DLL version only, using #include <smapi/cvsdate.h>
408   const char *smapidate(){
409   static const
410   #include "cvsdate.h"
411   return cvs_date;
412   }
413   CheckSmapiVersion( ..., smapidate());
414  */
415 int _XPENTRY CheckSmapiVersion( int need_major, int need_minor,
416                                 int need_patch, const char *cvs_date_string );
417 
418 /*  Return MSGAPI error text (string constant).
419  */
420 char * _XPENTRY  strmerr(int msgapierr);
421 
422 
423 #if !defined(__OS2__) && !defined(__FLAT__) && !defined(__UNIX__) && !defined(__NT__)
424 #ifndef farread
425 sword far pascal farread(sword handle, byte far * buf, word len);
426 #endif
427 #ifndef farwrite
428 sword far pascal farwrite(sword handle, byte far * buf, word len);
429 #endif
430 #endif
431 
432 byte *_fast Address(NETADDR * a);
433 byte *StripNasties(byte * str);
434 
435 #if defined(__DOS__)
436 sword far pascal shareloaded(void);
437 #elif defined(__OS2__) || defined(__NT__) || defined(__UNIX__)
438 #define shareloaded() TRUE
439 #else
440 #define shareloaded() FALSE
441 #endif
442 
443 #endif
444 
445 #ifdef __cplusplus
446 }
447 #endif
448 
449