Changeset 3210 for trunk/src/kmk
- Timestamp:
- Mar 29, 2018, 4:51:12 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/redirect.c
r3207 r3210 114 114 { 115 115 kmk_builtin_ctx_printf(pCtx, fIsErr, 116 "usage: %s [-[rwa+tb]<fd> <file>] [-d<fd>=<src-fd>] [-c<fd>] \n"116 "usage: %s [-[rwa+tb]<fd> <file>] [-d<fd>=<src-fd>] [-c<fd>] [--stdin-pipe]\n" 117 117 " [-Z] [-E <var=val>] [-C <dir>] [--wcc-brain-damage]\n" 118 118 " [-v] -- <program> [args]\n" … … 127 127 "\n" 128 128 "The -d switch duplicate the right hand file descriptor (src-fd) to the left\n" 129 "hand side one (fd). The latter is limited to standard handles on windows.\n"129 "hand side one (fd). The latter is limited to standard handles on windows.\n" 130 130 "\n" 131 131 "The -c switch will close the specified file descriptor. Limited to standard\n" 132 132 "handles on windows.\n" 133 "\n" 134 "The --stdin-pipe switch will replace stdin with the read end of an anonymous\n" 135 "pipe. This is for tricking things like rsh.exe that blocks reading on stdin.\n" 133 136 "\n" 134 137 "The -Z switch zaps the environment.\n" … … 178 181 /** The filename - NULL if close only. */ 179 182 const char *pszFilename; 183 /** The other pipe end, needs closing in cleanup. */ 184 int fdOtherPipeEnd; 180 185 #ifndef USE_POSIX_SPAWN 181 186 /** Saved file descriptor. */ … … 197 202 return K_FALSE; 198 203 #endif 204 } 205 206 207 /** 208 * Creates a pair of pipe descriptors that does not conflict with any previous 209 * orders. 210 * 211 * The pipe is open with both descriptors being inherited by the child as it's 212 * supposed to be a dummy pipe for stdin that won't break. 213 * 214 * @returns 0 on success, exit code on failure (error message displayed). 215 * @param pCtx The command execution context. 216 * @param paFds Where to return the pipe descriptors 217 * @param cOrders The number of orders. 218 * @param paOrders The order array. 219 * @param fdTarget The target descriptor (0). 220 */ 221 static int kRedirectCreateStdInPipeWithoutConflict(PKMKBUILTINCTX pCtx, int paFds[2], 222 unsigned cOrders, REDIRECTORDERS *paOrders, int fdTarget) 223 { 224 struct 225 { 226 int aFds[2]; 227 } aTries[32]; 228 unsigned cTries = 0; 229 230 while (cTries < K_ELEMENTS(aTries)) 231 { 232 #ifdef _MSC_VER 233 int rc = _pipe(aTries[cTries].aFds, 0, _O_BINARY); 234 #else 235 int rc = pipe(aTries[cTries].aFds); 236 #endif 237 if (rc >= 0) 238 { 239 if ( !kRedirectHasConflict(aTries[cTries].aFds[0], cOrders, paOrders) 240 && !kRedirectHasConflict(aTries[cTries].aFds[1], cOrders, paOrders) 241 #ifndef _MSC_VER 242 && aTries[cTries].aFds[0] != fdTarget 243 && aTries[cTries].aFds[1] != fdTarget 244 #endif 245 ) 246 { 247 paFds[0] = aTries[cTries].aFds[0]; 248 paFds[1] = aTries[cTries].aFds[1]; 249 250 while (cTries-- > 0) 251 { 252 close(aTries[cTries].aFds[0]); 253 close(aTries[cTries].aFds[1]); 254 } 255 return 0; 256 } 257 } 258 else 259 { 260 err(pCtx, -1, "failed to create stdin pipe (try #%u)", cTries + 1); 261 break; 262 } 263 cTries++; 264 } 265 if (cTries >= K_ELEMENTS(aTries)) 266 errx(pCtx, -1, "failed to find a conflict free pair of pipe descriptor for stdin!"); 267 268 /* cleanup */ 269 while (cTries-- > 0) 270 { 271 close(aTries[cTries].aFds[0]); 272 close(aTries[cTries].aFds[1]); 273 } 274 return 1; 199 275 } 200 276 … … 331 407 close(paOrders[i].fdSource); 332 408 paOrders[i].fdSource = -1; 409 410 if (paOrders[i].fdOtherPipeEnd >= 0) 411 { 412 close(paOrders[i].fdOtherPipeEnd); 413 paOrders[i].fdOtherPipeEnd = -1; 414 } 415 333 416 if ( fFailure 334 417 && paOrders[i].fRemoveOnFailure … … 920 1003 FALSE /*fInheritHandles*/, CREATE_SUSPENDED, pszzEnv, pszCwd, &StartupInfo, &ProcInfo)) 921 1004 { 1005 unsigned i; 1006 922 1007 /* Inject the handles and try make it start executing. */ 923 1008 char szErrMsg[128]; … … 927 1012 else if (!ResumeThread(ProcInfo.hThread)) 928 1013 rc = errx(pCtx, 10, "ResumeThread failed: %u", GetLastError()); 1014 1015 /* Duplicate the write end of any stdin pipe handles into the child. */ 1016 for (i = 0; i < cOrders; i++) 1017 if (paOrders[cOrders].fdOtherPipeEnd >= 0) 1018 { 1019 HANDLE hIgnored = INVALID_HANDLE_VALUE; 1020 HANDLE hPipeW = (HANDLE)_get_osfhandle(paOrders[i].fdOtherPipeEnd); 1021 if (!DuplicateHandle(GetCurrentProcess(), hPipeW, ProcInfo.hProcess, &hIgnored, 0 /*fDesiredAccess*/, 1022 TRUE /*fInheritable*/, DUPLICATE_SAME_ACCESS)) 1023 rc = errx(pCtx, 10, "DuplicateHandle failed on other stdin pipe end %d/%p: %u", 1024 paOrders[i].fdOtherPipeEnd, hPipeW, GetLastError()); 1025 } 929 1026 930 1027 /* Kill it if any of that fails. */ … … 1365 1462 else if (strcmp(pszArg, "verbose") == 0) 1366 1463 chOpt = 'v'; 1464 else if (strcmp(pszArg, "stdin-pipe") == 0) 1465 chOpt = 'I'; 1367 1466 else 1368 1467 { … … 1560 1659 1561 1660 /* 1562 * Okay, it is some file descriptor ope aration. Make sure we've got room for it.1661 * Okay, it is some file descriptor operation. Make sure we've got room for it. 1563 1662 */ 1564 1663 if (cOrders + 1 < K_ELEMENTS(aOrders)) … … 1569 1668 aOrders[cOrders].fRemoveOnFailure = 0; 1570 1669 aOrders[cOrders].pszFilename = NULL; 1670 aOrders[cOrders].fdOtherPipeEnd = -1; 1571 1671 #ifndef USE_POSIX_SPAWN 1572 1672 aOrders[cOrders].fdSaved = -1; … … 1643 1743 #endif 1644 1744 } 1745 } 1746 } 1747 else if (chOpt == 'I') 1748 { 1749 /* 1750 * Replace stdin with the read end of an anonymous pipe. 1751 */ 1752 int aFds[2] = { -1, -1 }; 1753 rcExit = kRedirectCreateStdInPipeWithoutConflict(pCtx, aFds, cOrders, aOrders, 0 /*fdTarget*/); 1754 if (rcExit == 0) 1755 { 1756 aOrders[cOrders].enmOrder = kRedirectOrder_Dup; 1757 aOrders[cOrders].fdTarget = 0; 1758 aOrders[cOrders].fdSource = aFds[0]; 1759 aOrders[cOrders].fdOtherPipeEnd = aFds[1]; 1760 cOrders++; 1761 #ifdef USE_POSIX_SPAWN 1762 rcExit = posix_spawn_file_actions_adddup2(&FileActions, aFds[0], 0); 1763 if (rcExit != 0) 1764 rcExit = errx(pCtx, 2, "posix_spawn_file_actions_addclose(%d) failed: %s", fd, strerror(rcExit)); 1765 #endif 1645 1766 } 1646 1767 }
Note:
See TracChangeset
for help on using the changeset viewer.