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

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

Executable updates, mostly.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 40.2 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 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
551APIRET csysManipulate(PSZ *ppszContents, // in/out: CONFIG.SYS text (reallocated)
552 PCONFIGMANIP pManip, // in: CONFIG.SYS manipulation instructions
553 PBOOL pfDirty, // out: set to TRUE if something was changed
554 PXSTRING pstrChanged) // out: new string describing changes (must be free'd)
555{
556 APIRET arc = NO_ERROR;
557
558 PSZ pszCommand = 0,
559 pszArgNew = 0;
560 BOOL fIsAllUpperCase = FALSE;
561
562 // The CONFIG.SYS manipulation is a six-step process,
563 // depending on the data in the BSCfgSysManip instance.
564 // This is an outline what needs to be done when;
565 // the implementation follows below.
566
567 // 1) First find out if a line needs to be updated or deleted
568 // or if we only need to write a new line.
569 // This depends on BSCfgSysManip.iReplaceMode.
570 BOOL fFindLine = FALSE;
571
572 // 2) If we need to find a line, find the
573 // line and copy it into pszLineToUpdate.
574 // Set pInsertAt to the original line, if found.
575 // If not found, set fInsertWRTVertical to TRUE.
576 PSZ pInsertAt = 0;
577 // address of that line in original buffer if (fFindLine == TRUE) and
578 // found
579 BOOL fInsertWRTVertical = FALSE;
580 // TRUE means set a new pInsertAt depending on Manip.iVertical;
581 // this is set to TRUE if (fFindLine == FALSE) or line not found
582
583 // 3) If a line needs to be deleted, well, delete it then.
584 PSZ pLineToDelete = 0;
585 // pointer to start of original line (pLineToUpdate);
586 // points to character right after \n
587 PSZ pszDeletedLine = 0;
588 // copy of that line if deleted (this has the stuff between
589 // the EOL chars, not including those)
590
591 // 4) If (fInsertWRTVertical == TRUE), set pInsertAt to a position in
592 // the original buffer, depending on Manip.iVertical.
593
594 // 5) Compose a new line to be inserted at pInsertAt.
595 PSZ pszLineToInsert = 0;
596
597 // 6) Insert that line at pInsertAt.
598
599 /*
600 * Prepare data
601 *
602 */
603
604 // First, check if the new-line string has a "=" char
605 PSZ pSep;
606 if (pSep = strchr(pManip->pszNewLine, '='))
607 {
608 // yes: separate in two strings
609 pszCommand = strhSubstr(pManip->pszNewLine, pSep);
610 pszArgNew = strdup(pSep+1);
611 }
612 else
613 {
614 // no:
615 pszCommand = strdup(pManip->pszNewLine);
616 pszArgNew = 0;
617 }
618
619 /*
620 * GO!!
621 *
622 */
623
624 // **** 1): do we need to search for a line?
625 switch (pManip->iReplaceMode)
626 {
627 case CFGRPL_ADD:
628 fFindLine = FALSE;
629 fInsertWRTVertical = TRUE; // always find new position
630 break;
631
632 case CFGRPL_UNIQUE:
633 case CFGRPL_ADDLEFT:
634 case CFGRPL_ADDRIGHT:
635 case CFGRPL_REMOVELINE:
636 case CFGRPL_REMOVEPART:
637 fFindLine = TRUE; // search line first; this sets
638 // fInsertWRTVertical if not found
639 break;
640 }
641
642 // **** 2): search line, if needed
643 if (fFindLine)
644 {
645 PSZ pKeyFound = 0,
646 // address of key found
647 pStartOfLineWithKeyFound = 0,
648 // pointer to that line in original buffer; NULL if not found
649 pszSearch = *ppszContents;
650
651 do // while ((pManip->pszUniqueSearchString2) && (pszSearch));
652 {
653 pKeyFound = csysFindKey(pszSearch, // CONFIG.SYS text
654 pszCommand, // stuff to search for
655 &pStartOfLineWithKeyFound,
656 &fIsAllUpperCase);
657 // returns beginning of line
658
659 if (!pKeyFound)
660 break;
661 else
662 if (pManip->pszUniqueSearchString2)
663 {
664 // UNIQUE(xxx) mode:
665 // find end of line
666 PSZ pEOL = strhFindEOL(pKeyFound, NULL);
667
668 // find "="
669 PSZ p = strchr(pKeyFound, '=');
670 if (p && p < pEOL)
671 {
672 // find UNIQUE(xxx) substring in line
673 p = strhistr(p, pManip->pszUniqueSearchString2);
674 if (p && p < pEOL)
675 // found: OK, keep pLineToUpdate
676 break;
677 else
678 pKeyFound = NULL; // V0.9.7 (2001-01-15) [umoeller]
679 }
680
681 // else: search on
682 pszSearch = pEOL;
683 }
684 } while ((pManip->pszUniqueSearchString2) && (pszSearch));
685
686 if (pKeyFound)
687 {
688 // line found:
689 pLineToDelete = pStartOfLineWithKeyFound;
690 pInsertAt = pStartOfLineWithKeyFound;
691 }
692 else
693 // line not found:
694 // insert new line then,
695 // respecting the iVertical flag,
696 // unless we are in "remove" mode
697 if ( (pManip->iReplaceMode != CFGRPL_REMOVELINE)
698 && (pManip->iReplaceMode != CFGRPL_REMOVEPART)
699 )
700 fInsertWRTVertical = TRUE;
701 }
702
703 // **** 3): delete original line (OK)
704 if (pLineToDelete)
705 {
706 // pLineToDelete is only != NULL if we searched and found a line above
707 // and points to the character right after \n;
708 // find end of this line
709 PSZ pEOL = strhFindEOL(pLineToDelete, NULL);
710
711 // make a copy of the line to be deleted;
712 // this might be needed later
713 pszDeletedLine = strhSubstr(pLineToDelete, pEOL);
714
715 // pEOL now points to the \n char or the terminating 0 byte;
716 // if not null byte, advance pointer
717 while (*pEOL == '\n')
718 pEOL++;
719
720 // overwrite beginning of line with next line;
721 // the buffers overlap, but this works
722 strcpy(pLineToDelete, pEOL);
723
724 // we've made changes...
725 *pfDirty = TRUE;
726 }
727
728 // **** 4):
729 if (fInsertWRTVertical)
730 {
731 // this is only TRUE if a) we didn't search for a line
732 // or b) we did search, but we didn't find a line
733 // (but never with CFGRPL_REMOVE* mode);
734 // we need to find a new vertical position in CONFIG.SYS then
735 // and set pInsertAt to the beginning of a line (after \n)
736 switch (pManip->iVertical)
737 {
738 case CFGVRT_BOTTOM:
739 // insert at the very bottom (default)
740 pInsertAt = *ppszContents + strlen(*ppszContents);
741 break;
742
743 case CFGVRT_TOP:
744 // insert at the very top
745 pInsertAt = *ppszContents;
746 break;
747
748 case CFGVRT_BEFORE:
749 {
750 // Manip.pszSearchString has the search string
751 // before whose line we must insert
752 PSZ pFound;
753 if (pFound = strhistr(*ppszContents,
754 pManip->pszVerticalSearchString))
755 {
756 // search string found:
757 // find beginning of line
758 while ( (pFound > *ppszContents)
759 && (*pFound != '\n')
760 )
761 pFound--;
762
763 if (pFound > *ppszContents)
764 // we're on the \n char now:
765 pFound++;
766
767 pInsertAt = pFound;
768 }
769 else
770 // search string not found: insert at top then
771 pInsertAt = *ppszContents;
772 break; }
773
774 case CFGVRT_AFTER:
775 {
776 // Manip.pszSearchString has the search string
777 // after whose line we must insert
778 PSZ pFound;
779 if (pFound = strhistr(*ppszContents,
780 pManip->pszVerticalSearchString))
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.