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