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

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

Lots of changes for icons and refresh.

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