1 /* 2 * PROJECT: ReactOS NetSh 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Network Shell command interpreter 5 * COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org> 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include "precomp.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 /* FUNCTIONS *****************************************************************/ 16 17 BOOL 18 InterpretCommand( 19 _In_ LPWSTR *argv, 20 _In_ DWORD dwArgCount) 21 { 22 PCONTEXT_ENTRY pContext, pSubContext; 23 PCOMMAND_ENTRY pCommand; 24 PCOMMAND_GROUP pGroup; 25 BOOL bDone = FALSE; 26 DWORD dwHelpLevel = 0; 27 DWORD dwError = ERROR_SUCCESS; 28 29 /* If no args provided */ 30 if (dwArgCount == 0) 31 return TRUE; 32 33 if (pCurrentContext == NULL) 34 { 35 DPRINT1("InterpretCmd: invalid context %p\n", pCurrentContext); 36 return FALSE; 37 } 38 39 if ((_wcsicmp(argv[dwArgCount - 1], L"?") == 0) || 40 (_wcsicmp(argv[dwArgCount - 1], L"help") == 0)) 41 { 42 dwHelpLevel = dwArgCount - 1; 43 } 44 45 pContext = pCurrentContext; 46 47 while (TRUE) 48 { 49 pCommand = pContext->pCommandListHead; 50 while (pCommand != NULL) 51 { 52 if (_wcsicmp(argv[0], pCommand->pwszCmdToken) == 0) 53 { 54 if (dwHelpLevel == 1) 55 { 56 ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 57 return TRUE; 58 } 59 else 60 { 61 dwError = pCommand->pfnCmdHandler(NULL, argv, 0, dwArgCount, 0, NULL, &bDone); 62 if (dwError != ERROR_SUCCESS) 63 { 64 ConPrintf(StdOut, L"Error: %lu\n\n"); 65 ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 66 } 67 return !bDone; 68 } 69 } 70 71 pCommand = pCommand->pNext; 72 } 73 74 pGroup = pContext->pGroupListHead; 75 while (pGroup != NULL) 76 { 77 if (_wcsicmp(argv[0], pGroup->pwszCmdGroupToken) == 0) 78 { 79 if (dwHelpLevel == 1) 80 { 81 HelpGroup(pGroup); 82 return TRUE; 83 } 84 85 pCommand = pGroup->pCommandListHead; 86 while (pCommand != NULL) 87 { 88 if ((dwArgCount > 1) && (_wcsicmp(argv[1], pCommand->pwszCmdToken) == 0)) 89 { 90 if (dwHelpLevel == 2) 91 { 92 ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 93 return TRUE; 94 } 95 else 96 { 97 dwError = pCommand->pfnCmdHandler(NULL, argv, 1, dwArgCount, 0, NULL, &bDone); 98 if (dwError != ERROR_SUCCESS) 99 { 100 ConPrintf(StdOut, L"Error: %lu\n\n"); 101 ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 102 return TRUE; 103 } 104 return !bDone; 105 } 106 } 107 108 pCommand = pCommand->pNext; 109 } 110 111 HelpGroup(pGroup); 112 return TRUE; 113 } 114 115 pGroup = pGroup->pNext; 116 } 117 118 if (pContext == pCurrentContext) 119 { 120 pSubContext = pContext->pSubContextHead; 121 while (pSubContext != NULL) 122 { 123 if (_wcsicmp(argv[0], pSubContext->pszContextName) == 0) 124 { 125 pCurrentContext = pSubContext; 126 return TRUE; 127 } 128 129 pSubContext = pSubContext->pNext; 130 } 131 } 132 133 if (pContext == pRootContext) 134 break; 135 136 pContext = pContext->pParentContext; 137 } 138 139 ConResPrintf(StdErr, IDS_INVALID_COMMAND, argv[0]); 140 141 return TRUE; 142 } 143 144 145 /* 146 * InterpretScript(char *line): 147 * The main function used for when reading commands from scripts. 148 */ 149 BOOL 150 InterpretScript( 151 _In_ LPWSTR pszInputLine) 152 { 153 LPWSTR args_vector[MAX_ARGS_COUNT]; 154 DWORD dwArgCount = 0; 155 BOOL bWhiteSpace = TRUE; 156 LPWSTR ptr; 157 158 memset(args_vector, 0, sizeof(args_vector)); 159 160 ptr = pszInputLine; 161 while (*ptr != 0) 162 { 163 if (iswspace(*ptr) || *ptr == L'\n') 164 { 165 *ptr = 0; 166 bWhiteSpace = TRUE; 167 } 168 else 169 { 170 if ((bWhiteSpace != FALSE) && (dwArgCount < MAX_ARGS_COUNT)) 171 { 172 args_vector[dwArgCount] = ptr; 173 dwArgCount++; 174 } 175 176 bWhiteSpace = FALSE; 177 } 178 179 ptr++; 180 } 181 182 /* sends the string to find the command */ 183 return InterpretCommand(args_vector, dwArgCount); 184 } 185 186 187 VOID 188 InterpretInteractive(VOID) 189 { 190 WCHAR input_line[MAX_STRING_SIZE]; 191 LPWSTR args_vector[MAX_ARGS_COUNT]; 192 DWORD dwArgCount = 0; 193 BOOL bWhiteSpace = TRUE; 194 BOOL bRun = TRUE; 195 LPWSTR ptr; 196 197 while (bRun != FALSE) 198 { 199 dwArgCount = 0; 200 memset(args_vector, 0, sizeof(args_vector)); 201 202 /* Shown just before the input where the user places commands */ 203 // ConResPuts(StdOut, IDS_APP_PROMPT); 204 ConPuts(StdOut, L"netsh"); 205 if (pCurrentContext != pRootContext) 206 { 207 ConPuts(StdOut, L" "); 208 ConPuts(StdOut, pCurrentContext->pszContextName); 209 } 210 ConPuts(StdOut, L">"); 211 212 /* Get input from the user. */ 213 fgetws(input_line, MAX_STRING_SIZE, stdin); 214 215 ptr = input_line; 216 while (*ptr != 0) 217 { 218 if (iswspace(*ptr) || *ptr == L'\n') 219 { 220 *ptr = 0; 221 bWhiteSpace = TRUE; 222 } 223 else 224 { 225 if ((bWhiteSpace != FALSE) && (dwArgCount < MAX_ARGS_COUNT)) 226 { 227 args_vector[dwArgCount] = ptr; 228 dwArgCount++; 229 } 230 bWhiteSpace = FALSE; 231 } 232 ptr++; 233 } 234 235 /* Send the string to find the command */ 236 bRun = InterpretCommand(args_vector, dwArgCount); 237 } 238 } 239