source: trunk/src/helpers/configsys.c@ 117

Last change on this file since 117 was 117, checked in by umoeller, 24 years ago

Tons of changes.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 40.1 KB
Line 
1
2/*
3 *@@sourcefile configsys.c:
4 * contains helper functions for parsing and changing lines
5 * in the CONFIG.SYS file.
6 *
7 * Some of these used to be in stringh.c. However, that
8 * code was really old and was largely rewritten. Besides,
9 * this fixes some bugs that have popped up in WarpIN.
10 *
11 * Usage: All OS/2 programs.
12 *
13 * Function prefixes (new with V0.81):
14 * -- csys* CONFIG.SYS helper functions.
15 *
16 * Note: Version numbering in this file relates to XWorkplace version
17 * numbering.
18 *
19 *@@added V0.9.7 (2001-01-15) [umoeller]
20 *@@header "helpers\configsys.h"
21 */
22
23/*
24 * Copyright (C) 1997-2001 Ulrich M”ller.
25 * This file is part of the "XWorkplace helpers" source package.
26 * This is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published
28 * by the Free Software Foundation, in version 2 as it comes in the
29 * "COPYING" file of the XWorkplace main distribution.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 */
35
36#define OS2EMX_PLAIN_CHAR
37 // this is needed for "os2emx.h"; if this is defined,
38 // emx will define PSZ as _signed_ char, otherwise
39 // as unsigned char
40
41#define INCL_DOSERRORS
42#include <os2.h>
43
44#include <stdlib.h>
45#include <stdio.h>
46#include <string.h>
47#include <ctype.h>
48#include <math.h>
49
50#include "setup.h" // code generation and debugging options
51
52#include "helpers\dosh.h"
53#include "helpers\stringh.h"
54#include "helpers\xstring.h" // extended string helpers
55
56#include "helpers\configsys.h" // CONFIG.SYS helpers
57
58#pragma hdrstop
59
60/*
61 *@@category: Helpers\Control program helpers\CONFIG.SYS
62 * CONFIG.SYS parsing and manipulation. See configsys.c.
63 */
64
65/*
66 *@@ csysLoadConfigSys:
67 * loads a CONFIG.SYS file.
68 *
69 * If pcszFile is specified, that file is loaded.
70 * If (pcszFile == NULL), this loads the system CONFIG.SYS
71 * file (?:\CONFIG.SYS on the boot drive).
72 *
73 * If this returns NO_ERROR, the contents of the file
74 * are put into ppszContents, which will then point
75 * to a new buffer (which must be free()'d by the caller).
76 *
77 * Note that in that buffer, all \r\n pairs have been
78 * converted to \n (as with fopen()).
79 */
80
81APIRET csysLoadConfigSys(const char *pcszFile, // in: CONFIG.SYS filename or NULL
82 PSZ *ppszContents)
83{
84 APIRET arc = NO_ERROR;
85
86 CHAR szFile[CCHMAXPATH];
87 if (pcszFile == NULL)
88 {
89 sprintf(szFile, "%c:\\CONFIG.SYS", doshQueryBootDrive());
90 pcszFile = szFile;
91 }
92
93 arc = doshLoadTextFile(pcszFile,
94 ppszContents);
95
96 if (arc == NO_ERROR)
97 {
98 // convert all \r\n to \n
99 XSTRING strBuf;
100 xstrInitSet(&strBuf, *ppszContents);
101 xstrConvertLineFormat(&strBuf,
102 TRUE); // to C format
103 *ppszContents = strBuf.psz;
104 }
105
106 return (arc);
107}
108
109/*
110 *@@ csysWriteConfigSys:
111 *
112 *@@added V0.9.7 (2001-01-15) [umoeller]
113 */
114
115APIRET csysWriteConfigSys(const char *pcszFile, // in: CONFIG.SYS filename or NULL
116 const char *pcszContents,
117 PSZ pszBackup)
118{
119 APIRET arc = NO_ERROR;
120
121 XSTRING strBuf;
122
123 CHAR szFile[CCHMAXPATH];
124 if (pcszFile == NULL)
125 {
126 sprintf(szFile, "%c:\\CONFIG.SYS", doshQueryBootDrive());
127 pcszFile = szFile;
128 }
129
130 // convert all \n to \r\n
131 xstrInitCopy(&strBuf, pcszContents, 0);
132 xstrConvertLineFormat(&strBuf,
133 FALSE); // C to OS/2 format
134
135 arc = doshWriteTextFile(pcszFile,
136 strBuf.psz,
137 NULL,
138 pszBackup);
139
140 xstrClear(&strBuf);
141
142 return (arc);
143}
144
145/*
146 *@@ csysFindKey:
147 * finds pcszKey in pcszSearchIn.
148 *
149 * This is similar to strhistr, but this one makes sure the
150 * key is at the beginning of a line. Spaces and tabs before
151 * the key are tolerated.
152 *
153 * Returns NULL if the key was not found. Otherwise this
154 * returns the exact pointer to pcszKey in pcszSearchIn
155 * and puts the address of the first character of the line
156 * (after \r or \n) into ppStartOfLine.
157 *
158 * Used by csysGetParameter/csysSetParameter; useful
159 * for analyzing CONFIG.SYS settings.
160 *
161 * Remarks:
162 *
163 * -- With pcszKey, you can either specify a CONFIG.SYS
164 * key WITH an equals sign (e.g. search for "LIBPATH=")
165 * or the key name only (e.g. "SET SHELL").
166 *
167 * Only in the latter case, this function makes sure
168 * that the search key is complete; e.g. it will not
169 * find "SET SHELLHANDLESINC=" then.
170 *
171 * -- If the line found starts with leading spaces,
172 * *ppStartOfLine will still receive the start of
173 * the line.
174 * For example, if you're searching for "SET PATH"
175 * and the PATH line is
176 *
177 + " SET PATH=C:\os2"
178 *
179 * the first space in the line is written into
180 * *ppStartOfLine.
181 *
182 *@@changed V0.9.0 [umoeller]: fixed bug in that this would also return something if only the first chars matched
183 *@@changed V0.9.0 [umoeller]: fixed bug which could cause character before pszSearchIn to be examined
184 *@@changed V0.9.7 (2001-01-15) [umoeller]: moved this here from stringh.c; renamed from strhFindKey
185 *@@changed V0.9.7 (2001-01-15) [umoeller]: now checking for tabs too
186 *@@changed V0.9.11 (2001-04-25) [umoeller]: this never found lines which had leading spaces, fixed
187 *@@changed V0.9.12 (2001-05-22) [umoeller]: added checks for key termination (SET SHELLHANDLESINC)
188 */
189
190PSZ csysFindKey(const char *pcszSearchIn, // in: text buffer to search
191 const char *pcszKey, // in: key to search for (e.g. "PATH=")
192 PSZ *ppStartOfLine, // out: start of line which contains pcszKey;
193 // ptr can be NULL
194 PBOOL pfIsAllUpperCase) // out: TRUE if key is completely in upper
195 // case; ptr can be NULL
196{
197 const char *p = pcszSearchIn;
198 PSZ pReturn = NULL;
199 ULONG ulKeyLength = strlen(pcszKey);
200
201 BOOL fSearchKeyContainsEquals = (strchr(pcszKey, '=') != 0);
202
203 do
204 {
205 // find the key
206 // (on first loop, p is start of buffer;
207 // on subsequent loops, p is somewhere in bufer,
208 // if we've found the key somewhere else)
209 if (p = strhistr(p, pcszKey))
210 {
211 // make sure the key is at the beginning of a line
212 // by going backwards until we find a char != " "
213 const char *pStartOfLine = p;
214
215 // fixed this V0.9.11 (2001-04-25) [umoeller]
216 while ( (pStartOfLine > pcszSearchIn)
217 && ( (*(pStartOfLine - 1) == ' ')
218 || (*(pStartOfLine - 1) == '\t') // allow tabs too
219 )
220 )
221 --pStartOfLine;
222
223 // if we're at the beginning of a line or
224 // at the beginning of the buffer at all,
225 // let's go on
226 if ( (pStartOfLine == pcszSearchIn) // order fixed V0.9.0, Rdiger Ihle
227 || (*(pStartOfLine - 1) == '\r')
228 || (*(pStartOfLine - 1) == '\n')
229 )
230 {
231 // OK, we're at the start of a line:
232
233 // check the character AFTER the
234 // key if it's a space or '=';
235 // without this check, we'd find
236 // SET SHELL= if caller is really
237 // looking for SET SHELLHANDLESINC=,
238 // but only do this check if the caller
239 // doesn't have '=' in the search string
240 // already
241 // V0.9.12 (2001-05-22) [umoeller]
242 CHAR c = *(p + ulKeyLength);
243 if ( (fSearchKeyContainsEquals)
244 || (c == ' ')
245 || (c == '=')
246 || (c == '\n')
247 || (c == '\r')
248 || (c == '\t')
249 )
250 {
251 // return address of key
252 pReturn = (PSZ)p;
253 // return start of line
254 if (ppStartOfLine)
255 *ppStartOfLine = (PSZ)pStartOfLine;
256
257 // test for all upper case?
258 if (pfIsAllUpperCase)
259 {
260 ULONG ul = 0;
261 *pfIsAllUpperCase = TRUE;
262
263 for (ul = 0;
264 ul < ulKeyLength;
265 ul++)
266 {
267 if (islower(*(p + ul)))
268 {
269 *pfIsAllUpperCase = FALSE;
270 break; // for
271 }
272 }
273 }
274
275 break; // do
276 } // else search next key
277 } // else search next key
278
279 p += ulKeyLength; // search on after this key
280 // now skipping ulKeyLength V0.9.12 (2001-05-22) [umoeller]
281 }
282 else
283 // nothing more found:
284 break;
285 } while ((!pReturn) && (p != NULL) && (p != pcszSearchIn));
286
287 return (pReturn);
288}
289
290/*
291 *@@ csysGetParameter:
292 * searches pcszSearchIn for the key pcszKey and gets
293 * its parameter.
294 *
295 * If found, it returns a pointer to the following
296 * characters in pcszSearchIn and, if pszCopyTo != NULL,
297 * copies the rest of the line to that buffer, of which
298 * cbCopyTo specified the size.
299 *
300 * If the key is not found, NULL is returned.
301 * String search is done by calling csysFindKey.
302 * This is useful for querying CONFIG.SYS settings.
303 *
304 * <B>Example:</B>
305 *
306 * For the CONFIG.SYS line
307 *
308 + PAUSEONERROR=YES
309 *
310 * this would return "YES" if you searched for "PAUSEONERROR=".
311 */
312
313PSZ csysGetParameter(const char *pcszSearchIn, // in: text buffer to search
314 const char *pcszKey, // in: key to search for (e.g. "PATH=")
315 PSZ pszCopyTo, // out: key value
316 ULONG cbCopyTo) // out: sizeof(*pszCopyTo)
317{
318 PSZ p = csysFindKey(pcszSearchIn, pcszKey, NULL, NULL),
319 prc = NULL;
320
321 if (p)
322 {
323 prc = p + strlen(pcszKey);
324 if (pszCopyTo)
325 {
326 // copy to pszCopyTo
327 ULONG cb;
328 PSZ pEOL = strhFindEOL(prc, &cb);
329 if (pEOL)
330 {
331 if (cb > cbCopyTo)
332 cb = cbCopyTo-1;
333 strhncpy0(pszCopyTo, prc, cb);
334 }
335 }
336 }
337
338 return (prc);
339}
340
341/*
342 *@@ csysSetParameter:
343 * searches *ppszBuf for the key pszKey; if found, it
344 * replaces the characters following this key up to the
345 * end of the line with pszParam. If pszKey is not found in
346 * *ppszBuf, it is appended to the file in a new line.
347 *
348 * If any changes are made, *ppszBuf is re-allocated.
349 *
350 * This function searches w/out case sensitivity.
351 *
352 * Returns a pointer to the new parameter inside the
353 * reallocated buffer, or NULL if the key was not found
354 * (and a new item was added).
355 *
356 * NOTE: This assumes that the file uses \n for line
357 * breaks only (not \r\n).
358 *
359 *@@changed V0.9.0 [umoeller]: changed function prototype to PSZ* ppszSearchIn
360 *@@changed V0.9.7 (2001-01-15) [umoeller]: fixed various bugs with the mem buffers
361 */
362
363PSZ csysSetParameter(PSZ* ppszBuf, // in: text buffer to search
364 const char *pcszKey, // in: key to search for (e.g. "PATH=")
365 const char *pcszNewParam, // in: new parameter to set for key
366 BOOL fRespectCase) // in: if TRUE, pszNewParam will
367 // be converted to upper case if the found key is
368 // in upper case also. pszNewParam should be in
369 // lower case if you use this.
370{
371 BOOL fIsAllUpperCase = FALSE;
372 PSZ pKey = csysFindKey(*ppszBuf,
373 pcszKey,
374 NULL,
375 &fIsAllUpperCase),
376 pReturn = NULL;
377 if (pKey)
378 {
379 // key found in file:
380 // ULONG ulOfs;
381
382 // replace existing parameter
383 PSZ pOldParam = pKey + strlen(pcszKey);
384 // pOldParam now has the old parameter, which we
385 // will overwrite now; pOldParam points into *ppszBuf
386
387 if (pOldParam)
388 {
389 ULONG ulOldParamOfs = pOldParam - *ppszBuf;
390
391 PSZ pEOL = strhFindEOL(pOldParam, NULL);
392 // pEOL now has first end-of-line after the parameter
393
394 if (pEOL)
395 {
396 // char count to replace
397 ULONG ulToReplace = pEOL - pOldParam;
398
399 XSTRING strBuf,
400 strReplaceWith;
401
402 // ULONG ulOfs = 0;
403 // PSZ pszOldParamCopy = strhSubstr(pOldParam, pEOL);
404 /* (PSZ)malloc(cbOldParam+1);
405 strncpy(pszOldCopy, pOldParam, cbOldParam);
406 pszOldCopy[cbOldParam] = '\0'; */
407
408 xstrInitSet(&strBuf, *ppszBuf);
409 // this must not be freed!
410
411 xstrInitCopy(&strReplaceWith, pcszNewParam, 0);
412 // check for upper case desired?
413 if ((fRespectCase) && (fIsAllUpperCase))
414 strupr(strReplaceWith.psz);
415
416 xstrrpl(&strBuf,
417 ulOldParamOfs,
418 ulToReplace,
419 strReplaceWith.psz,
420 strReplaceWith.ulLength); // adjusted V0.9.11 (2001-04-22) [umoeller]
421
422 xstrClear(&strReplaceWith);
423
424 /* xstrFindReplaceC(&strBuf,
425 &ulOfs,
426 pszOldParamCopy,
427 pszNewParam); */
428
429 // free(pszOldParamCopy);
430
431 // replace output buffer
432 *ppszBuf = strBuf.psz;
433 // return ptr into that
434 pReturn = *ppszBuf + ulOldParamOfs;
435 }
436 }
437 }
438 else
439 {
440 // key not found: append to end of file
441 XSTRING strContents;
442 xstrInitCopy(&strContents, *ppszBuf, 0);
443 /* PSZ pszNew = (PSZ)malloc(strlen(*ppszBuf)
444 + strlen(pcszKey)
445 + strlen(pszNewParam)
446 + 5); // 2 * \r\n + null byte
447 */
448
449 xstrcatc(&strContents, '\n');
450 xstrcat(&strContents, pcszKey, 0);
451 xstrcat(&strContents, pcszNewParam, 0);
452 xstrcatc(&strContents, '\n');
453 /* sprintf(pszNew, "%s\r\n%s%s\r\n",
454 *ppszBuf, pcszKey, pszNewParam); */
455
456 free(*ppszBuf);
457 *ppszBuf = strContents.psz;
458 }
459
460 return (pReturn);
461}
462
463/*
464 *@@ csysDeleteLine:
465 * this deletes the line in pszSearchIn which starts with
466 * the key pszKey. Returns TRUE if the line was found and
467 * deleted.
468 *
469 * This copies within pszSearchIn.
470 *
471 *@@changed V0.9.7 (2001-01-15) [umoeller]: fixed wrong beginning of line
472 */
473
474BOOL csysDeleteLine(PSZ pszSearchIn, // in: buffer to search
475 PSZ pszKey) // in: key to find
476{
477 BOOL fIsAllUpperCase = FALSE;
478 PSZ pStartOfLine = NULL;
479 PSZ pKey = csysFindKey(pszSearchIn,
480 pszKey,
481 &pStartOfLine,
482 &fIsAllUpperCase);
483 BOOL brc = FALSE;
484
485 if (pKey)
486 {
487 PSZ pEOL = strhFindEOL(pKey, NULL);
488 // pEOL now has first end-of-line after the key
489 if (pEOL)
490 {
491 // go to first character after EOL
492 while ( (*pEOL)
493 && ( (*pEOL == '\n')
494 || (*pEOL == '\r')
495 )
496 )
497 pEOL++;
498
499 // delete line by overwriting it with
500 // the next line
501 strcpy(pStartOfLine,
502 pEOL);
503 }
504 else
505 {
506 // EOL not found: we must be at the end of the file
507 *pKey = '\0';
508 }
509 brc = TRUE;
510 }
511
512 return (brc);
513}
514
515/*
516 *@@ csysManipulate:
517 * makes a single CONFIG.SYS change according to the
518 * CONFIGMANIP which was passed in.
519 *
520 * If the manipulation succeeded, NO_ERROR is returned
521 * and pstrChanged receives a new string describing
522 * what was changed. This can be:
523 *
524 * -- "DLL xxx": deleted a line containing "xxx".
525 *
526 * -- "DLP xxx": deleted part of line.
527 *
528 * -- "NWL xxx": added an all new line.
529 *
530 * -- "NWP xxx": added a new part to an existing line.
531 *
532 * This has been moved here from WarpIN so that C programs
533 * can use these features as well.
534 *
535 * This returns:
536 *
537 * -- NO_ERROR: changed OK, or nothing happened.
538 *
539 * -- CFGERR_NOSEPARATOR: with CFGRPL_ADDLEFT or CFGRPL_ADDRIGHT
540 * modes, no "=" character was found.
541 *
542 * -- CFGERR_MANIPULATING: error in string handling. This should
543 * never happen, and if it does, it's a bug.
544 *
545 * Preconditions:
546 *
547 * -- This assumes that the line breaks are represented
548 * by \n ONLY. If *ppszContents has \r\n line breaks,
549 * they must be converted to pure \n first.
550 */
551
552APIRET csysManipulate(PSZ *ppszContents, // in/out: CONFIG.SYS text (reallocated)
553 PCONFIGMANIP pManip, // in: CONFIG.SYS manipulation instructions
554 PBOOL pfDirty, // out: set to TRUE if something was changed
555 PXSTRING pstrChanged) // out: new string describing changes (must be free'd)
556{
557 APIRET arc = NO_ERROR;
558
559 PSZ pszCommand = 0,
560 pszArgNew = 0;
561 BOOL fIsAllUpperCase = FALSE;
562
563 // The CONFIG.SYS manipulation is a six-step process,
564 // depending on the data in the BSCfgSysManip instance.
565 // This is an outline what needs to be done when;
566 // the implementation follows below.
567
568 // 1) First find out if a line needs to be updated or deleted
569 // or if we only need to write a new line.
570 // This depends on BSCfgSysManip.iReplaceMode.
571 BOOL fFindLine = FALSE;
572
573 // 2) If we need to find a line, find the
574 // line and copy it into pszLineToUpdate.
575 // Set pInsertAt to the original line, if found.
576 // If not found, set fInsertWRTVertical to TRUE.
577 PSZ pInsertAt = 0;
578 // address of that line in original buffer if (fFindLine == TRUE) and
579 // found
580 BOOL fInsertWRTVertical = FALSE;
581 // TRUE means set a new pInsertAt depending on Manip.iVertical;
582 // this is set to TRUE if (fFindLine == FALSE) or line not found
583
584 // 3) If a line needs to be deleted, well, delete it then.
585 PSZ pLineToDelete = 0;
586 // pointer to start of original line (pLineToUpdate);
587 // points to character right after \n
588 PSZ pszDeletedLine = 0;
589 // copy of that line if deleted (this has the stuff between
590 // the EOL chars, not including those)
591
592 // 4) If (fInsertWRTVertical == TRUE), set pInsertAt to a position in
593 // the original buffer, depending on Manip.iVertical.
594
595 // 5) Compose a new line to be inserted at pInsertAt.
596 PSZ pszLineToInsert = 0;
597
598 // 6) Insert that line at pInsertAt.
599
600 /*
601 * Prepare data
602 *
603 */
604
605 // First, check if the new-line string has a "=" char
606 PSZ pSep = strchr(pManip->pszNewLine, '=');
607 if (pSep)
608 {
609 // yes: separate in two strings
610 pszCommand = strhSubstr(pManip->pszNewLine, pSep);
611 pszArgNew = strdup(pSep+1);
612 }
613 else
614 {
615 // no:
616 pszCommand = strdup(pManip->pszNewLine);
617 pszArgNew = 0;
618 }
619
620 /*
621 * GO!!
622 *
623 */
624
625 // **** 1): do we need to search for a line?
626 switch (pManip->iReplaceMode)
627 {
628 case CFGRPL_ADD:
629 fFindLine = FALSE;
630 fInsertWRTVertical = TRUE; // always find new position
631 break;
632
633 case CFGRPL_UNIQUE:
634 case CFGRPL_ADDLEFT:
635 case CFGRPL_ADDRIGHT:
636 case CFGRPL_REMOVELINE:
637 case CFGRPL_REMOVEPART:
638 fFindLine = TRUE; // search line first; this sets
639 // fInsertWRTVertical if not found
640 break;
641 }
642
643 // **** 2): search line, if needed
644 if (fFindLine)
645 {
646 PSZ pKeyFound = 0,
647 // address of key found
648 pStartOfLineWithKeyFound = 0,
649 // pointer to that line in original buffer; NULL if not found
650 pszSearch = *ppszContents;
651
652 do // while ((pManip->pszUniqueSearchString2) && (pszSearch));
653 {
654 pKeyFound = csysFindKey(pszSearch, // CONFIG.SYS text
655 pszCommand, // stuff to search for
656 &pStartOfLineWithKeyFound,
657 &fIsAllUpperCase);
658 // returns beginning of line
659
660 if (!pKeyFound)
661 break;
662 else
663 if (pManip->pszUniqueSearchString2)
664 {
665 // UNIQUE(xxx) mode:
666 // find end of line
667 PSZ pEOL = strhFindEOL(pKeyFound, NULL);
668
669 // find "="
670 PSZ p = strchr(pKeyFound, '=');
671 if (p && p < pEOL)
672 {
673 // find UNIQUE(xxx) substring in line
674 p = strhistr(p, pManip->pszUniqueSearchString2);
675 if (p && p < pEOL)
676 // found: OK, keep pLineToUpdate
677 break;
678 else
679 pKeyFound = NULL; // V0.9.7 (2001-01-15) [umoeller]
680 }
681
682 // else: search on
683 pszSearch = pEOL;
684 }
685 } while ((pManip->pszUniqueSearchString2) && (pszSearch));
686
687 if (pKeyFound)
688 {
689 // line found:
690 pLineToDelete = pStartOfLineWithKeyFound;
691 pInsertAt = pStartOfLineWithKeyFound;
692 }
693 else
694 // line not found:
695 // insert new line then,
696 // respecting the iVertical flag,
697 // unless we are in "remove" mode
698 if ( (pManip->iReplaceMode != CFGRPL_REMOVELINE)
699 && (pManip->iReplaceMode != CFGRPL_REMOVEPART)
700 )
701 fInsertWRTVertical = TRUE;
702 }
703
704 // **** 3): delete original line (OK)
705 if (pLineToDelete)
706 {
707 // pLineToDelete is only != NULL if we searched and found a line above
708 // and points to the character right after \n;
709 // find end of this line
710 PSZ pEOL = strhFindEOL(pLineToDelete, NULL);
711
712 // make a copy of the line to be deleted;
713 // this might be needed later
714 pszDeletedLine = strhSubstr(pLineToDelete, pEOL);
715
716 // pEOL now points to the \n char or the terminating 0 byte;
717 // if not null byte, advance pointer
718 while (*pEOL == '\n')
719 pEOL++;
720
721 // overwrite beginning of line with next line;
722 // the buffers overlap, but this works
723 strcpy(pLineToDelete, pEOL);
724
725 // we've made changes...
726 *pfDirty = TRUE;
727 }
728
729 // **** 4):
730 if (fInsertWRTVertical)
731 {
732 // this is only TRUE if a) we didn't search for a line
733 // or b) we did search, but we didn't find a line
734 // (but never with CFGRPL_REMOVE* mode);
735 // we need to find a new vertical position in CONFIG.SYS then
736 // and set pInsertAt to the beginning of a line (after \n)
737 switch (pManip->iVertical)
738 {
739 case CFGVRT_BOTTOM:
740 // insert at the very bottom (default)
741 pInsertAt = *ppszContents + strlen(*ppszContents);
742 break;
743
744 case CFGVRT_TOP:
745 // insert at the very top
746 pInsertAt = *ppszContents;
747 break;
748
749 case CFGVRT_BEFORE:
750 {
751 // Manip.pszSearchString has the search string
752 // before whose line we must insert
753 PSZ pFound = strhistr(*ppszContents,
754 pManip->pszVerticalSearchString);
755 if (pFound)
756 {
757 // search string found:
758 // find beginning of line
759 while ( (pFound > *ppszContents)
760 && (*pFound != '\n')
761 )
762 pFound--;
763
764 if (pFound > *ppszContents)
765 // we're on the \n char now:
766 pFound++;
767
768 pInsertAt = pFound;
769 }
770 else
771 // search string not found: insert at top then
772 pInsertAt = *ppszContents;
773 break; }
774
775 case CFGVRT_AFTER:
776 {
777 // Manip.pszSearchString has the search string
778 // after whose line we must insert
779 PSZ pFound = strhistr(*ppszContents, pManip->pszVerticalSearchString);
780 if (pFound)
781 {
782 // search string found:
783 // find end of line
784 pInsertAt = strhFindNextLine(pFound, NULL);
785 }
786 else
787 // search string not found: insert at bottom then
788 pInsertAt = *ppszContents + strlen(*ppszContents);
789 break; }
790 }
791 }
792
793 // **** 5): compose new line
794 switch (pManip->iReplaceMode)
795 {
796 case CFGRPL_ADD:
797 case CFGRPL_UNIQUE:
798 // that's easy, the new line is simply given
799 pszLineToInsert = strdup(pManip->pszNewLine);
800 break;
801
802 case CFGRPL_REMOVELINE:
803 // that's easy, just leave pszLineToInsert = 0;
804 break;
805
806 case CFGRPL_REMOVEPART:
807 if (pszDeletedLine)
808 {
809 // parse the line which we removed above,
810 // find the part which was to be removed,
811 // and set pszLineToInsert to the rest of that
812 PSZ pArgToDel = 0;
813 // find the subpart to look for
814 if ((pArgToDel = strhistr(pszDeletedLine, pszArgNew)))
815 {
816 ULONG ulOfs = 0;
817 // pArgToDel now has the position of the
818 // part to be deleted in the old part
819 pszLineToInsert = strdup(pszDeletedLine);
820 strhFindReplace(&pszLineToInsert,
821 &ulOfs,
822 pszArgNew, // search string
823 ""); // replacement string
824 }
825 else
826 // subpart not found:
827 // reinsert the old line
828 pszLineToInsert = strdup(pszDeletedLine);
829 }
830 // else line to be deleted was not found: leave pszLineToInsert = 0;
831 break;
832
833 case CFGRPL_ADDLEFT:
834 case CFGRPL_ADDRIGHT:
835 // add something to the left or right of the existing
836 // argument:
837 // check if we found a line above
838 if (pszDeletedLine)
839 {
840 PSZ pszCommandOld = 0,
841 pszArgOld = 0;
842 // yes: split the existing line
843 pSep = strchr(pszDeletedLine, '=');
844 if (pSep)
845 {
846 // "=" found: separate in two strings
847 pszCommandOld = strhSubstr(pszDeletedLine, pSep);
848 pszArgOld = strdup(pSep+1);
849 }
850 else
851 {
852 // no "=" found: that's strange
853 /* throw(BSConfigExcpt(CFGEXCPT_NOSEPARATOR,
854 strdup(pszDeletedLine))); */
855 arc = CFGERR_NOSEPARATOR;
856 break;
857 }
858
859 if ((pszCommandOld) && (pszArgOld))
860 {
861 // does the new arg exist in old arg already?
862 if (strhistr(pszArgOld, pszArgNew) == 0)
863 {
864 // no: go!
865 ULONG cbCommandOld = strlen(pszCommandOld);
866 ULONG cbArgOld = strlen(pszArgOld);
867 ULONG cbArgNew = strlen(pszArgNew); // created at the very top
868
869 // compose new line
870 pszLineToInsert = (PSZ)malloc(cbCommandOld
871 + cbArgOld
872 + cbArgNew
873 + 5);
874
875 if (pManip->iReplaceMode == CFGRPL_ADDLEFT)
876 // add new arg to the left:
877 sprintf(pszLineToInsert,
878 "%s=%s;%s",
879 pszCommandOld,
880 pszArgNew,
881 pszArgOld);
882 else
883 // add new arg to the right:
884 if (*(pszArgOld + cbArgOld - 1) == ';')
885 // old arg has terminating ";" already:
886 sprintf(pszLineToInsert,
887 "%s=%s%s",
888 pszCommandOld,
889 pszArgOld,
890 pszArgNew);
891 else
892 // we need to append a ";":
893 sprintf(pszLineToInsert,
894 "%s=%s;%s",
895 pszCommandOld,
896 pszArgOld,
897 pszArgNew);
898 } // end if (stristr(pszArgOld, pszArgNew) == 0)
899 else
900 // exists already:
901 // reinsert the line we deleted above
902 pszLineToInsert = strdup(pszDeletedLine);
903
904 free(pszCommandOld);
905 free(pszArgOld);
906 }
907 } // end if (pszDeletedLine)
908 else
909 // line was not found: add a new one then
910 // (the position has been determined above)
911 pszLineToInsert = strdup(pManip->pszNewLine);
912 break;
913 }
914
915 // **** 6): insert new line at pInsertAt
916 if ((pszLineToInsert) && (arc == NO_ERROR))
917 {
918 PSZ pszInsert2 = NULL;
919 PSZ pszNew = NULL;
920 ULONG cbInsert = strlen(pszLineToInsert);
921 BOOL fLineBreakNeeded = FALSE;
922
923 // check if the char before pInsertAt is EOL
924 if (pInsertAt > *ppszContents)
925 if (*(pInsertAt-1) != '\n')
926 fLineBreakNeeded = TRUE;
927
928 if (fLineBreakNeeded)
929 {
930 // not EOL (this might be the case if we're
931 // appending to the very bottom of CONFIG.SYS)
932 pszInsert2 = (PSZ)malloc(cbInsert + 5);
933 // insert an extra line break then
934 *pszInsert2 = '\n';
935 memcpy(pszInsert2 + 1, pszLineToInsert, cbInsert);
936 strcpy(pszInsert2 + cbInsert + 1, "\n");
937 }
938 else
939 {
940 // OK:
941 pszInsert2 = (PSZ)malloc(cbInsert + 3);
942 memcpy(pszInsert2, pszLineToInsert, cbInsert);
943 strcpy(pszInsert2 + cbInsert, "\n");
944 }
945
946 pszNew = strhins(*ppszContents, // source
947 (pInsertAt - *ppszContents), // offset
948 pszInsert2); // insertion string
949 if (pszNew)
950 {
951 free(pszInsert2);
952 free(*ppszContents);
953 *ppszContents = pszNew;
954
955 // we've made changes...
956 *pfDirty = TRUE;
957 }
958 else
959 arc = CFGERR_MANIPULATING;
960 }
961 else
962 if ( (pManip->iReplaceMode != CFGRPL_REMOVELINE)
963 && (pManip->iReplaceMode != CFGRPL_REMOVEPART)
964 )
965 arc = CFGERR_MANIPULATING;
966
967 if (arc == NO_ERROR)
968 {
969 // finally, create log entries for Undo().
970 // This uses the first three characters of the
971 // each log entry to signify what happend:
972 // -- "DLL": deleted line
973 // -- "DLP": deleted part of line
974 // -- "NWL": added an all new line
975 // -- "NWP": added a new part to an existing line
976 // There may be several log entries per manipulator
977 // if a line was deleted and then re-inserted (i.e. updated).
978
979 if (pstrChanged)
980 {
981 switch (pManip->iReplaceMode)
982 {
983 case CFGRPL_UNIQUE:
984 if (pszDeletedLine)
985 {
986 // did we delete a line?
987 xstrcat(pstrChanged, "DLL ", 0);
988 xstrcat(pstrChanged, pszDeletedLine, 0);
989 xstrcatc(pstrChanged, '\n');
990 }
991
992 // no break, because we also added something
993 goto LABEL_CFGRPL_ADD ;
994 // VAC gives us warnings otherwise...
995
996 case CFGRPL_ADD:
997LABEL_CFGRPL_ADD:
998 if (pszLineToInsert)
999 {
1000 // added a line:
1001 xstrcat(pstrChanged, "NWL ", 0);
1002 xstrcat(pstrChanged, pszLineToInsert, 0);
1003 xstrcatc(pstrChanged, '\n');
1004 }
1005 break;
1006
1007 case CFGRPL_ADDLEFT:
1008 case CFGRPL_ADDRIGHT:
1009 if (pszDeletedLine)
1010 {
1011 // a line was found and updated:
1012 // store the new part only
1013 xstrcat(pstrChanged, "NWP ", 0);
1014 xstrcat(pstrChanged, pManip->pszNewLine, 0);
1015 }
1016 else
1017 {
1018 xstrcat(pstrChanged, "NWL ", 0);
1019 xstrcat(pstrChanged, pszLineToInsert, 0);
1020 }
1021 xstrcatc(pstrChanged, '\n');
1022 break;
1023
1024 case CFGRPL_REMOVELINE:
1025 if (pszDeletedLine)
1026 {
1027 // did we delete a line?
1028 xstrcat(pstrChanged, "DLL ", 0);
1029 xstrcat(pstrChanged, pszDeletedLine, 0);
1030 xstrcatc(pstrChanged, '\n');
1031 }
1032 break;
1033
1034 case CFGRPL_REMOVEPART:
1035 if (pszDeletedLine)
1036 {
1037 // did we delete a part?
1038 xstrcat(pstrChanged, "DLP ", 0);
1039 xstrcat(pstrChanged, pManip->pszNewLine, 0);
1040 xstrcatc(pstrChanged, '\n');
1041 }
1042 break;
1043 }
1044 } // end if (pstrChanged)
1045 }
1046
1047 // clean up
1048 if (pszCommand)
1049 free(pszCommand);
1050 if (pszArgNew)
1051 free(pszArgNew);
1052 if (pszDeletedLine)
1053 free(pszDeletedLine);
1054 if (pszLineToInsert)
1055 free(pszLineToInsert);
1056
1057 return (arc);
1058}
1059
1060/* ******************************************************************
1061 *
1062 * Swappath
1063 *
1064 ********************************************************************/
1065
1066extern CHAR G_szSwapperFilename[CCHMAXPATH] = "";
1067
1068/*
1069 *@@ csysParseSwapPath:
1070 *
1071 *@@added V0.9.9 (2001-02-08) [umoeller]
1072 *@@changed V0.9.16 (2001-11-10) [umoeller]: moved to helpers
1073 */
1074
1075BOOL csysParseSwapPath(const char *pcszConfigSys, // in: if NULL, this gets loaded
1076 PSZ pszSwapPath, // out: swapper directory
1077 PULONG pulMinFree, // out: min free
1078 PULONG pulMinSize) // out: min size
1079{
1080 BOOL brc = FALSE;
1081
1082 PSZ pszConfigSysTemp = 0;
1083
1084 if (!pcszConfigSys)
1085 {
1086 // not specified: load it
1087 if (csysLoadConfigSys(NULL, &pszConfigSysTemp) == NO_ERROR)
1088 pcszConfigSys = pszConfigSysTemp;
1089 }
1090
1091 if (pcszConfigSys)
1092 {
1093 // parse SWAPPATH command
1094 PSZ p;
1095 if (p = csysGetParameter(pcszConfigSys, "SWAPPATH=", NULL, 0))
1096 {
1097 CHAR szSwap[CCHMAXPATH];
1098 ULONG ulMinFree = 2048, ulMinSize = 2048;
1099 // int iScanned;
1100 sscanf(p,
1101 "%s %d %d",
1102 &szSwap, &ulMinFree, &ulMinSize);
1103
1104 if (pszSwapPath)
1105 strcpy(pszSwapPath, szSwap);
1106 if (pulMinFree)
1107 *pulMinFree = ulMinFree;
1108 if (pulMinSize)
1109 *pulMinSize = ulMinSize;
1110
1111 if (G_szSwapperFilename[0] == '\0')
1112 {
1113 // first call: copy to global so that the swapper
1114 // monitors will always use the old one, in case
1115 // the user changes this
1116 strcpy(G_szSwapperFilename, szSwap);
1117 if (G_szSwapperFilename[strlen(G_szSwapperFilename)-1] != '\\')
1118 strcat(G_szSwapperFilename, "\\");
1119 strcat(G_szSwapperFilename, "swapper.dat");
1120 }
1121
1122 brc = TRUE;
1123 }
1124 }
1125
1126 if (pszConfigSysTemp)
1127 free(pszConfigSysTemp);
1128
1129 return (brc);
1130}
1131
1132/*
1133 *@@ csysQuerySwapperSize:
1134 * returns the current size of the swap file
1135 * in bytes.
1136 *
1137 *@@added V0.9.9 (2001-02-08) [umoeller]
1138 *@@changed V0.9.16 (2001-11-10) [umoeller]: moved to helpers
1139 */
1140
1141ULONG csysQuerySwapperSize(VOID)
1142{
1143 ULONG ulrc = 0;
1144
1145 if (G_szSwapperFilename[0] == '\0')
1146 {
1147 // first call: compose the path
1148 csysParseSwapPath(NULL,
1149 NULL,
1150 NULL,
1151 NULL);
1152 }
1153
1154 if (G_szSwapperFilename[0])
1155 doshQueryPathSize(G_szSwapperFilename, &ulrc);
1156
1157 return (ulrc);
1158}
1159
1160// testcase
1161
1162/* int main()
1163{
1164 PSZ pszContents = NULL;
1165 if (0 == csysLoadConfigSys(NULL, &pszContents))
1166 {
1167 CHAR szValue[1000];
1168 PSZ pszValue = csysGetParameter(pszContents,
1169 "IFS=",
1170 szValue,
1171 sizeof(szValue));
1172 if (pszValue)
1173 printf("Value: %s", szValue);
1174 }
1175
1176 return (0);
1177} */
Note: See TracBrowser for help on using the repository browser.