1 /*****************************************************************************/
2 /*                                                                           */
3 /*                 (C) Copyright 1994-1997  Alberto Pasquale                 */
4 /*                 Portions (C) Copyright 1999 Per Lundberg                  */
5 /*                                                                           */
6 /*                   A L L   R I G H T S   R E S E R V E D                   */
7 /*                                                                           */
8 /*****************************************************************************/
9 /*                                                                           */
10 /*   How to contact the author:  Alberto Pasquale of 2:332/504@fidonet       */
11 /*                               Viale Verdi 106                             */
12 /*                               41100 Modena                                */
13 /*                               Italy                                       */
14 /*                                                                           */
15 /*****************************************************************************/
16 
17 #include <dirent.h>
18 
19 #ifndef _APGENLIB_HPP_
20 #define _APGENLIB_HPP_
21 
22 #include <limits.h>
23 #include <stddef.h>
24 #include <time.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 #include "defines.h"
29 #include "typedefs.h"
30 #include <smapi/msgapi.h>
31 #include "bbsgenlb.hpp"
32 
33 //#pragma pack (1)
34 
35 typedef int (*CMPF) (const void *, const void *);
36 // Usually the two pointers are double pointers.
37 
38 
39 
40                 // Implementation in MDIR.CPP
41 
42 
43 int mkdirpath (const char *path);
44 
45 // Tries to build path, if not existent.
46 // Returns 0 on path created, 1 on path already existent, -1 on error.
47 
48 
49 int cdd (const char *newdir);
50 
51 // Changes drive and directory.
52 // newdir is a full path specification (can have drive) and
53 // can optionally have trailing backslash.
54 // Returns 0 on success.
55 
56 
57                 // Implementation in DirStack.Cpp
58 
59 // Class to handle Push and Pop of directory.
60 // The drive is also changed whenever appropriate.
61 
62 struct _DirStackEl;
63 
64 class DirStack {
65     private:
66         _DirStackEl *Top;
67     public:
68         DirStack ();
69         ~DirStack ();
70         int Push (const char *newdir);
71                 // newdir is a full path specification (can have drive)
72                 // and can optionally have a terminating backslash.
73                 // Returns 0 on success.
74         int Pop ();
75                 // Returns 0 on success.
76                 // Returns 1 if stack is empty.
77                 // Returns -1 in case of error.
78 };
79 
80                 // Implementation in PARSETXT.CPP
81 
82 
83 #define GN_None    0x0000
84 #define GN_Empty   0x0001       // Return empty string instead of NULL
85 #define GN_SrcFix  0x0002
86 #define GN_BSlash  0x0004       // Assure backslash termination
87 #define GN_UBSlash 0x0008       // Assure no backslash termination
88 #define GN_MkDir   0x0010       // Make the dir path if missing
89 
90 
91 int GetName (const char *&src, char *dest=NULL, int maxlen=INT_MAX, int action=GN_None, BOOL *HasSpace=NULL);
92 
93 /* Copies a "name" from src to dest.
94  *
95  * The "name" can be: - A word (sequence of chars not containing
96  *                      blanks ' ' or quotes '"').
97  *                    - A multi-word between quotes ("word word word").
98  *                      If you need to include the quotes character '"'
99  *                      in the "name", you must write it twice.
100  *                      Tabs are changed to blanks, if found inside
101  *                      the quoted string.
102  *                      E.G. """one""""two""" becomes '"one""two"'.
103  *                           "one two" becomes 'one two'
104  *
105  * src:    A reference to the pointer to the buffer to be analyzed, there
106  *         can be space before the real name.
107  *         On return, the src pointer points to the first non space character
108  *         that follows the "name", unless dest is NULL or action is GN_SrcFix
109  *         (in which case it is not moved).
110  *         It will point to the terminating NULL if no other non-space
111  *         characters are present in the string.
112  *
113  * dest:   A pointer to the buffer where the name will be copied.
114  *         The enclosing quotes (if present) will NOT be copied.
115  *         If no name is found, only the terminating NULL is copied to
116  *         dest, so that it will contain a valid empty string.
117  *         You must assure there is enough space to hold the "name".
118  *         If omitted, nothing is stored but the length of the name
119  *         is evaluated and src not moved.
120  *
121  * maxlen: An optional specification for maximum copy length.
122  *         If used, no more than maxlen bytes will be copied to
123  *         dest, including the terminating NULL (always included).
124  *         When dest==NULL, maxlen is ignored.
125  *
126  * action: Specifies some optional action.
127  *         GN_MkDir is ignored if dest == NULL
128  *
129  * HasSpace: is set TRUE if the name has spaces.
130  *
131  * return: The length of dest, NULL excluded, -1 on error
132  *         When no more "names", returns 0 !
133  */
134 
135 
136 char *GetStatName (const char *&src, int action = GN_None, int *len=NULL, BOOL *HasSpace=NULL);
137 
138 /* Copies a "name" from src to a static buffer  !!! No Multithread !!!
139  *
140  * As GetName, but returns a pointer to a static buffer.
141  * If the name lenght exceeds that of the buffer (PATH_MAX), it is truncated.
142  * If action != GN_Empty, returns NULL on empty string.
143  * The optional len pointer allows to return the length of the string,
144  * NULL excluded.
145  * In case of error (GN_MkDir) return NULL.
146  * !!!!!!! No provision for MultiThreading !!!!!!!!
147  */
148 
149 
150 char *GetAllocName (const char *&src, int action=GN_None, int *len=NULL, BOOL *HasSpace=NULL);
151 
152 /* Copies a "name" from src to an allocated dest.
153  *
154  * The same as GetStatName, but this function allocates space
155  * for dest and returns the resulting pointer.
156  * You can free the allocated memory using operator delete.
157  * Instead you are not allowed to use the free function.
158  * There is no limit on the length of "name".
159  */
160 
161 
162 void strbslash (char *dir);
163 
164 // Assure dir is backslash terminated.
165 // Directory MUST have space for the added character
166 
167 void strubslash (char *dir);
168 
169 // Assure dir is not backslash terminated.
170 // The terminating backslash is overwritten with '\0'.
171 
172 
173 #define GL_None    0x00
174 #define GL_Empty   0x01
175 
176 int GetLn (const char *src, char *dest=NULL, int maxlen=INT_MAX);
177 char *GetStatLn (const char *src, int action=GL_None, int *len=NULL);
178 char *GetAllocLn (const char *src, int action=GL_None, int *len=NULL);
179 
180 // Get rest of line.
181 // Similar to GetName/GetStatName/GetAllocName, but:
182 // - src is not moved
183 // - The whole line is copied to destination, skipping both heading and
184 //   trailing space.
185 // - If the first non space character is a quotes '"', only that string
186 //   is copied (subsequent strings, if present, are ignored).
187 
188 
189 #if defined (__OS2__)
190 
191                 // Implementation in QueryFs.Cpp
192 
193 
194 #define QFS_ERROR         -1    // Usually when unit not ready or undefined
195 #define QFS_OTH            0
196 #define QFS_FAT            1
197 #define QFS_HPFS           2
198 #define QFS_NET_EA         3    // network drive, EAs supported
199 #define QFS_NET_NOEA       4    // network drive, EAs not supported
200 #define QFS_DEV            5    // device
201 #define QFS_CDFS           7    // CDROM
202 #define QFS_NET_DEV        8    // device
203 
204 
205 int QueryFS (const char *filename);
206 
207 // Returns the type of files system where filename resides.
208 // If filename is NULL or does not have a drive specification, current
209 // drive is used.
210 // UNC names are recognized.
211 // If filename specifies a dir or file, this may not exist.
212 
213 
214             // Implementation in System.Cpp
215 
216 void SetPriority (LONG Delta, ULONG Class = PRTYC_NOCHANGE, ULONG Scope = PRTYS_PROCESSTREE, ULONG ID = 0);
217 
218 // Changes priority of process or thread.
219 // Delta: -31 (PRTYD_MINIMUM) -> 31 (PRTYD_MAXIMUM)
220 //        relative to current (0 if class changed also)
221 // Class: PRTYC_IDLETIME, PRTYC_REGULAR, PRTYC_FOREGROUNDSERVER, PRTYC_TIMECRITICAL
222 // Scope: PRTYS_PROCESS (all threads of any process)
223 //        PRTYS_PROCESSTREE (all threads of a process and any descendants)
224 //        PRTYS_THREAD (a single thread of the current process)
225 // Priority of other processes is changed only if they were not set explicitly.
226 // ID: Process or thread identifier
227 
228 
229             // Implementation in OS2_extended_attributes.cpp
230 
231 
232 #define EAGS_NULL            2      // EA is not present
233 #define EAGS_MULTI           1      // EA is MultiValue
234 #define EAGS_OK              0
235 #define EAGS_SMALL_BUFFER   -1
236 #define EAGS_OPEN_ERR       -2
237 #define EAGS_CLOSE_ERR      -3
238 #define EAGS_ERROR         -99
239 
240 
241 struct EAsingle {      // structure for single EA
242     word type;
243     word length;
244     pvoid value;
245 };
246 
247 // EAsingleGet, input: type ignored
248 //                     length is size of value
249 //                     value points to a buffer of length byte size
250 //             output: type is EAT_* (BSEDOS.H)
251 //                     length is length of ea stored in value
252 //                     value contains the EA of length size
253 //
254 // EAsingleSet       : type is EAT_* of value
255 //                     length is length of EA stored in value
256 //                     value contains the EA of size length
257 //
258 //                     If ea==NULL, the EA is deleted
259 //
260 
261 #define EAsingleHeadSize    4
262 
263 
264 int EAsingleGet (pcsz filename,
265                  pcsz eaname,
266                  EAsingle *ea
267                 );        // Returns:
268                           // EAGS_OK: success
269                           // EAGS_SMALL_BUFFER: easize insufficient
270                           // EAGS_OPEN_ERR: cannot open filename
271                           // EAGS_ERROR: other error
272                           // EAsingle.length == 0 means EA not found
273 
274 int EAsingleGet (int handle,      // must be open for read access, deny-write
275                  pcsz eaname,
276                  EAsingle *ea
277                 );
278 
279 
280 int EAsingleSet (pcsz filename,
281                  pcsz eaname,
282                  const EAsingle *ea
283                 );         // EAGS_OK: success
284                            // EAGS_OPEN_ERR: no filename
285                            // EAGS_CLOSE_ERR: closing filename
286                            // EAGS_ERROR: other error
287 
288 
289 int EAsingleSet (int handle,      // must be open for write, deny-both
290                  pcsz eaname,
291                  const EAsingle *ea
292                 );
293 
294                                 // Sets longname as .LONGNAME EA
295 int SetLongName (int handle,    // open for write, deny=both
296                  pcsz longname  // no path
297                 );
298 int SetLongName (pcsz filename, // w path
299                  pcsz longname  // no path
300                 );
301                   // Gets longname from .LONGNAME, empty string if none
302 int GetLongName (int handle,    // open for read, deny-write
303                  psz longname   // PATH_MAX size required
304                 );
305 int GetLongName (pcsz filename, // w path
306                  psz longname   // PATH_MAX size required
307                 );
308 
309 #endif
310 
311 
312             // Implementation in Dates.Cpp
313 
314 time_t dosdatimetounix (ushort date, ushort time);
315 // converts dos date and time to unix timestamp
316 // if date and time == 0, returns 0
317 
318 //time_t DosDatime2Unix (const dosdate_t *ddate, const dostime_t *dtime = NULL);
319 // the dayofweek in *ddate is not relevant.
320 
321 time_t stamptounix (_stamp *stamp);
322 // converts a datime "stamp" to unix timestamp
323 // If stamp is zeroed, returns 0
324 
325 
326 //void unix2dosdatime (time_t utime, ushort *date, ushort *time);
327 // same as unix2stamp but without _stamp structure
328 
329 //void Unix2DosDatime (time_t utime, dosdate_t *ddate = NULL, dostime_t *dtime = NULL);
330 
331 void unix2stamp (time_t utime, _stamp *datime);
332 // converts unix datime to dos stamp
333 // If time == 0, stamp is zeroed
334 
335 #ifdef __NT__
336   void FiletimeUtc2Dosdatime (CONST LPFILETIME lpft, ushort *date, ushort *time);
337 #endif
338 
339 
340 extern byte DateFormat;
341 
342 #define DF_DEFAULT  0xFF        // use DateFormat (no override)
343 
344 // WARNING WARNING: these defines MUST NOT be changed !!!!!!
345 
346 #define DF_USA      0x00        // mm-dd-yy, default for DateFormat
347 #define DF_EURO     0x01        // dd-mm-yy
348 #define DF_JAPAN    0x02        // yy-mm-dd
349 #define DF_SCIENT   0x03        // yymmdd
350 
351 char *unix2dates (time_t utime, char *dates = NULL, byte DFovr = DF_DEFAULT);
352 char *stamp2dates (_stamp *stamp, char *dates = NULL, byte DFovr = DF_DEFAULT);
353 
354 // Convert unix timestamp or "dos" timestamp to a string of 8 or 6 characters.
355 // dates must have enough space. If NULL, static buffer is returned.
356 // Returns pointer to dates.
357 // The format of dates depends on global variable DateFormat.
358 // DFovr overrides DateFormat (necessary for multithreading)
359 
360 time_t dates2unix (char *dates, byte DFovr = DF_DEFAULT);
361 // converts to unix a date in the form specified by DateFormat or DFovr
362 // returns 0 if dates not valid
363 
364 
365         // Implementation in DosFind.Cpp
366 
367 
368 // attributes (input):
369 
370 #define _DFF_A_NORMAL           0x00000000
371 #define _DFF_A_REQ_HIDDEN       0x00000001
372 #define _DFF_A_REQ_SYSTEM       0x00000002
373 #define _DFF_A_REQ_DIRECTORY    0x00000004
374 #define _DFF_A_REQ_ARCHIVED     0x00000008
375 #define _DFF_A_REQ_READONLY     0x00000010
376 #define _DFF_A_MAY_HIDDEN       0x00000020
377 #define _DFF_A_MAY_SYSTEM       0x00000040
378 #define _DFF_A_MAY_DIRECTORY    0x00000080
379 #define _DFF_A_NON_ARCHIVED     0x00000100
380 #define _DFF_A_NON_READONLY     0x00000200
381 
382 #ifdef __OS2__
383   #define _DFF_A_LONGNAME    0x80000000 // get .LONGNAME (FAT, NET w EAs)
384 #endif
385 
386 // _DFF_A_NORMAL: nothing required, SYSTEM,HIDDEN,DIRECTORY prohibited
387 //                READONLY,ARCHIVED permitted
388 
389 
390 // FLFFIND.attrib:
391 //
392 #define _DFF_FILE_ARCHIVED      0x20
393 #define _DFF_FILE_DIRECTORY     0x10
394 #define _DFF_FILE_SYSTEM        0x04
395 #define _DFF_FILE_HIDDEN        0x02
396 #define _DFF_FILE_READONLY      0x01
397 #define _DFF_FILE_NORMAL        0x00
398 
399 
400 struct FILEFINDEABUF;
401 
402 struct FLFFIND {
403 
404   private:
405 #if defined (__OS2__)
406     HDIR DirHandle;
407     ULONG bufsize;
408     ULONG infolevel;
409     union {
410       FILEFINDBUF3  *ffb3;
411       FILEFINDEABUF *ffeab;
412       pvoid         *ff;
413     };
414 #elif defined (__NT__)
415     HANDLE DirHandle;
416     PWIN32_FIND_DATA ff;
417 #elif defined (__linux__) || defined(UNIX) || defined(__CYGWIN32__)
418     dirent *ff;
419 #else   // __DOS__
420     find_t *ff;
421 #endif
422 
423     byte flags;
424     byte required_attributes;
425     byte forbidden_attributes;
426 
427   public:
428     byte attrib;
429     unsigned short cr_time;     // 0 when not available (DOS FAT)
430     unsigned short cr_date;     // 0
431     unsigned short ac_time;     // 0
432     unsigned short ac_date;     // 0
433     unsigned short wr_time;
434     unsigned short wr_date;
435     unsigned long  size;
436     char *name;
437 
438     friend void Dos2My (FLFFIND *);
439     friend void SetAttrMask (unsigned, FLFFIND *);
440     friend unsigned _DosFindFirst (pcsz, unsigned, FLFFIND *);
441     friend unsigned _DosFindNext (FLFFIND *);
442     friend unsigned _DosFindClose (FLFFIND *);
443 
444 };
445 
446 
447 unsigned _DosFindFirst (pcsz path, unsigned attributes, FLFFIND *buffer);
448 unsigned _DosFindNext (FLFFIND *buffer);
449 unsigned _DosFindClose (FLFFIND *buffer);
450 
451 
452 
453         // Implementation in Dir.Cpp
454 
455 
456 struct _dir {
457     byte namelen;
458     BOOL Got;       // Already Got via Get (filename) method
459     long fsize;
460     time_t cdate;   // creation date, 0 under DOS or FAT
461     time_t mdate;   // modification date
462     char fname[1];  // first char of name
463 };
464 
465 struct _dirblk;
466 
467 class DIRcl {
468     private:
469         _dirblk *dirblkhead;
470         _dirblk *curblk;
471         _dir **dirp;
472         uint ntot;
473 
474         void Add (const FLFFIND *f);
475         void Read (const char *path);
476 
477     public:
478         DIRcl (const char *path);
479         ~DIRcl(void);
480         _dir *Get (int first = 0);
481         _dir *Get (const char *filename, BOOL NoDupes = FALSE);
482 };
483 
484 // DIRcl (path): reads the directory pointed to by path, normal files only.
485 // Get (1): returns the first file (alphabetically).
486 // Get (): returns next file.
487 // Get (filename): returns the _dir struct for filename, NULL if none.
488 //      Sets Got=TRUE.
489 //      filename must be a simple filename (no wildcards).
490 //      If NoDupes = TRUE and Got = TRUE, returns NULL.
491 
492 
493             // Implementation in file.cpp
494 
495 struct _ExistStat {
496     time_t ctime;  // HPFS Creation time, 0 under Dos or FAT
497     time_t atime;  // HPFS Last Access time, 0 under Dos or FAT
498     time_t mtime;  // only field valid under Dos or FAT
499     ulong  size;
500 };
501                     // bit-wise for Exist
502 #define _ExFILE_    1      // is a file
503 #define _ExDIR_     2      // is a directory
504 #define _ExWRITE_   4      // has write permission
505 #define _ExDEVICE_  8      // is a character device
506 
507 int Exist (const char *path, _ExistStat *st = NULL);
508 // path can have a trailing backslash or not in the case it's a directory
509 // If st, *st is filled in.
510 
511 BOOL IsShareViol (void);
512 // Returns TRUE if last error was due to a Share violation.
513 
514 int stopen (char *path, int access, int shflag, int mode, int timeout);
515 // sopen with timeout in seconds
516 
517 FILE *_fstopen (const char *filename, const char *mode, int shflag, int timeout);
518 // _fsopen with timeout in seconds
519 
520 BOOL getftime (int handle, time_t *mtime, time_t *ctime = NULL, time_t *atime = NULL);
521 // get file time, 0 if not existent (in FAT and Dos only mtime can be retrieved)
522 // Return TRUE on success.
523 
524 BOOL getftime (const char *filename, time_t *mtime, time_t *ctime = NULL, time_t *atime = NULL);
525 
526 
527                      // bit wise definitions for touchf and copy/movefile
528 #define _CF_notouch_    0x00
529 #define _CF_mtouch_     0x01
530 #define _CF_ctouch_     0x02
531 #define _CF_touchflags_ 0x03
532 
533                                 // for copy/movefile only,
534                                 // ignored by touchf.
535 #define _CF_ExistFail_  0x80    // Fail if destination exists
536 
537                     // return values for copy/movefile
538 
539 #define _CF_OK_             0
540 #define _CF_ERROR_         -1
541 #define _CF_NOSRC_         -2       // source does not exist
542 #define _CF_TOUCHERR_       1
543 #define _CF_SRCNOTDELETED_  2
544 #define _CF_SRCEQDEST_      3
545 #define _CF_DESTEXISTS_     4
546 
547 
548                             // for touchf mtime
549 #define _TF_Auto     1UL    // If ctime not valid -> set mtime
550 
551 #define	FL_TIME_MAX	(time_t)LONG_MAX
552 BOOL touchf (int handle, time_t mtime, time_t ctime = 0, time_t *nowp = NULL);
553 BOOL touchf (pcsz filename, time_t mtime, time_t ctime = 0, time_t *nowp = NULL);
554 BOOL touchf (int handle, byte touchflag = _CF_mtouch_ | _CF_ctouch_, time_t *nowp = NULL);
555 BOOL touchf (pcsz filename, byte touchflag = _CF_mtouch_ | _CF_ctouch_, time_t *nowp = NULL);
556 // Sets filename time to ?time,
557 // handle MUST be open for writing with SH_DENYRW
558 // if ?time is 0 it is not changed,
559 // if ?time is FL_TIME_MAX the current time is used (touch).
560 // If ctime=FL_TIME_MAX is specified and old ctime==0 (FAT, DOS), mtime is touched.
561 // If nowp != NULL, the current time is stored in *nowp.
562 // Returns TRUE on success.
563 // The last 2 forms allow touch only, full by default.
564 
565                 // copyfile & movefile
566 
567 // Dos: _CF_ctouch_ is equivalent to _CF_mtouch.
568 // OS/2: if _CF_ctouch specified and creation datime not available,
569 // _CF_mtouch is done.
570 
571 
572 int copyfile (pcsz sourcefile, pcsz destfile, byte flags = _CF_notouch_);
573 // Copies sourcefile to destfile, optionally resets its datime.
574 // Source and destination cannot contain wildcards.
575 // In the case of source==dest, touch is done anyway
576 
577 int movefile (pcsz sourcefile, pcsz destfile, byte flags = _CF_notouch_);
578 // as copyfile but deletes source (uses rename when possible).
579 
580 
581 // for tunlink, bitmapped
582 #define _TUNLINK_NRM_  0        // normal unlink
583 #define _TUNLINK_ANY_  1        // reset HSR attributes before deleting
584 
585 // for tunlink results
586 
587 #define _TUNLINK_OK_            0
588 #define _TUNLINK_NOTFILE_       1
589 #define _TUNLINK_UNDELETABLE_   2
590 #define _TUNLINK_TIMEOUT_       3
591 #define _TUNLINK_ERROR_        -1
592 
593 int tunlink (const char *path, int timeout, int flags = _TUNLINK_NRM_);
594 // as unlink, but retries for timeout seconds before giving up
595 
596 char *pathnobs (char *path);
597 // Removes trailing backslash from path, if present.
598 // Does not remove from "c:\" or "\".
599 // Returns path.
600 
601 char *pathwbs (char *path);
602 // Appends a trailing backslash to path, if not present.
603 // Does not add to "c:" or "".
604 // Returns path.
605 
606 char *fullpath (char *buffer, const char *path, size_t size = PATH_MAX,
607                 int *len = NULL);
608 // Finds the full path specification for path and stores it in buffer.
609 // Returns buffer on success, NULL on error.
610 // If len != NULL, the length of the returned path is stored.
611 // path can be a file or a directory, with or without a terminating '\'.
612 // The returned fullpath will have a terminating '\' if path has it.
613 // Multiple '.' are supported: "..." means two levels up in the tree.
614 // If path is NULL or points to an empty string, returns the current
615 // working directory.
616 // If buffer is NULL, allocates a buffer of PATH_MAX that can be
617 // deallocated with free.
618 // If size is omitted, PATH_MAX is assumed.
619 // If size is not enough, error is returned.
620 // After error, errno contains:
621 // ENOENT: erroneous path.
622 // ENOMEM: the buffer could not be allocated.
623 // ERANGE: the buffer was too small.
624 
625 
626 BOOL eqpath (const char *p1, const char *p2);
627 // compares p1 to p2 after converting them to full path.
628 // if p1 or p2 is NULL, returns FALSE.
629 // p1 and p2 can have terminating '\' and use multiple '.'.
630 // returns TRUE if they are equal.
631 
632 
633 int fnamecmp (const char *fname, const char *wildname);
634 // compares fname to wildname (? and * accepted, OS/2 way)
635 // return 0 if equal.
636 
637 
638 char *hasext (pcsz filename);
639 // NULL: filename (w possible path) has no extension
640 // !NULL: points to '.' starting the extension
641 // May also be used with dir names, if not terminated by backslash.
642 
643 void remext (char *filename);
644 // removes extension from filename, if available
645 
646 void setext (char *filename, pcsz newext);
647 // substitues current extension (if any) with newext in filename.
648 // If filename does not have an extension, newext is appended.
649 // newext must include the heading '.'
650 
651 void addext (char *filename, pcsz ext);
652 // if filename has no extension, ext is appended; otherwise NOP
653 
654 char *filefrompath (const char *path);
655 // returns a pointer to the filename contained in path.
656 // Points to the terminating '\0' if path terminates with '\'.
657 
658 char *fullname2path (const char *fullname, char *path, const char **fname = NULL);
659 // copies from fullname the path, including terminating '\', to path.
660 // path must be PATH_MAX long.
661 // The optional fname, on return, will point to the filename in fullname.
662 // Returns path.
663 
664 time_t DosFileTime (const char *filename);
665 time_t DosFileTime (int handle);
666 // returns the unix modification time of filename or handle.
667 // Returns 0 if file not found.
668 
669 
670 
671 
672 
673             // Implementation in HardErr.Cpp
674 
675 
676 void HardErrDisable (void);
677 // Disables Hard error pop ups
678 
679 
680             // Implementation in RunCmd.Cpp
681 
682 typedef void (*RCShow) (int code, ...);
683 // called by RunCmd when something must be output.
684 // code values and respective following parameters
685 
686 #define RC_DOING 1  // resolved command line string
687 #define RC_EXIT  2  // int exit code
688 #define RC_EMPTY 3  // none: empty command line error
689 
690 int RunCmd (const char *cmd, RCShow rcs = NULL, const char *prmlst = "", ...);
691 // - Runs the command contained in cmd.
692 // - cmd can be an executable, batch, or any command line command.
693 //   If the command is not found, .COM and .EXE extensions are attempted.
694 //   If cmd cannot be executed directly, the command processor is
695 //   loaded and executed.
696 //   A maximum of 20 tokens is allowed.
697 // - rcs is a function to be called for outputting status
698 // - prmlst is a string containing the list of characters for
699 //   parameter substitution. E.g. prmlst = "ad": tokens %a and %d in
700 //   cmd will be substituted by the first and second string listed after
701 //   prmlst.
702 //   Under OS/2, when the command processor must be invoked,
703 //   each substituted parameter is enclosed in quotes, so that
704 //   special characters (command separator, escape etc.) do not
705 //   cause trouble.
706 // - The total size of the expanded command line must not exceed
707 //   4*PATH_MAX.
708 // - ... there must be as many strings as many characters are contained
709 //   in prmlst (max 10).
710 // - returns the program exit code (errorlevel)
711 //   returns -1 on RC_EMPTY error or (cmd == NULL)
712 // - If you go out of limits with tokens, parameters, expanded length
713 //   nothing bad will happen (all limits checked internally).
714 
715 
716         // implementation in Misc.Cpp
717 
718 
719 char *newcpy (pcsz text);
720 // allocates with new the space for text and copies it therein.
721 // returns the allocated and filled string.
722 
723 char *newncpy (pcsz text, size_t len);
724 // allocates with new and copies (up to) len chars therein, NULL appended.
725 // returns the allocated and filled string.
726 
727 char *strzcpy(char *dest, const char *src, size_t maxlen);
728 // copies src to dest up to a maximum of maxlen-1 characters,
729 // always appends a NULL, returns dest.
730 // maxlen MUST be at least 1.
731 
732 char *fl_stpcpy (char *dest, const char *src);
733 // copies src to dest, returns pointer to terminating null
734 
735 char *stpzcpy (char *dest, const char *src, size_t maxlen);
736 // copies src to dest up to a maximum of maxlen-1 characters,
737 // always appends a NULL, returns pointer to terminating null
738 // maxlen MUST be at least 1.
739 
740 // char *strlcat (char *dest, const char *src, size_t totsize);
741 // Appends src (w terminating null) to dest, returns dest.
742 // If totsize is not sufficient, returns NULL
743 
744 char *stristr (const char *str, const char *substr);
745 // As strstr but case insensitive.
746 
747 char *_fgets (char *buf, size_t n, FILE *fp, int *buflen = NULL);
748 // As standard fgets, but removes trailing \n and skips remainder
749 // if line exceeds n.
750 // Optionally, the string length (\n removed) is stored in buflen.
751 
752 char *StrChg (char *src, char from, char to);
753 // Changes 'from' to 'to' in string src.
754 // Returns src;
755 
756 int _fputs (const char *buf, FILE *fp);
757 // As standard fputs, but adds trailing \n
758 
759 // class Busy to get exclusive access to some resource.
760 // The .BSY flag is named after refname: the path must be valid,
761 // the extension is changed to or appended as .BSY.
762 // No problem if .BSY is not deleted after power failure etc.
763 
764 #define BSY_EXCL  0     // exclusive access
765 #define BSY_SHARE 1     // shared (read) access
766 
767 class Busy {
768     private:
769         int bsyh;
770         char *bsyname;
771     public:
772         Busy (pcsz refname);       // Establish flag name.
773         int Wait (int timeout = 0,  // timeout in seconds.
774                   byte shflg = BSY_EXCL); // sharing flags
775                         // returns 0 on success (bsy created),
776                         // -1 on timeout (bsy already open)
777         ~Busy ();                   // deletes the bsy flag
778 };
779 
780 
781                     // implementation in Pipe.Cpp
782 
783 // class to deal with two pipes (one bidirectional pipe)
784 
785                     // The Pipe must always have enough space
786                     // for the items that are written
787 class Pipe {
788     private:
789         int hpread,     // handle for reading from pipe
790             hpwrite;    // handle for writing into pipe
791     public:
792         Pipe (int hpread, int hpwrite); // handles for read and write
793         ~Pipe ();       // closes the pipe
794         void SendByte (byte b);    // send byte
795         void SendString (const char *text);   // send zero terminated string
796         void SendBlock (const void *data, long count);  // send data
797                                             // Zero length string or block
798                                             // is acceptable.
799         byte WaitByte (byte *b = NULL); // if b != NULL,
800                                         // the returned byte is stored in *b.
801         char *WaitString (char *buffer); // buffer must be long enough
802                                         // returns buffer
803         void *WaitBlock (void *data);    // returns data
804                                         // data must be capable enough
805 };
806 
807 
808                     // Implementation in HeapStor.Cpp
809 
810 struct HeapBlk;
811 
812 typedef void (*HSPF) (void *obj, void *prm);
813 
814 // When the CMPF is used to compare a key to an element of the heap,
815 // the first argument is the pointer to the key,
816 // the second one is the (double) pointer to the element in the heap.
817 
818 
819 class HeapStore {
820     private:
821         size_t blksize;
822         HeapBlk *HeapHead,      // head of HeapBlk list
823                 *HeapTail,      // current HeapBlk, for store
824                 *HeapCur;       // current HeapBlk, for GetFirst/Next
825         uint tailofs,   // offset in current HeapBlk.buf, for store
826              curofs;    // offset in current HeapBlk.buf, for GetFirst/Next
827         uint ni;        // total number of items stored
828         CMPF cmpf;      // last sort function used
829 
830         void **ptr;     // pointer to array of pointers to stored objects
831 
832         void LoadArray ();  // Load array of indexes
833     public:
834         HeapStore (size_t blksize = 1024);
835                                     // blksize MUST be large enough to get
836                                     // an adequate number of entries.
837                                     // Entries > blksize are skipped
838         ~HeapStore ();
839         void Store (const void *p); // object to be stored,
840                                     // total size in first word.
841         uint NTot ();               // Returns number of stored objects
842         void Sort (CMPF cmpf);            // function for sort and compare
843         const void *Retrieve (uint n);   // Get nth item, 0 based
844         const void *Retrieve (const void *key, // key to be searched.
845                               uint *n = NULL, // index for returned item.
846                               CMPF bscmpf = NULL // Optional cmp function
847                               );         // if not specified, the Sort one
848                                         // is used and key must point to
849                                         // a pointer to a full object !
850                         // binary search, NULL if none
851                         // MUST be preceded by Sort
852         const void *LRetrieve (const void *key, // key to be searched.
853                                CMPF cmpf,       // Compare function.
854                                uint *n = NULL   // index for returned item.
855                                );
856                         // Linear search.
857                         // NULL if not found.
858                         // n is in order of storing, not affected
859                         // by Sort.
860         void Process (uint n,       // Item to be modified, 0 based
861                       HSPF hspf,    // function to modify.
862                       void *prm = NULL);    // parameters for hspf.
863                       // the size of the item MUST NOT change !
864         const void *GetFirst ();    // Get first/next item
865         const void *GetNext ();     // in order of storing
866 };
867 
868 
869                 // Implementation in WordStore.Cpp
870 
871 // Class to handle storage and retrieval of list of words in a string.
872 // Words are tokens that do not contain space or are enclosed in
873 // quotes.
874 // The returned words cannot exceed PATH_MAX size.
875 
876 #define     WST_NoClear     0x0001      // Don't clear buffer.
877 
878 
879 class WordStore {
880     private:
881         char *storebuf;             // storage string
882         char retbuf[PATH_MAX];     // Return buffer
883         int  storesize,      // size of storage string
884              usedsize;       // Currently used storage
885         const char *nextp,   // Pointer to next item to return
886                    *lastp;   // Pointer to last item returned
887         int  sflags;
888         void Init ();       // Internal use
889     public:
890         WordStore (char *buf,       // Buffer to be used
891                    int size = 0,    // Size of string: 0   -> No Store.
892                    int flags = 0);  //               : !=0 -> clear buffer.
893         void Clear ();
894         int Store (const char *tok); // returns 0 on success
895         char *GetFirst ();          // NULL when not found
896         char *GetNext ();           // Get Next; at start as GetFirst.
897         void RemoveLast ();         // Removes last returned entry.
898 };
899 
900 
901 int AddWord (const char *src, char *dest, size_t totsize);
902 // Appends src to dest, adding a heading space is dest is not empty.
903 // Returns 1 if src is empty
904 //        -1 if totsize is not sufficient
905 //         0 on success
906 
907 int filelength (int);
908 
909 
910 #endif
911 
912