📄 configfile.c
字号:
return pRes;}/* filePreset * * Load a file containing presetting information (a configuration file). */static voidfilePreset( tOptions* pOpts, char const* pzFileName, int direction ){ tmap_info_t cfgfile; tOptState st = OPTSTATE_INITIALIZER(PRESET); char* pzFileText = text_mmap( pzFileName, PROT_READ|PROT_WRITE, MAP_PRIVATE, &cfgfile ); if (TEXT_MMAP_FAILED_ADDR(pzFileText)) return; if (direction == DIRECTION_CALLED) { st.flags = OPTST_DEFINED; direction = DIRECTION_PROCESS; } /* * IF this is called via "optionProcess", then we are presetting. * This is the default and the PRESETTING bit will be set. * If this is called via "optionFileLoad", then the bit is not set * and we consider stuff set herein to be "set" by the client program. */ if ((pOpts->fOptSet & OPTPROC_PRESETTING) == 0) st.flags = OPTST_SET; do { while (isspace( (int)*pzFileText )) pzFileText++; if (isalpha( (int)*pzFileText )) { pzFileText = handleConfig( pOpts, &st, pzFileText, direction ); } else switch (*pzFileText) { case '<': if (isalpha( (int)pzFileText[1] )) pzFileText = handleStructure(pOpts, &st, pzFileText, direction); else switch (pzFileText[1]) { case '?': pzFileText = handleDirective( pOpts, pzFileText ); break; case '!': pzFileText = handleComment( pzFileText ); break; case '/': pzFileText = strchr( pzFileText+2, '>' ); if (pzFileText++ != NULL) break; default: goto all_done; } break; case '[': pzFileText = handleProgramSection( pOpts, pzFileText ); break; case '#': pzFileText = strchr( pzFileText+1, '\n' ); break; default: goto all_done; /* invalid format */ } } while (pzFileText != NULL); all_done: text_munmap( &cfgfile );}/* handleComment * * "pzText" points to a "<!" sequence. * Theoretically, we should ensure that it begins with "<!--", * but actually I don't care that much. It ends with "-->". */static char*handleComment( char* pzText ){ char* pz = strstr( pzText, "-->" ); if (pz != NULL) pz += 3; return pz;}/* handleConfig * * "pzText" points to the start of some value name. * The end of the entry is the end of the line that is not preceded by * a backslash escape character. The string value is always processed * in "cooked" mode. */static char*handleConfig( tOptions* pOpts, tOptState* pOS, char* pzText, int direction ){ char* pzName = pzText++; char* pzEnd = strchr( pzText, '\n' ); if (pzEnd == NULL) return pzText + strlen(pzText); while (ISNAMECHAR( (int)*pzText )) pzText++; while (isspace( (int)*pzText )) pzText++; if (pzText > pzEnd) { name_only: *pzEnd++ = NUL; loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED ); return pzEnd; } /* * Either the first character after the name is a ':' or '=', * or else we must have skipped over white space. Anything else * is an invalid format and we give up parsing the text. */ if ((*pzText == '=') || (*pzText == ':')) { while (isspace( (int)*++pzText )) ; if (pzText > pzEnd) goto name_only; } else if (! isspace((int)pzText[-1])) return NULL; /* * IF the value is continued, remove the backslash escape and push "pzEnd" * on to a newline *not* preceded by a backslash. */ if (pzEnd[-1] == '\\') { char* pcD = pzEnd-1; char* pcS = pzEnd; for (;;) { char ch = *(pcS++); switch (ch) { case NUL: pcS = NULL; case '\n': *pcD = NUL; pzEnd = pcS; goto copy_done; case '\\': if (*pcS == '\n') { ch = *(pcS++); } /* FALLTHROUGH */ default: *(pcD++) = ch; } } copy_done:; } else { /* * The newline was not preceded by a backslash. NUL it out */ *(pzEnd++) = NUL; } /* * "pzName" points to what looks like text for one option/configurable. * It is NUL terminated. Process it. */ loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED ); return pzEnd;}/* handleDirective * * "pzText" points to a "<?" sequence. * For the moment, we only handle "<?program" directives. */static char*handleDirective( tOptions* pOpts, char* pzText ){ char ztitle[32] = "<?"; size_t title_len = strlen( zProg ); size_t name_len; if ( (strncmp( pzText+2, zProg, title_len ) != 0) || (! isspace( (int)pzText[title_len+2] )) ) { pzText = strchr( pzText+2, '>' ); if (pzText != NULL) pzText++; return pzText; } name_len = strlen( pOpts->pzProgName ); strcpy( ztitle+2, zProg ); title_len += 2; do { pzText += title_len; if (isspace((int)*pzText)) { while (isspace((int)*pzText)) pzText++; if ( (strneqvcmp( pzText, pOpts->pzProgName, (int)name_len) == 0) && (pzText[name_len] == '>')) { pzText += name_len + 1; break; } } pzText = strstr( pzText, ztitle ); } while (pzText != NULL); return pzText;}/* handleProgramSection * * "pzText" points to a '[' character. * The "traditional" [PROG_NAME] segmentation of the config file. * Do not ever mix with the "<?program prog-name>" variation. */static char*handleProgramSection( tOptions* pOpts, char* pzText ){ size_t len = strlen( pOpts->pzPROGNAME ); if ( (strncmp( pzText+1, pOpts->pzPROGNAME, len ) == 0) && (pzText[len+1] == ']')) return strchr( pzText + len + 2, '\n' ); if (len > 16) return NULL; { char z[24]; sprintf( z, "[%s]", pOpts->pzPROGNAME ); pzText = strstr( pzText, z ); } if (pzText != NULL) pzText = strchr( pzText, '\n' ); return pzText;}/* handleStructure * * "pzText" points to a '<' character, followed by an alpha. * The end of the entry is either the "/>" following the name, or else a * "</name>" string. */static char*handleStructure( tOptions* pOpts, tOptState* pOS, char* pzText, int direction ){ tOptionLoadMode mode = option_load_mode; tOptionValue valu; char* pzName = ++pzText; char* pzData; char* pcNulPoint; while (ISNAMECHAR( *pzText )) pzText++; pcNulPoint = pzText; valu.valType = OPARG_TYPE_STRING; switch (*pzText) { case ' ': case '\t': pzText = parseAttributes( pOpts, pzText, &mode, &valu ); if (*pzText == '>') break; if (*pzText != '/') return NULL; /* FALLTHROUGH */ case '/': if (pzText[1] != '>') return NULL; *pzText = NUL; pzText += 2; loadOptionLine( pOpts, pOS, pzName, direction, mode ); return pzText; case '>': break; default: pzText = strchr( pzText, '>'); if (pzText != NULL) pzText++; return pzText; } /* * If we are here, we have a value. "pzText" points to a closing angle * bracket. Separate the name from the value for a moment. */ *pcNulPoint = NUL; pzData = ++pzText; /* * Find the end of the option text and NUL terminate it */ { char z[64], *pz = z; size_t len = strlen(pzName) + 4; if (len > sizeof(z)) pz = AGALOC(len, "scan name"); sprintf( pz, "</%s>", pzName ); *pzText = ' '; pzText = strstr( pzText, pz ); if (pz != z) AGFREE(pz); if (pzText == NULL) return pzText; *pzText = NUL; pzText += len-1; } /* * Rejoin the name and value for parsing by "loadOptionLine()". * Erase any attributes parsed by "parseAttributes()". */ memset(pcNulPoint, ' ', pzData - pcNulPoint); /* * "pzName" points to what looks like text for one option/configurable. * It is NUL terminated. Process it. */ loadOptionLine( pOpts, pOS, pzName, direction, mode ); return pzText;}/* internalFileLoad * * Load a configuration file. This may be invoked either from * scanning the "homerc" list, or from a specific file request. * (see "optionFileLoad()", the implementation for --load-opts) */LOCAL voidinternalFileLoad( tOptions* pOpts ){ int idx; int inc = DIRECTION_PRESET; char zFileName[ AG_PATH_MAX+1 ]; if (pOpts->papzHomeList == NULL) return; /* * Find the last RC entry (highest priority entry) */ for (idx = 0; pOpts->papzHomeList[ idx+1 ] != NULL; ++idx) ; /* * For every path in the home list, ... *TWICE* We start at the last * (highest priority) entry, work our way down to the lowest priority, * handling the immediate options. * Then we go back up, doing the normal options. */ for (;;) { struct stat StatBuf; cch_t* pzPath; /* * IF we've reached the bottom end, change direction */ if (idx < 0) { inc = DIRECTION_PROCESS; idx = 0; } pzPath = pOpts->papzHomeList[ idx ]; /* * IF we've reached the top end, bail out */ if (pzPath == NULL) break; idx += inc; if (! optionMakePath( zFileName, (int)sizeof(zFileName), pzPath, pOpts->pzProgPath )) continue; /* * IF the file name we constructed is a directory, * THEN append the Resource Configuration file name * ELSE we must have the complete file name */ if (stat( zFileName, &StatBuf ) != 0) continue; /* bogus name - skip the home list entry */ if (S_ISDIR( StatBuf.st_mode )) { size_t len = strlen( zFileName ); char* pz; if (len + 1 + strlen( pOpts->pzRcName ) >= sizeof( zFileName )) continue; pz = zFileName + len; if (pz[-1] != DIRCH) *(pz++) = DIRCH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -