Changeset 2912 for trunk/src/kmk/kmkbuiltin/kSubmit.c
- Timestamp:
- Sep 14, 2016, 3:36:15 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/kSubmit.c
r2894 r2912 1162 1162 1163 1163 1164 /** The environment variable compare function.1165 * We must use case insensitive compare on windows (Path vs PATH). */1166 #ifdef KBUILD_OS_WINDOWS1167 # define KSUBMIT_ENV_NCMP _strnicmp1168 #else1169 # define KSUBMIT_ENV_NCMP strncmp1170 #endif1171 1172 1173 /**1174 * Handles the --set var=value option.1175 *1176 * @returns 0 on success, non-zero exit code on error.1177 * @param papszEnv The environment vector.1178 * @param pcEnvVars Pointer to the variable holding the number of1179 * environment variables held by @a papszEnv.1180 * @param pcAllocatedEnvVars Pointer to the variable holding max size of the1181 * environment vector.1182 * @param cVerbosity The verbosity level.1183 * @param pszValue The var=value string to apply.1184 */1185 static int kSubmitOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,1186 int cVerbosity, const char *pszValue)1187 {1188 const char *pszEqual = strchr(pszValue, '=');1189 if (pszEqual)1190 {1191 char **papszEnv = *ppapszEnv;1192 unsigned iEnvVar;1193 unsigned cEnvVars = *pcEnvVars;1194 size_t const cchVar = pszEqual - pszValue;1195 for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)1196 {1197 char *pszCur = papszEnv[iEnvVar];1198 if ( KSUBMIT_ENV_NCMP(pszCur, pszValue, cchVar) == 01199 && pszCur[cchVar] == '=')1200 {1201 if (cVerbosity > 0)1202 fprintf(stderr, "kSubmit: replacing '%s' with '%s'\n", papszEnv[iEnvVar], pszValue);1203 free(papszEnv[iEnvVar]);1204 papszEnv[iEnvVar] = xstrdup(pszValue);1205 break;1206 }1207 }1208 if (iEnvVar == cEnvVars)1209 {1210 /* Append new variable. We probably need to resize the vector. */1211 if ((cEnvVars + 2) > *pcAllocatedEnvVars)1212 {1213 *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;1214 *ppapszEnv = papszEnv = (char **)xrealloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));1215 }1216 papszEnv[cEnvVars++] = xstrdup(pszValue);1217 papszEnv[cEnvVars] = NULL;1218 *pcEnvVars = cEnvVars;1219 if (cVerbosity > 0)1220 fprintf(stderr, "kSubmit: added '%s'\n", papszEnv[iEnvVar]);1221 }1222 else1223 {1224 /* Check for duplicates. */1225 for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)1226 if ( KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 01227 && papszEnv[iEnvVar][cchVar] == '=')1228 {1229 if (cVerbosity > 0)1230 fprintf(stderr, "kSubmit: removing duplicate '%s'\n", papszEnv[iEnvVar]);1231 free(papszEnv[iEnvVar]);1232 cEnvVars--;1233 if (iEnvVar != cEnvVars)1234 papszEnv[iEnvVar] = papszEnv[cEnvVars];1235 papszEnv[cEnvVars] = NULL;1236 iEnvVar--;1237 }1238 }1239 }1240 else1241 return errx(1, "Missing '=': -E %s", pszValue);1242 1243 return 0;1244 }1245 1246 1247 /**1248 * Handles the --unset var option.1249 *1250 * @returns 0 on success, non-zero exit code on error.1251 * @param papszEnv The environment vector.1252 * @param pcEnvVars Pointer to the variable holding the number of1253 * environment variables held by @a papszEnv.1254 * @param cVerbosity The verbosity level.1255 * @param pszVarToRemove The name of the variable to remove.1256 */1257 static int kSubmitOptEnvUnset(char **papszEnv, unsigned *pcEnvVars, int cVerbosity, const char *pszVarToRemove)1258 {1259 if (strchr(pszVarToRemove, '=') == NULL)1260 {1261 unsigned cRemoved = 0;1262 size_t const cchVar = strlen(pszVarToRemove);1263 unsigned cEnvVars = *pcEnvVars;1264 unsigned iEnvVar;1265 1266 for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)1267 if ( KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszVarToRemove, cchVar) == 01268 && papszEnv[iEnvVar][cchVar] == '=')1269 {1270 if (cVerbosity > 0)1271 fprintf(stderr, !cRemoved ? "kSubmit: removing '%s'\n"1272 : "kSubmit: removing duplicate '%s'\n", papszEnv[iEnvVar]);1273 free(papszEnv[iEnvVar]);1274 cEnvVars--;1275 if (iEnvVar != cEnvVars)1276 papszEnv[iEnvVar] = papszEnv[cEnvVars];1277 papszEnv[cEnvVars] = NULL;1278 cRemoved++;1279 iEnvVar--;1280 }1281 *pcEnvVars = cEnvVars;1282 1283 if (cVerbosity > 0 && !cRemoved)1284 fprintf(stderr, "kSubmit: not found '%s'\n", pszVarToRemove);1285 }1286 else1287 return errx(1, "Found invalid variable name character '=' in: -U %s", pszVarToRemove);1288 return 0;1289 }1290 1291 1292 1293 /**1294 * Handles the --chdir dir option.1295 *1296 * @returns 0 on success, non-zero exit code on error.1297 * @param pszCwd The CWD buffer. Contains current CWD on input,1298 * modified by @a pszValue on output.1299 * @param cbCwdBuf The size of the CWD buffer.1300 * @param pszValue The --chdir value to apply.1301 */1302 static int kSubmitOptChDir(char *pszCwd, size_t cbCwdBuf, const char *pszValue)1303 {1304 size_t cchNewCwd = strlen(pszValue);1305 size_t offDst;1306 if (cchNewCwd)1307 {1308 #ifdef HAVE_DOS_PATHS1309 if (*pszValue == '/' || *pszValue == '\\')1310 {1311 if (pszValue[1] == '/' || pszValue[1] == '\\')1312 offDst = 0; /* UNC */1313 else if (pszCwd[1] == ':' && isalpha(pszCwd[0]))1314 offDst = 2; /* Take drive letter from CWD. */1315 else1316 return errx(1, "UNC relative CWD not implemented: cur='%s' new='%s'", pszCwd, pszValue);1317 }1318 else if ( pszValue[1] == ':'1319 && isalpha(pszValue[0]))1320 {1321 if (pszValue[2] == '/'|| pszValue[2] == '\\')1322 offDst = 0; /* DOS style absolute path. */1323 else if ( pszCwd[1] == ':'1324 && tolower(pszCwd[0]) == tolower(pszValue[0]) )1325 {1326 pszValue += 2; /* Same drive as CWD, append drive relative path from value. */1327 cchNewCwd -= 2;1328 offDst = strlen(pszCwd);1329 }1330 else1331 {1332 /* Get current CWD on the specified drive and append value. */1333 int iDrive = tolower(pszValue[0]) - 'a' + 1;1334 if (!_getdcwd(iDrive, pszCwd, cbCwdBuf))1335 return err(1, "_getdcwd(%d,,) failed", iDrive);1336 pszValue += 2;1337 cchNewCwd -= 2;1338 }1339 }1340 #else1341 if (*pszValue == '/')1342 offDst = 0;1343 #endif1344 else1345 offDst = strlen(pszCwd); /* Relative path, append to the existing CWD value. */1346 1347 /* Do the copying. */1348 #ifdef HAVE_DOS_PATHS1349 if (offDst > 0 && pszCwd[offDst - 1] != '/' && pszCwd[offDst - 1] != '\\')1350 #else1351 if (offDst > 0 && pszCwd[offDst - 1] != '/')1352 #endif1353 pszCwd[offDst++] = '/';1354 if (offDst + cchNewCwd >= cbCwdBuf)1355 return errx(1, "Too long CWD: %*.*s%s", offDst, offDst, pszCwd, pszValue);1356 memcpy(&pszCwd[offDst], pszValue, cchNewCwd + 1);1357 }1358 /* else: relative, no change - quitely ignore. */1359 return 0;1360 }1361 1362 1363 1164 static int usage(FILE *pOut, const char *argv0) 1364 1165 { … … 1401 1202 , 1402 1203 argv0, argv0, argv0); 1403 return 1;1204 return 2; 1404 1205 } 1405 1206 … … 1414 1215 char **papszEnv = NULL; 1415 1216 const char *pszExecutable = NULL; 1416 const char *pszCwd = NULL;1417 1217 int iPostCmd = argc; 1418 1218 int cPostCmdArgs = 0; … … 1503 1303 else 1504 1304 { 1505 errx( 1, "Unknown option: '%s'", pszArg - 2);1305 errx(2, "Unknown option: '%s'", pszArg - 2); 1506 1306 return usage(stderr, argv[0]); 1507 1307 } … … 1542 1342 1543 1343 case 'E': 1544 rcExit = k SubmitOptEnvSet(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);1344 rcExit = kBuiltinOptEnvSet(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1545 1345 pChild->environment = papszEnv; 1546 1346 if (rcExit == 0) … … 1549 1349 1550 1350 case 'U': 1551 rcExit = k SubmitOptEnvUnset(papszEnv, &cEnvVars, cVerbosity, pszValue);1351 rcExit = kBuiltinOptEnvUnset(papszEnv, &cEnvVars, cVerbosity, pszValue); 1552 1352 if (rcExit == 0) 1553 1353 break; … … 1555 1355 1556 1356 case 'C': 1557 rcExit = k SubmitOptChDir(szCwd, cbCwdBuf, pszValue);1357 rcExit = kBuiltinOptChDir(szCwd, cbCwdBuf, pszValue); 1558 1358 if (rcExit == 0) 1559 1359 break;
Note:
See TracChangeset
for help on using the changeset viewer.