source: branches/branch-1-0/src/helpers/configsys.c@ 365

Last change on this file since 365 was 196, checked in by umoeller, 23 years ago

Misc fixes.

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