diff -r 000000000000 -r 044383f39525 sbsv2/raptor/util/talon/talon.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbsv2/raptor/util/talon/talon.c Tue Oct 27 16:36:35 2009 +0000 @@ -0,0 +1,613 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "talon_process.h" +#include "sema.h" +#include "buffer.h" +#include "../config.h" + +/* The output semaphore. */ +sbs_semaphore talon_sem; + +#define TALON_ATTEMPT_STRMAX 32 +#define RECIPETAG_STRMAX 2048 +#define STATUS_STRMAX 100 + +#define TALONDELIMITER '|' +#define VARNAMEMAX 100 +#define VARVALMAX 1024 + + +#include "log.h" + +#ifdef HAS_MSVCRT +/* Make all output handling binary */ +unsigned int _CRT_fmode = _O_BINARY; +#endif + +double getseconds(void) +{ + struct timeval tp; + gettimeofday(&tp, NULL); + + return (double)tp.tv_sec + ((double)tp.tv_usec)/1000000.0L; +} + +void talon_setenv(char name[], char val[]) +{ +#if defined(HAS_GETENVIRONMENTVARIABLE) + SetEnvironmentVariableA(name,val); +#elif defined(HAS_GETENV) + setenv(name,val, 1); +#else +# error "Need a function for setting environment variables" +#endif +} + + +#define TALON_MAXENV 4096 +char * talon_getenv(char name[]) +{ +#if defined(HAS_SETENV) + char *val = getenv(name); + char *dest = NULL; + + if (val) + { + dest = malloc(strlen(val) + 1); + if (dest) + { + strcpy(dest,val); + } + } + return dest; +#elif defined(HAS_SETENVIRONMENTVARIABLE) + char *val = malloc(TALON_MAXENV); + if (0 != GetEnvironmentVariableA(name,val,TALON_MAXENV-1)) + return val; + else + return NULL; +#else +# error "Need a function for setting environment variables" +#endif +} + +void prependattributes(buffer *b, char *attributes) +{ + char recipetag[RECIPETAG_STRMAX]; + char *rt; + char envvarname[VARNAMEMAX]; + char *att; + + + strcpy(recipetag, " 0 && recipe[recipelen - 1] == '"') + recipe[recipelen - 1] = '\0'; /* remove trailing quote */ + } + else + { + /* there was no -c so extract the argument as a filename */ + + recipe = strstr(commandline, "talon"); + if (recipe) + { + /* find the first space */ + while (!isspace(*recipe) && *recipe != '\0') + recipe++; + /* skip past the spaces */ + while (isspace(*recipe)) + recipe++; + + recipe = read_recipe_from_file(recipe); + + if (!recipe) + { + error("talon: error: bad script file in shell call '%s'\n", commandline); + return 1; + } + } + else + { + error("talon: error: no 'talon' in shell call '%s'\n", commandline); + return 1; + } + } +#else + /* + * The command line should be either, + * talon -c "some shell commands" + * or + * talon shell_script_file + * + * talon could be an absolute path and may have a .exe extension. + */ + switch (argc) + { + case 2: + recipe = read_recipe_from_file(argv[1]); + break; + case 3: + if (strcmp("-c", argv[1]) != 0) + { + error("talon: error: %s\n", "usage is 'talon -c command' or 'talon script_filename'"); + return 1; + } + recipe = argv[2]; + break; + default: + error("talon: error: %s\n", "usage is 'talon -c command' or 'talon script_filename'"); + return 1; + } +#endif + + /* did we get a recipe at all? */ + if (!recipe) + { + error("talon: error: %s", "no recipe supplied to the shell.\n"); + return 1; + } + + /* remove any leading white space on the recipe */ + while (isspace(*recipe)) + recipe++; + + /* turn debugging on? */ + char *debugstr=talon_getenv("TALON_DEBUG"); + + if (debugstr) + { + loglevel=LOGDEBUG; + free(debugstr); debugstr=NULL; + } + + DEBUG(("talon: recipe: %s\n", recipe)); + + + char varname[VARNAMEMAX]; + char varval[VARVALMAX]; + int dotagging = 0; + int force_descramble_off = 0; + + char *rp = recipe; + if (*rp == TALONDELIMITER) { + dotagging = 1; + + /* there are some talon-specific settings + * in the command which must be stripped */ + rp++; + char *out = varname; + char *stopout = varname + VARNAMEMAX - 1; + DEBUG(("talon: parameters found\n")); + while (*rp != '\0') + { + + switch (*rp) { + case '=': + *out = '\0'; + DEBUG(("talon: varname: %s\n",varname)); + out = varval; + stopout = varval + VARVALMAX - 1; + break; + case ';': + *out = '\0'; + DEBUG(("talon: varval: %s\n",varval)); + talon_setenv(varname, varval); + out = varname; + stopout = varname + VARNAMEMAX - 1; + break; + default: + *out = *rp; + if (out < stopout) + out++; + break; + } + + if (*rp == TALONDELIMITER) + { + rp++; + break; + } + + rp++; + } + } else { + /* This is probably a $(shell) statement + * in make so no descrambling needed and + * tags are definitely not wanted as they + * would corrupt the expected output*/ + force_descramble_off = 1; + } + + + /* Now take settings from the environment (having potentially modified it) */ + if (talon_getenv("TALON_DEBUG")) + loglevel=LOGDEBUG; + + + int enverrors = 0; + + char *shell = talon_getenv("TALON_SHELL"); + if (!shell) + { + error("error: %s", "TALON_SHELL not set in environment\n"); + enverrors++; + } + + int timeout = -1; + char *timeout_str = talon_getenv("TALON_TIMEOUT"); + if (timeout_str) + { + timeout = atoi(timeout_str); + free(timeout_str); timeout_str = NULL; + } + + char *buildid = talon_getenv("TALON_BUILDID"); + if (!buildid) + { + error("error: %s", "TALON_BUILDID not set in environment\n"); + enverrors++; + } + + char *attributes = talon_getenv("TALON_RECIPEATTRIBUTES"); + if (!attributes) + { + error("error: %s", "TALON_RECIPEATTRIBUTES not set in environment\n"); + enverrors++; + } + + + int max_retries = 0; + char *retries_str = talon_getenv("TALON_RETRIES"); + if (retries_str) + { + max_retries = atoi(retries_str); + free(retries_str); retries_str = NULL; + } + + + int descramble = 0; + if (! force_descramble_off ) + { + char *descramblestr = talon_getenv("TALON_DESCRAMBLE"); + if (descramblestr) + { + if (*descramblestr == '0') + descramble = 0; + else + descramble = 1; + + free(descramblestr); descramblestr = NULL; + } + } + + + + /* Talon can look in a flags variable to alter it's behaviour */ + int force_success = 0; + char *flags_str = talon_getenv("TALON_FLAGS"); + if (flags_str) + { + int c; + for (c=0; flags_str[c] !=0; c++) + flags_str[c] = tolower(flags_str[c]); + + if (strstr(flags_str, "forcesuccess")) + force_success = 1; + + /* don't put or returncode; + + if (dotagging) + { + char *forcesuccessstr = force_success == 0 ? "" : " forcesuccess='FORCESUCCESS'"; + + if (p->returncode != 0) + { + char *exitstr = retries > 0 ? "retry" : "failed"; + snprintf(status, STATUS_STRMAX - 1, "\n", exitstr, p->returncode, attempt, forcesuccessstr ); + } else { + snprintf(status, STATUS_STRMAX - 1, "\n", attempt, forcesuccessstr ); + } + status[STATUS_STRMAX-1] = '\0'; + + snprintf(timestat, STATUS_STRMAX - 1, "\n", 11); + } + + unsigned int iterator = 0; + byteblock *bb; + + if (descramble) + sema_wait(&talon_sem); + while ((bb = buffer_getbytes(p->output, &iterator))) + { + write(STDOUT_FILENO, &bb->byte0, bb->fill); + } + if (descramble) + sema_release(&talon_sem); + + + if (p->returncode == 0 || force_success) + { + process_free(&p); + break; + } + + process_free(&p); + } else { + error("error: failed to run shell: %s: check the SHELL environment variable.\n", args[0]); + return 1; + } + + retries--; + } + while (retries >= 0); + + if (buildid) free(buildid); buildid = NULL; + if (attributes) free(attributes); attributes = NULL; + if (shell) free(shell); shell = NULL; + + if (force_success) + return 0; + else + return talon_returncode; +}