/* *@@sourcefile configsys.c: * contains helper functions for parsing and changing lines * in the CONFIG.SYS file. * * Some of these used to be in stringh.c. However, that * code was really old and was largely rewritten. Besides, * this fixes some bugs that have popped up in WarpIN. * * Usage: All OS/2 programs. * * Function prefixes (new with V0.81): * -- csys* CONFIG.SYS helper functions. * * Note: Version numbering in this file relates to XWorkplace version * numbering. * *@@added V0.9.7 (2001-01-15) [umoeller] *@@header "helpers\configsys.h" */ /* * Copyright (C) 1997-2002 Ulrich M”ller. * This file is part of the "XWorkplace helpers" source package. * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, in version 2 as it comes in the * "COPYING" file of the XWorkplace main distribution. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #define OS2EMX_PLAIN_CHAR // this is needed for "os2emx.h"; if this is defined, // emx will define PSZ as _signed_ char, otherwise // as unsigned char #define INCL_DOSERRORS #include #include #include #include #include #include #include "setup.h" // code generation and debugging options #include "helpers\dosh.h" #include "helpers\stringh.h" #include "helpers\xstring.h" // extended string helpers #include "helpers\configsys.h" // CONFIG.SYS helpers #pragma hdrstop /* *@@category: Helpers\Control program helpers\CONFIG.SYS * CONFIG.SYS parsing and manipulation. See configsys.c. */ /* *@@ csysLoadConfigSys: * loads a CONFIG.SYS file. * * If pcszFile is specified, that file is loaded. * If (pcszFile == NULL), this loads the system CONFIG.SYS * file (?:\CONFIG.SYS on the boot drive). * * If this returns NO_ERROR, the contents of the file * are put into ppszContents, which will then point * to a new buffer (which must be free()'d by the caller). * * Note that in that buffer, all \r\n pairs have been * converted to \n (as with fopen()). */ APIRET csysLoadConfigSys(const char *pcszFile, // in: CONFIG.SYS filename or NULL PSZ *ppszContents) { APIRET arc = NO_ERROR; CHAR szFile[CCHMAXPATH]; if (pcszFile == NULL) { sprintf(szFile, "%c:\\CONFIG.SYS", doshQueryBootDrive()); pcszFile = szFile; } if (!(arc = doshLoadTextFile(pcszFile, ppszContents, NULL))) { // convert all \r\n to \n XSTRING strBuf; xstrInitSet(&strBuf, *ppszContents); xstrConvertLineFormat(&strBuf, TRUE); // to C format *ppszContents = strBuf.psz; } return arc; } /* *@@ csysWriteConfigSys: * *@@added V0.9.7 (2001-01-15) [umoeller] */ APIRET csysWriteConfigSys(const char *pcszFile, // in: CONFIG.SYS filename or NULL const char *pcszContents, PSZ pszBackup) { APIRET arc = NO_ERROR; XSTRING strBuf; CHAR szFile[CCHMAXPATH]; if (pcszFile == NULL) { sprintf(szFile, "%c:\\CONFIG.SYS", doshQueryBootDrive()); pcszFile = szFile; } // convert all \n to \r\n xstrInitCopy(&strBuf, pcszContents, 0); xstrConvertLineFormat(&strBuf, FALSE); // C to OS/2 format arc = doshWriteTextFile(pcszFile, strBuf.psz, NULL, pszBackup); xstrClear(&strBuf); return arc; } /* *@@ csysFindKey: * finds pcszKey in pcszSearchIn. * * This is similar to strhistr, but this one makes sure the * key is at the beginning of a line. Spaces and tabs before * the key are tolerated. * * Returns NULL if the key was not found. Otherwise this * returns the exact pointer to pcszKey in pcszSearchIn * and puts the address of the first character of the line * (after \r or \n) into ppStartOfLine. * * Used by csysGetParameter/csysSetParameter; useful * for analyzing CONFIG.SYS settings. * * Remarks: * * -- With pcszKey, you can either specify a CONFIG.SYS * key WITH an equals sign (e.g. search for "LIBPATH=") * or the key name only (e.g. "SET SHELL"). * * Only in the latter case, this function makes sure * that the search key is complete; e.g. it will not * find "SET SHELLHANDLESINC=" then. * * -- If the line found starts with leading spaces, * *ppStartOfLine will still receive the start of * the line. * For example, if you're searching for "SET PATH" * and the PATH line is * + " SET PATH=C:\os2" * * the first space in the line is written into * *ppStartOfLine. * *@@changed V0.9.0 [umoeller]: fixed bug in that this would also return something if only the first chars matched *@@changed V0.9.0 [umoeller]: fixed bug which could cause character before pszSearchIn to be examined *@@changed V0.9.7 (2001-01-15) [umoeller]: moved this here from stringh.c; renamed from strhFindKey *@@changed V0.9.7 (2001-01-15) [umoeller]: now checking for tabs too *@@changed V0.9.11 (2001-04-25) [umoeller]: this never found lines which had leading spaces, fixed *@@changed V0.9.12 (2001-05-22) [umoeller]: added checks for key termination (SET SHELLHANDLESINC) */ PSZ csysFindKey(const char *pcszSearchIn, // in: text buffer to search const char *pcszKey, // in: key to search for (e.g. "PATH=") PSZ *ppStartOfLine, // out: start of line which contains pcszKey; // ptr can be NULL PBOOL pfIsAllUpperCase) // out: TRUE if key is completely in upper // case; ptr can be NULL { const char *p = pcszSearchIn; PSZ pReturn = NULL; ULONG ulKeyLength = strlen(pcszKey); BOOL fSearchKeyContainsEquals = (strchr(pcszKey, '=') != 0); do { // find the key // (on first loop, p is start of buffer; // on subsequent loops, p is somewhere in bufer, // if we've found the key somewhere else) if (p = strhistr(p, pcszKey)) { // make sure the key is at the beginning of a line // by going backwards until we find a char != " " const char *pStartOfLine = p; // fixed this V0.9.11 (2001-04-25) [umoeller] while ( (pStartOfLine > pcszSearchIn) && ( (*(pStartOfLine - 1) == ' ') || (*(pStartOfLine - 1) == '\t') // allow tabs too ) ) --pStartOfLine; // if we're at the beginning of a line or // at the beginning of the buffer at all, // let's go on if ( (pStartOfLine == pcszSearchIn) // order fixed V0.9.0, Rdiger Ihle || (*(pStartOfLine - 1) == '\r') || (*(pStartOfLine - 1) == '\n') ) { // OK, we're at the start of a line: // check the character AFTER the // key if it's a space or '='; // without this check, we'd find // SET SHELL= if caller is really // looking for SET SHELLHANDLESINC=, // but only do this check if the caller // doesn't have '=' in the search string // already // V0.9.12 (2001-05-22) [umoeller] CHAR c = *(p + ulKeyLength); if ( (fSearchKeyContainsEquals) || (c == ' ') || (c == '=') || (c == '\n') || (c == '\r') || (c == '\t') ) { // return address of key pReturn = (PSZ)p; // return start of line if (ppStartOfLine) *ppStartOfLine = (PSZ)pStartOfLine; // test for all upper case? if (pfIsAllUpperCase) { ULONG ul = 0; *pfIsAllUpperCase = TRUE; for (ul = 0; ul < ulKeyLength; ul++) { if (islower(*(p + ul))) { *pfIsAllUpperCase = FALSE; break; // for } } } break; // do } // else search next key } // else search next key p += ulKeyLength; // search on after this key // now skipping ulKeyLength V0.9.12 (2001-05-22) [umoeller] } else // nothing more found: break; } while ((!pReturn) && (p != NULL) && (p != pcszSearchIn)); return pReturn; } /* *@@ csysGetParameter: * searches pcszSearchIn for the key pcszKey and gets * its parameter. * * If found, it returns a pointer to the following * characters in pcszSearchIn and, if pszCopyTo != NULL, * copies the rest of the line to that buffer, of which * cbCopyTo specified the size. * * If the key is not found, NULL is returned. * String search is done by calling csysFindKey. * This is useful for querying CONFIG.SYS settings. * * Example: * * For the CONFIG.SYS line * + PAUSEONERROR=YES * * this would return "YES" if you searched for "PAUSEONERROR=". */ PSZ csysGetParameter(const char *pcszSearchIn, // in: text buffer to search const char *pcszKey, // in: key to search for (e.g. "PATH=") PSZ pszCopyTo, // out: key value ULONG cbCopyTo) // out: sizeof(*pszCopyTo) { PSZ p, prc = NULL; if (p = csysFindKey(pcszSearchIn, pcszKey, NULL, NULL)) { prc = p + strlen(pcszKey); if (pszCopyTo) { // copy to pszCopyTo ULONG cb; PSZ pEOL; if (pEOL = strhFindEOL(prc, &cb)) { if (cb > cbCopyTo) cb = cbCopyTo-1; strhncpy0(pszCopyTo, prc, cb); } } } return prc; } /* *@@ csysSetParameter: * searches *ppszBuf for the key pszKey; if found, it * replaces the characters following this key up to the * end of the line with pszParam. If pszKey is not found in * *ppszBuf, it is appended to the file in a new line. * * If any changes are made, *ppszBuf is re-allocated. * * This function searches w/out case sensitivity. * * Returns a pointer to the new parameter inside the * reallocated buffer, or NULL if the key was not found * (and a new item was added). * * NOTE: This assumes that the file uses \n for line * breaks only (not \r\n). * *@@changed V0.9.0 [umoeller]: changed function prototype to PSZ* ppszSearchIn *@@changed V0.9.7 (2001-01-15) [umoeller]: fixed various bugs with the mem buffers */ PSZ csysSetParameter(PSZ* ppszBuf, // in: text buffer to search const char *pcszKey, // in: key to search for (e.g. "PATH=") const char *pcszNewParam, // in: new parameter to set for key BOOL fRespectCase) // in: if TRUE, pszNewParam will // be converted to upper case if the found key is // in upper case also. pszNewParam should be in // lower case if you use this. { BOOL fIsAllUpperCase = FALSE; PSZ pKey, pReturn = NULL; if (pKey = csysFindKey(*ppszBuf, pcszKey, NULL, &fIsAllUpperCase)) { // key found in file: // ULONG ulOfs; // replace existing parameter PSZ pOldParam; if (pOldParam = pKey + strlen(pcszKey)) { // pOldParam now has the old parameter, which we // will overwrite now; pOldParam points into *ppszBuf ULONG ulOldParamOfs = pOldParam - *ppszBuf; PSZ pEOL; if (pEOL = strhFindEOL(pOldParam, NULL)) { // pEOL now has first end-of-line after the parameter // char count to replace ULONG ulToReplace = pEOL - pOldParam; XSTRING strBuf, strReplaceWith; // ULONG ulOfs = 0; // PSZ pszOldParamCopy = strhSubstr(pOldParam, pEOL); /* (PSZ)malloc(cbOldParam+1); strncpy(pszOldCopy, pOldParam, cbOldParam); pszOldCopy[cbOldParam] = '\0'; */ xstrInitSet(&strBuf, *ppszBuf); // this must not be freed! xstrInitCopy(&strReplaceWith, pcszNewParam, 0); // check for upper case desired? if ((fRespectCase) && (fIsAllUpperCase)) strupr(strReplaceWith.psz); xstrrpl(&strBuf, ulOldParamOfs, ulToReplace, strReplaceWith.psz, strReplaceWith.ulLength); // adjusted V0.9.11 (2001-04-22) [umoeller] xstrClear(&strReplaceWith); /* xstrFindReplaceC(&strBuf, &ulOfs, pszOldParamCopy, pszNewParam); */ // free(pszOldParamCopy); // replace output buffer *ppszBuf = strBuf.psz; // return ptr into that pReturn = *ppszBuf + ulOldParamOfs; } } } else { // key not found: append to end of file XSTRING strContents; xstrInitCopy(&strContents, *ppszBuf, 0); /* PSZ pszNew = (PSZ)malloc(strlen(*ppszBuf) + strlen(pcszKey) + strlen(pszNewParam) + 5); // 2 * \r\n + null byte */ xstrcatc(&strContents, '\n'); xstrcat(&strContents, pcszKey, 0); xstrcat(&strContents, pcszNewParam, 0); xstrcatc(&strContents, '\n'); /* sprintf(pszNew, "%s\r\n%s%s\r\n", *ppszBuf, pcszKey, pszNewParam); */ free(*ppszBuf); *ppszBuf = strContents.psz; } return pReturn; } /* *@@ csysDeleteLine: * this deletes the line in pszSearchIn which starts with * the key pszKey. Returns TRUE if the line was found and * deleted. * * This copies within pszSearchIn. * *@@changed V0.9.7 (2001-01-15) [umoeller]: fixed wrong beginning of line */ BOOL csysDeleteLine(PSZ pszSearchIn, // in: buffer to search PSZ pszKey) // in: key to find { BOOL fIsAllUpperCase = FALSE; PSZ pStartOfLine = NULL; PSZ pKey; BOOL brc = FALSE; if (pKey = csysFindKey(pszSearchIn, pszKey, &pStartOfLine, &fIsAllUpperCase)) { PSZ pEOL; if (pEOL = strhFindEOL(pKey, NULL)) { // pEOL now has first end-of-line after the key; // go to first character after EOL while ( (*pEOL) && ( (*pEOL == '\n') || (*pEOL == '\r') ) ) pEOL++; // delete line by overwriting it with // the next line strcpy(pStartOfLine, pEOL); } else { // EOL not found: we must be at the end of the file *pKey = '\0'; } brc = TRUE; } return brc; } /* *@@ csysManipulate: * makes a single CONFIG.SYS change according to the * CONFIGMANIP which was passed in. * * If the manipulation succeeded, NO_ERROR is returned * and pstrChanged receives a new string describing * what was changed. This can be: * * -- "DLL xxx": deleted a line containing "xxx". * * -- "DLP xxx": deleted part of line. * * -- "NWL xxx": added an all new line. * * -- "NWP xxx": added a new part to an existing line. * * This has been moved here from WarpIN so that C programs * can use these features as well. * * This returns: * * -- NO_ERROR: changed OK, or nothing happened. * * -- CFGERR_NOSEPARATOR: with CFGRPL_ADDLEFT or CFGRPL_ADDRIGHT * modes, no "=" character was found. * * -- CFGERR_MANIPULATING: error in string handling. This should * never happen, and if it does, it's a bug. * * Preconditions: * * -- This assumes that the line breaks are represented * by \n ONLY. If *ppszContents has \r\n line breaks, * they must be converted to pure \n first. * *@@changed V0.9.18 (2002-03-24) [umoeller]: fixed leftover duplicate ';' chars with CFGRPL_REMOVEPART */ APIRET csysManipulate(PSZ *ppszContents, // in/out: CONFIG.SYS text (reallocated) PCONFIGMANIP pManip, // in: CONFIG.SYS manipulation instructions PBOOL pfDirty, // out: set to TRUE if something was changed PXSTRING pstrChanged) // out: new string describing changes (must be free'd) { APIRET arc = NO_ERROR; PSZ pszCommand = 0, pszArgNew = 0; BOOL fIsAllUpperCase = FALSE; // The CONFIG.SYS manipulation is a six-step process, // depending on the data in the BSCfgSysManip instance. // This is an outline what needs to be done when; // the implementation follows below. // 1) First find out if a line needs to be updated or deleted // or if we only need to write a new line. // This depends on BSCfgSysManip.iReplaceMode. BOOL fFindLine = FALSE; // 2) If we need to find a line, find the // line and copy it into pszLineToUpdate. // Set pInsertAt to the original line, if found. // If not found, set fInsertWRTVertical to TRUE. PSZ pInsertAt = 0; // address of that line in original buffer if (fFindLine == TRUE) and // found BOOL fInsertWRTVertical = FALSE; // TRUE means set a new pInsertAt depending on Manip.iVertical; // this is set to TRUE if (fFindLine == FALSE) or line not found // 3) If a line needs to be deleted, well, delete it then. PSZ pLineToDelete = 0; // pointer to start of original line (pLineToUpdate); // points to character right after \n PSZ pszDeletedLine = 0; // copy of that line if deleted (this has the stuff between // the EOL chars, not including those) // 4) If (fInsertWRTVertical == TRUE), set pInsertAt to a position in // the original buffer, depending on Manip.iVertical. // 5) Compose a new line to be inserted at pInsertAt. PSZ pszLineToInsert = 0; // 6) Insert that line at pInsertAt. /* * Prepare data * */ // First, check if the new-line string has a "=" char PSZ pSep; if (pSep = strchr(pManip->pszNewLine, '=')) { // yes: separate in two strings pszCommand = strhSubstr(pManip->pszNewLine, pSep); pszArgNew = strdup(pSep+1); } else { // no: pszCommand = strdup(pManip->pszNewLine); pszArgNew = 0; } /* * GO!! * */ // **** 1): do we need to search for a line? switch (pManip->iReplaceMode) { case CFGRPL_ADD: fFindLine = FALSE; fInsertWRTVertical = TRUE; // always find new position break; case CFGRPL_UNIQUE: case CFGRPL_ADDLEFT: case CFGRPL_ADDRIGHT: case CFGRPL_REMOVELINE: case CFGRPL_REMOVEPART: fFindLine = TRUE; // search line first; this sets // fInsertWRTVertical if not found break; } // **** 2): search line, if needed if (fFindLine) { PSZ pKeyFound = 0, // address of key found pStartOfLineWithKeyFound = 0, // pointer to that line in original buffer; NULL if not found pszSearch = *ppszContents; do // while ((pManip->pszUniqueSearchString2) && (pszSearch)); { pKeyFound = csysFindKey(pszSearch, // CONFIG.SYS text pszCommand, // stuff to search for &pStartOfLineWithKeyFound, &fIsAllUpperCase); // returns beginning of line if (!pKeyFound) break; else if (pManip->pszUniqueSearchString2) { // UNIQUE(xxx) mode: // find end of line PSZ pEOL = strhFindEOL(pKeyFound, NULL); // find "=" PSZ p = strchr(pKeyFound, '='); if (p && p < pEOL) { // find UNIQUE(xxx) substring in line p = strhistr(p, pManip->pszUniqueSearchString2); if (p && p < pEOL) // found: OK, keep pLineToUpdate break; else pKeyFound = NULL; // V0.9.7 (2001-01-15) [umoeller] } // else: search on pszSearch = pEOL; } } while ((pManip->pszUniqueSearchString2) && (pszSearch)); if (pKeyFound) { // line found: pLineToDelete = pStartOfLineWithKeyFound; pInsertAt = pStartOfLineWithKeyFound; } else // line not found: // insert new line then, // respecting the iVertical flag, // unless we are in "remove" mode if ( (pManip->iReplaceMode != CFGRPL_REMOVELINE) && (pManip->iReplaceMode != CFGRPL_REMOVEPART) ) fInsertWRTVertical = TRUE; } // **** 3): delete original line (OK) if (pLineToDelete) { // pLineToDelete is only != NULL if we searched and found a line above // and points to the character right after \n; // find end of this line PSZ pEOL = strhFindEOL(pLineToDelete, NULL); // make a copy of the line to be deleted; // this might be needed later pszDeletedLine = strhSubstr(pLineToDelete, pEOL); // pEOL now points to the \n char or the terminating 0 byte; // if not null byte, advance pointer while (*pEOL == '\n') pEOL++; // overwrite beginning of line with next line; // the buffers overlap, but this works strcpy(pLineToDelete, pEOL); // we've made changes... *pfDirty = TRUE; } // **** 4): if (fInsertWRTVertical) { // this is only TRUE if a) we didn't search for a line // or b) we did search, but we didn't find a line // (but never with CFGRPL_REMOVE* mode); // we need to find a new vertical position in CONFIG.SYS then // and set pInsertAt to the beginning of a line (after \n) switch (pManip->iVertical) { case CFGVRT_BOTTOM: // insert at the very bottom (default) pInsertAt = *ppszContents + strlen(*ppszContents); break; case CFGVRT_TOP: // insert at the very top pInsertAt = *ppszContents; break; case CFGVRT_BEFORE: { // Manip.pszSearchString has the search string // before whose line we must insert PSZ pFound; if (pFound = strhistr(*ppszContents, pManip->pszVerticalSearchString)) { // search string found: // find beginning of line while ( (pFound > *ppszContents) && (*pFound != '\n') ) pFound--; if (pFound > *ppszContents) // we're on the \n char now: pFound++; pInsertAt = pFound; } else // search string not found: insert at top then pInsertAt = *ppszContents; break; } case CFGVRT_AFTER: { // Manip.pszSearchString has the search string // after whose line we must insert PSZ pFound; if (pFound = strhistr(*ppszContents, pManip->pszVerticalSearchString)) { // search string found: // find end of line pInsertAt = strhFindNextLine(pFound, NULL); } else // search string not found: insert at bottom then pInsertAt = *ppszContents + strlen(*ppszContents); break; } } } // **** 5): compose new line switch (pManip->iReplaceMode) { case CFGRPL_ADD: case CFGRPL_UNIQUE: // that's easy, the new line is simply given pszLineToInsert = strdup(pManip->pszNewLine); break; case CFGRPL_REMOVELINE: // that's easy, just leave pszLineToInsert = 0; break; case CFGRPL_REMOVEPART: if (pszDeletedLine) { // parse the line which we removed above, // find the part which was to be removed, // and set pszLineToInsert to the rest of that PSZ pArgToDel = 0; // find the subpart to look for if ((pArgToDel = strhistr(pszDeletedLine, pszArgNew))) { // ULONG ulOfs = 0; // pArgToDel now has the position of the // part to be deleted in the old part /* pszLineToInsert = strdup(pszDeletedLine); strhFindReplace(&pszLineToInsert, &ulOfs, pszArgNew, // search string ""); // replacement string */ // V0.9.18 (2002-03-24) [umoeller] // the above left duplicate ";" characters in the line ULONG ulArgNewLen = strlen(pszArgNew); ULONG cbFirst, cb; PSZ pAfter = pArgToDel + ulArgNewLen; while (*pAfter == ';') ++pAfter; // now recompose cbFirst = pArgToDel - pszDeletedLine; cb = cbFirst // length up to pArgToDel + strlen(pAfter) // length of remainder + 1; // null terminator; if (pszLineToInsert = (PSZ)malloc(cb)) { if (cbFirst) memcpy(pszLineToInsert, pszDeletedLine, cbFirst); strcpy(pszLineToInsert + cbFirst, pAfter); } else arc = ERROR_NOT_ENOUGH_MEMORY; } else // subpart not found: // reinsert the old line pszLineToInsert = strdup(pszDeletedLine); } // else line to be deleted was not found: leave pszLineToInsert = 0; break; case CFGRPL_ADDLEFT: case CFGRPL_ADDRIGHT: // add something to the left or right of the existing // argument: // check if we found a line above if (pszDeletedLine) { PSZ pszCommandOld = 0, pszArgOld = 0; // yes: split the existing line pSep = strchr(pszDeletedLine, '='); if (pSep) { // "=" found: separate in two strings pszCommandOld = strhSubstr(pszDeletedLine, pSep); pszArgOld = strdup(pSep+1); } else { // no "=" found: that's strange /* throw(BSConfigExcpt(CFGEXCPT_NOSEPARATOR, strdup(pszDeletedLine))); */ arc = CFGERR_NOSEPARATOR; break; } if ((pszCommandOld) && (pszArgOld)) { // does the new arg exist in old arg already? if (strhistr(pszArgOld, pszArgNew) == 0) { // no: go! ULONG cbCommandOld = strlen(pszCommandOld); ULONG cbArgOld = strlen(pszArgOld); ULONG cbArgNew = strlen(pszArgNew); // created at the very top // compose new line pszLineToInsert = (PSZ)malloc(cbCommandOld + cbArgOld + cbArgNew + 5); if (pManip->iReplaceMode == CFGRPL_ADDLEFT) // add new arg to the left: sprintf(pszLineToInsert, "%s=%s;%s", pszCommandOld, pszArgNew, pszArgOld); else // add new arg to the right: if (*(pszArgOld + cbArgOld - 1) == ';') // old arg has terminating ";" already: sprintf(pszLineToInsert, "%s=%s%s", pszCommandOld, pszArgOld, pszArgNew); else // we need to append a ";": sprintf(pszLineToInsert, "%s=%s;%s", pszCommandOld, pszArgOld, pszArgNew); } // end if (stristr(pszArgOld, pszArgNew) == 0) else // exists already: // reinsert the line we deleted above pszLineToInsert = strdup(pszDeletedLine); free(pszCommandOld); free(pszArgOld); } } // end if (pszDeletedLine) else // line was not found: add a new one then // (the position has been determined above) pszLineToInsert = strdup(pManip->pszNewLine); break; } // **** 6): insert new line at pInsertAt if ((pszLineToInsert) && (arc == NO_ERROR)) { PSZ pszInsert2 = NULL; PSZ pszNew = NULL; ULONG cbInsert = strlen(pszLineToInsert); BOOL fLineBreakNeeded = FALSE; // check if the char before pInsertAt is EOL if (pInsertAt > *ppszContents) if (*(pInsertAt-1) != '\n') fLineBreakNeeded = TRUE; if (fLineBreakNeeded) { // not EOL (this might be the case if we're // appending to the very bottom of CONFIG.SYS) pszInsert2 = (PSZ)malloc(cbInsert + 5); // insert an extra line break then *pszInsert2 = '\n'; memcpy(pszInsert2 + 1, pszLineToInsert, cbInsert); strcpy(pszInsert2 + cbInsert + 1, "\n"); } else { // OK: pszInsert2 = (PSZ)malloc(cbInsert + 3); memcpy(pszInsert2, pszLineToInsert, cbInsert); strcpy(pszInsert2 + cbInsert, "\n"); } pszNew = strhins(*ppszContents, // source (pInsertAt - *ppszContents), // offset pszInsert2); // insertion string if (pszNew) { free(pszInsert2); free(*ppszContents); *ppszContents = pszNew; // we've made changes... *pfDirty = TRUE; } else arc = CFGERR_MANIPULATING; } else if ( (pManip->iReplaceMode != CFGRPL_REMOVELINE) && (pManip->iReplaceMode != CFGRPL_REMOVEPART) ) arc = CFGERR_MANIPULATING; if (arc == NO_ERROR) { // finally, create log entries for Undo(). // This uses the first three characters of the // each log entry to signify what happend: // -- "DLL": deleted line // -- "DLP": deleted part of line // -- "NWL": added an all new line // -- "NWP": added a new part to an existing line // There may be several log entries per manipulator // if a line was deleted and then re-inserted (i.e. updated). if (pstrChanged) { switch (pManip->iReplaceMode) { case CFGRPL_UNIQUE: if (pszDeletedLine) { // did we delete a line? xstrcat(pstrChanged, "DLL ", 0); xstrcat(pstrChanged, pszDeletedLine, 0); xstrcatc(pstrChanged, '\n'); } // no break, because we also added something goto LABEL_CFGRPL_ADD ; // VAC gives us warnings otherwise... case CFGRPL_ADD: LABEL_CFGRPL_ADD: if (pszLineToInsert) { // added a line: xstrcat(pstrChanged, "NWL ", 0); xstrcat(pstrChanged, pszLineToInsert, 0); xstrcatc(pstrChanged, '\n'); } break; case CFGRPL_ADDLEFT: case CFGRPL_ADDRIGHT: if (pszDeletedLine) { // a line was found and updated: // store the new part only xstrcat(pstrChanged, "NWP ", 0); xstrcat(pstrChanged, pManip->pszNewLine, 0); } else { xstrcat(pstrChanged, "NWL ", 0); xstrcat(pstrChanged, pszLineToInsert, 0); } xstrcatc(pstrChanged, '\n'); break; case CFGRPL_REMOVELINE: if (pszDeletedLine) { // did we delete a line? xstrcat(pstrChanged, "DLL ", 0); xstrcat(pstrChanged, pszDeletedLine, 0); xstrcatc(pstrChanged, '\n'); } break; case CFGRPL_REMOVEPART: if (pszDeletedLine) { // did we delete a part? xstrcat(pstrChanged, "DLP ", 0); xstrcat(pstrChanged, pManip->pszNewLine, 0); xstrcatc(pstrChanged, '\n'); } break; } } // end if (pstrChanged) } // clean up if (pszCommand) free(pszCommand); if (pszArgNew) free(pszArgNew); if (pszDeletedLine) free(pszDeletedLine); if (pszLineToInsert) free(pszLineToInsert); return arc; } /* ****************************************************************** * * Swappath * ********************************************************************/ extern CHAR G_szSwapperFilename[CCHMAXPATH] = ""; /* *@@ csysParseSwapPath: * *@@added V0.9.9 (2001-02-08) [umoeller] *@@changed V0.9.16 (2001-11-10) [umoeller]: moved to helpers */ BOOL csysParseSwapPath(const char *pcszConfigSys, // in: if NULL, this gets loaded PSZ pszSwapPath, // out: swapper directory PULONG pulMinFree, // out: min free PULONG pulMinSize) // out: min size { BOOL brc = FALSE; PSZ pszConfigSysTemp = 0; if (!pcszConfigSys) { // not specified: load it if (csysLoadConfigSys(NULL, &pszConfigSysTemp) == NO_ERROR) pcszConfigSys = pszConfigSysTemp; } if (pcszConfigSys) { // parse SWAPPATH command PSZ p; if (p = csysGetParameter(pcszConfigSys, "SWAPPATH=", NULL, 0)) { CHAR szSwap[CCHMAXPATH]; ULONG ulMinFree = 2048, ulMinSize = 2048; // int iScanned; sscanf(p, "%s %d %d", &szSwap, &ulMinFree, &ulMinSize); if (pszSwapPath) strcpy(pszSwapPath, szSwap); if (pulMinFree) *pulMinFree = ulMinFree; if (pulMinSize) *pulMinSize = ulMinSize; if (G_szSwapperFilename[0] == '\0') { // first call: copy to global so that the swapper // monitors will always use the old one, in case // the user changes this strcpy(G_szSwapperFilename, szSwap); if (G_szSwapperFilename[strlen(G_szSwapperFilename)-1] != '\\') strcat(G_szSwapperFilename, "\\"); strcat(G_szSwapperFilename, "swapper.dat"); } brc = TRUE; } } if (pszConfigSysTemp) free(pszConfigSysTemp); return brc; } /* *@@ csysQuerySwapperSize: * returns the current size of the swap file * in bytes. * *@@added V0.9.9 (2001-02-08) [umoeller] *@@changed V0.9.16 (2001-11-10) [umoeller]: moved to helpers */ ULONG csysQuerySwapperSize(VOID) { ULONG ulrc = 0; if (G_szSwapperFilename[0] == '\0') { // first call: compose the path csysParseSwapPath(NULL, NULL, NULL, NULL); } if (G_szSwapperFilename[0]) doshQueryPathSize(G_szSwapperFilename, &ulrc); return (ulrc); } // testcase /* int main() { PSZ pszContents = NULL; if (0 == csysLoadConfigSys(NULL, &pszContents)) { CHAR szValue[1000]; PSZ pszValue = csysGetParameter(pszContents, "IFS=", szValue, sizeof(szValue)); if (pszValue) printf("Value: %s", szValue); } return (0); } */