00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00039 #include "xdasd_exec.h"
00040 #include "xdasd_log.h"
00041
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #include <errno.h>
00046
00047 #ifdef _WIN32
00048 # define WIN32_LEAN_AND_MEAN
00049 # include <windows.h>
00050 # include <process.h>
00051 # include <direct.h>
00052 #else
00053 # include <unistd.h>
00054 # include <sys/types.h>
00055 # include <sys/wait.h>
00056 #endif
00057
00058 #ifdef XDASD_EXEC_TEST
00059 # define INITIAL_BUFSZ_MULTIPLIER 1
00060 #else
00061 # define INITIAL_BUFSZ_MULTIPLIER 2
00062 #endif
00063
00064 #define XDAS_FIELD_COUNT 33
00065
00076 static char * ex_substitute_vars(const char * script, const char ** msgflds)
00077 {
00078 char * p, * text;
00079 size_t scriptsz = strlen(script) + 1;
00080 size_t allocsz = scriptsz * INITIAL_BUFSZ_MULTIPLIER;
00081
00082 if ((text = (char *)malloc(allocsz)) == 0)
00083 {
00084 xdasd_log(0, "exec: Memory allocation failure.\n");
00085 return 0;
00086 }
00087 memcpy(text, script, scriptsz);
00088
00089 p = text;
00090 while ((p = strstr(p, "$XDAS")) != 0)
00091 {
00092 int fldnum = 0;
00093 size_t flen;
00094 size_t vlen = 5;
00095 const char * msg = msgflds[0];
00096 const char * limit = msgflds[XDAS_FIELD_COUNT] - 1;
00097
00098
00099 if (p[5] == '(')
00100 {
00101 while (p[vlen++] != ')') ;
00102 fldnum = strtoul(p + 6, 0, 0);
00103
00104 msg = msgflds[fldnum];
00105 limit = msgflds[fldnum + 1] - 1;
00106 }
00107
00108
00109 flen = limit - msg;
00110 if (scriptsz + flen - vlen > allocsz)
00111 {
00112 char * newtext;
00113 while (scriptsz + flen - vlen > allocsz)
00114 allocsz *= 2;
00115 if ((newtext = (char *)realloc(text, allocsz)) == 0)
00116 {
00117 xdasd_log(0, "exec: Memory allocation failure.\n");
00118 free(text);
00119 return 0;
00120 }
00121 p = newtext + (p - text);
00122 text = newtext;
00123 }
00124
00125
00126 memmove(p + flen, p + vlen, scriptsz - (p - text + vlen));
00127 memcpy(p, msg, flen);
00128 scriptsz += flen - vlen;
00129
00130
00131 p += flen;
00132 }
00133 return text;
00134 }
00135
00151 static int ex_exec_script(const char * script)
00152 {
00153 #ifdef _WIN32
00154
00155 # define SHELL_ENVAR "COMSPEC"
00156 # define DEFAULT_SHELL "CMD.EXE"
00157
00158 # if 0
00159
00160
00161
00162
00163 static char tmpath[MAX_PATH - 18] = "";
00164
00165 char cmdline[MAX_PATH + 3];
00166 PROCESS_INFORMATION pi;
00167 STARTUPINFO sui;
00168 DWORD pecode = 0;
00169 FILE * fp;
00170 char * shell;
00171
00172 if ((shell = getenv(SHELL_ENVAR)) == 0)
00173 shell = DEFAULT_SHELL;
00174
00175 if (*tmpath == 0 && GetTempPath(sizeof(tmpath), tmpath) == 0)
00176 {
00177 xdasd_log(0, "exec: Error getting TEMP directory, %ul.\n", GetLastError());
00178 return -1;
00179 }
00180 strcpy(cmdline, "/c ");
00181 if (GetTempFileName(tmpath, "XDAS", 0, cmdline + 3) == 0)
00182 {
00183 xdasd_log(0, "exec: Error generating temporary batch file name, %ul.\n",
00184 GetLastError());
00185 return -1;
00186 }
00187 strcat(cmdline, ".bat");
00188 if ((fp = fopen(cmdline, "w")) == 0)
00189 {
00190 xdasd_log(0, "exec: Unable to open temp batch file for write, %d - %s.\n",
00191 errno, strerror(errno));
00192 return -1;
00193 }
00194 fputs(script, fp);
00195 fclose(fp);
00196
00197 memset(&sui, 0, sizeof(sui));
00198 sui.cb = sizeof(sui);
00199 if (CreateProcess(shell, cmdline, 0, 0, TRUE, 0, 0, 0, &sui, &pi) == FALSE)
00200 {
00201 xdasd_log(0, "exec: Error creating child process, %ul.\n", GetLastError());
00202 pecode = (DWORD)(-1);
00203 }
00204 else
00205 {
00206 if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0)
00207 xdasd_log(0, "exec: Error waiting for child process, %ul.\n",
00208 GetLastError());
00209 else if (GetExitCodeProcess(pi.hProcess, &pecode) == FALSE)
00210 xdasd_log(0, "exec: Error retrieving child process status code, %ul.\n",
00211 GetLastError());
00212 CloseHandle(pi.hProcess);
00213 CloseHandle(pi.hThread);
00214 }
00215 _unlink(cmdline + 3);
00216 return (int)pecode;
00217
00218 # else
00219
00220
00221
00222
00223
00224
00225 SECURITY_ATTRIBUTES sa;
00226 PROCESS_INFORMATION pi;
00227 STARTUPINFOA sui;
00228 HANDLE hinrd = INVALID_HANDLE_VALUE;
00229 HANDLE hinwr = INVALID_HANDLE_VALUE;
00230 HANDLE houtrd = INVALID_HANDLE_VALUE;
00231 HANDLE houtwr = INVALID_HANDLE_VALUE;
00232 HANDLE hcurproc = GetCurrentProcess();
00233 DWORD pecode = (DWORD)(-1);
00234 BOOL status;
00235 char * shell;
00236
00237
00238 if ((shell = getenv(SHELL_ENVAR)) == 0)
00239 shell = DEFAULT_SHELL;
00240
00241
00242 memset(&sa, 0, sizeof(sa));
00243 sa.nLength = sizeof(sa);
00244 sa.bInheritHandle = TRUE;
00245
00246
00247 if ((status = CreatePipe(&houtrd, &houtwr, &sa, 0)) != FALSE)
00248 {
00249
00250 HANDLE htmp;
00251 if ((status = DuplicateHandle(hcurproc, houtrd, hcurproc,
00252 &htmp, 0, FALSE, DUPLICATE_SAME_ACCESS)) != FALSE)
00253 {
00254 CloseHandle(houtrd);
00255 houtrd = htmp;
00256 }
00257 }
00258 if (!status)
00259 {
00260 xdasd_log(0, "exec: Error creating child process STDOUT pipe, %ul.\n",
00261 GetLastError());
00262 goto errout;
00263 }
00264
00265
00266 if ((status = CreatePipe(&hinrd, &hinwr, &sa, 0)) != FALSE)
00267 {
00268
00269 HANDLE htmp;
00270 if ((status = DuplicateHandle(hcurproc, hinwr, hcurproc,
00271 &htmp, 0, FALSE, DUPLICATE_SAME_ACCESS)) != FALSE)
00272 {
00273 CloseHandle(hinwr);
00274 hinwr = htmp;
00275 }
00276 }
00277 if (!status)
00278 {
00279 xdasd_log(0, "exec: Error creating child process STDIN pipe, %ul.\n",
00280 GetLastError());
00281 goto errout;
00282 }
00283
00284
00285 memset(&sui, 0, sizeof(sui));
00286 sui.cb = sizeof(sui);
00287 sui.hStdInput = hinrd;
00288 sui.hStdOutput = houtwr;
00289 sui.hStdError = houtwr;
00290 sui.dwFlags |= STARTF_USESTDHANDLES;
00291
00292
00293 if (!CreateProcessA(shell, 0, 0, 0, TRUE, 0, 0, 0, &sui, &pi))
00294 xdasd_log(0, "exec: Error creating child process, %ul.\n",
00295 GetLastError());
00296 else
00297 {
00298 DWORD bytes_read, bytes_written;
00299 char buf[1024];
00300
00301 CloseHandle(hinrd); hinrd = INVALID_HANDLE_VALUE;
00302 CloseHandle(houtwr); houtwr = INVALID_HANDLE_VALUE;
00303
00304
00305 if (!WriteFile(hinwr, script, (DWORD)strlen(script), &bytes_written, 0))
00306 {
00307 xdasd_log(0, "exec: Error writing script to child process, %ul.\n",
00308 GetLastError());
00309 goto errout;
00310 }
00311
00312
00313
00314 CloseHandle(hinwr); hinwr = INVALID_HANDLE_VALUE;
00315
00316
00317 while (ReadFile(houtrd, buf, sizeof(buf), &bytes_read, 0) && bytes_read)
00318 # ifdef LOG_TO_STDOUT
00319 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf,
00320 bytes_read, &bytes_written, 0)
00321 # endif
00322 ;
00323
00324
00325 CloseHandle(houtrd); houtrd = INVALID_HANDLE_VALUE;
00326
00327 pecode = 0;
00328
00329
00330 if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0)
00331 xdasd_log(0, "exec: Error waiting for child process, %ul.\n",
00332 GetLastError());
00333 else if (GetExitCodeProcess(pi.hProcess, &pecode) == FALSE)
00334 xdasd_log(0, "exec: Error retrieving child process status "
00335 "code, %ul.\n", GetLastError());
00336
00337
00338 CloseHandle(pi.hProcess);
00339 CloseHandle(pi.hThread);
00340 }
00341
00342 errout:
00343 if (hinwr != INVALID_HANDLE_VALUE) CloseHandle(hinwr);
00344 if (houtwr != INVALID_HANDLE_VALUE) CloseHandle(houtwr);
00345 if (hinrd != INVALID_HANDLE_VALUE) CloseHandle(hinrd);
00346 if (houtrd != INVALID_HANDLE_VALUE) CloseHandle(houtrd);
00347
00348 return (int)pecode;
00349
00350 # endif
00351
00352 #else
00353
00354 # define SHELL_ENVAR "SHELL"
00355 # define DEFAULT_SHELL "/bin/sh"
00356
00357 int rv = -1;
00358 pid_t pid;
00359 int fdstdout[2] = {-1, -1};
00360 int fdstdin[2] = {-1, -1};
00361 char * shell;
00362
00363 if ((shell = getenv(SHELL_ENVAR)) == 0)
00364 shell = DEFAULT_SHELL;
00365
00366
00367 if (pipe(fdstdout) == -1 || pipe(fdstdin) == -1)
00368 {
00369 xdasd_log(0, "exec: Error creating child process pipes, (%d) %s.\n",
00370 errno, strerror(errno));
00371 close(fdstdout[0]); close(fdstdout[1]);
00372 return -1;
00373 }
00374
00375
00376 if ((pid = fork()) < 0)
00377 {
00378 xdasd_log(0, "exec: Error creating child process, (%d) %s.\n",
00379 errno, strerror(errno));
00380 close(fdstdin[0]); close(fdstdin[1]);
00381 close(fdstdout[0]); close(fdstdout[1]);
00382 return -1;
00383 }
00384
00385 if (pid > 0)
00386 {
00387 int status;
00388 int bytes;
00389 char buf[1024];
00390
00391
00392 close(fdstdin[0]);
00393 close(fdstdout[1]);
00394
00395
00396 write(fdstdin[1], script, strlen(script));
00397 close(fdstdin[1]);
00398
00399
00400 while ((bytes = read(fdstdout[0], buf, sizeof(buf))) > 0)
00401 # ifdef LOG_TO_STDOUT
00402 printf("%.*s", bytes, buf)
00403 # endif
00404 ;
00405
00406 close(fdstdout[0]);
00407
00408
00409 if (waitpid(pid, &status, 0) >= 0)
00410 rv = WEXITSTATUS(status);
00411 }
00412 else
00413 {
00414
00415 close(fdstdin[1]);
00416 close(fdstdout[0]);
00417
00418
00419 if (fdstdin[0] != STDIN_FILENO)
00420 {
00421 int fdtmp = dup2(fdstdin[0], STDIN_FILENO);
00422 close(fdstdin[0]);
00423 if (fdtmp != STDIN_FILENO)
00424 exit(-1);
00425 }
00426
00427
00428 if (fdstdout[1] != STDOUT_FILENO)
00429 {
00430 dup2(fdstdout[1], STDOUT_FILENO);
00431 close(fdstdout[1]);
00432 }
00433
00434
00435 if (STDOUT_FILENO != STDERR_FILENO)
00436 dup2(STDOUT_FILENO, STDERR_FILENO);
00437
00438
00439 if (execl(shell, 0) < 0)
00440 exit(-1);
00441
00442
00443 }
00444 return rv;
00445
00446 #endif
00447 }
00448
00480 int xdasd_exec(const char * script, const char ** msgflds)
00481 {
00482 int rv;
00483 char * text;
00484
00485 if ((text = ex_substitute_vars(script, msgflds)) == 0)
00486 return -1;
00487
00488 rv = ex_exec_script(text);
00489
00490 free(text);
00491 return rv;
00492 }
00493
00494
00495
00496 #ifdef XDASD_EXEC_TEST
00497
00498 #include <stdarg.h>
00499
00506 void xdasd_log(int level, const char * fmt, ... )
00507 {
00508 #ifdef LOG_TO_STDOUT
00509 va_list args;
00510 va_start(args, fmt);
00511 vprintf(fmt, args);
00512 va_end(args);
00513 #else
00514 (void)fmt;
00515 #endif
00516 }
00517
00538 int main(int argc, char ** argv)
00539 {
00540 static char * script =
00541 {
00542 "echo \"Replace $XDAS with entire message (really long text).\"\n"
00543 "echo \"Replace $XDAS(10) with the 10th field (< than the var).\"\n"
00544 "echo \"Replace $XDAS(11) with the 11th field (> than the var).\""
00545 };
00546 static char * msg =
00547 "HDR:"
00548 "00A8:"
00549 "OX1:"
00550 "2234934821:"
00551 ":"
00552 ":"
00553 "time.nist.gov:"
00554 "MST7MDT:"
00555 "0x10000001:"
00556 "0:"
00557 "ORG:"
00558 "org_location_name:"
00559 "org_location_address:"
00560 "org_service_type:"
00561 "org_auth_authority:"
00562 "org_principal_name:"
00563 "org_principal_id:"
00564 "INT:"
00565 "int_auth_authority:"
00566 "int_domain_specific_name:"
00567 "int_domain_specific_id:"
00568 "TGT:"
00569 "tgt_location_name:"
00570 "tgt_location_address:"
00571 "tgt_service_type:"
00572 "tgt_auth_authority:"
00573 "tgt_principal_name:"
00574 "tgt_principal_id:"
00575 "SRC:"
00576 "pointer_to_source_domain:"
00577 "EVT:"
00578 "event_specific_information:"
00579 "END";
00580
00581 unsigned i;
00582 char * cp = msg;
00583 const char * msgflds[XDAS_FIELD_COUNT + 1];
00584
00585 (void)argc;
00586 (void)argv;
00587
00588 for (i = 0; i < XDAS_FIELD_COUNT; i++)
00589 {
00590 msgflds[i] = cp;
00591 while (*cp && *cp != ':')
00592 cp++;
00593 cp++;
00594 }
00595 msgflds[i] = cp;
00596
00597 return xdasd_exec(script, msgflds);
00598 }
00599
00600 #endif
00601