| 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 Mller. | 
|---|
| 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 |  | 
|---|
| 81 | APIRET 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 |  | 
|---|
| 114 | APIRET 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 |  | 
|---|
| 189 | PSZ 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, Rdiger 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 |  | 
|---|
| 312 | PSZ 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 |  | 
|---|
| 362 | PSZ 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 |  | 
|---|
| 473 | BOOL 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 |  | 
|---|
| 553 | APIRET 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: | 
|---|
| 1023 | LABEL_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 |  | 
|---|
| 1092 | extern 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 |  | 
|---|
| 1101 | BOOL 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 |  | 
|---|
| 1167 | ULONG 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 | } */ | 
|---|