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