bool FlingState::evaluateMatrix(SkMatrix* matrix) {
    if (!fActive) {
        return false;
    }

    const float t =  getseconds() - fTime0;
    const float MIN_SPEED = 2;
    const float K0 = 5.0;
    const float K1 = 0.02;
    const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1);
    if (speed <= MIN_SPEED) {
        fActive = false;
        return false;
    }
    float dist = (fSpeed0 - speed) / K0;

//    printf("---- time %g speed %g dist %g\n", t, speed, dist);
    float tx = fDirection.fX * dist;
    float ty = fDirection.fY * dist;
    if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) {
        tx = sk_float_round2int(tx);
        ty = sk_float_round2int(ty);
    }
    matrix->setTranslate(tx, ty);
//    printf("---- evaluate (%g %g)\n", tx, ty);

    return true;
}
示例#2
0
  double X(measure_execution_time)(plan *pln, const problem *p)
  {
       seconds begin, now;
       double t, tmax, tmin;
       int iter;
       int repeat;

       AWAKE(pln, 1);
       p->adt->zero(p);

  start_over:
       for (iter = 1; iter; iter *= 2) {
	    tmin = 1.0E10;
	    tmax = -1.0E10;

	    begin = getseconds();
	    /* repeat the measurement TIME_REPEAT times */
	    for (repeat = 0; repeat < TIME_REPEAT; ++repeat) {
		 t = measure(pln, p, iter);

		 if (t < 0)
		      goto start_over;

		 if (t < tmin)
		      tmin = t;
		 if (t > tmax)
		      tmax = t;

		 /* do not run for too long */
		 now = getseconds();
		 t = elapsed_sec(now, begin);

		 if (t > FFTW_TIME_LIMIT)
		      break;
	    }

	    if (tmin >= TIME_MIN) {
		 tmin /= (double) iter;
		 tmax /= (double) iter;
		 AWAKE(pln, 0);
		 return tmin;
	    }
       }
       goto start_over; /* may happen if timer is screwed up */
  }
void FlingState::reset(float sx, float sy) {
    fActive = true;
    fDirection.set(sx, sy);
    fSpeed0 = SkPoint::Normalize(&fDirection);
    fSpeed0 = pin_max_fling(fSpeed0);
    fTime0 = getseconds();

    unit_axis_align(&fDirection);
//    printf("---- speed %g dir %g %g\n", fSpeed0, fDirection.fX, fDirection.fY);
}
示例#4
0
文件: th-dns.c 项目: jackuzzy/NewBox
void *dns_child_thread(struct host_data *host)
{
	unsigned int newip;

	pthread_mutex_lock(&prg.lockdns);
	newip = hostname2ip(host->name);
	pthread_mutex_unlock(&prg.lockdns);
	usleep(10000);
	if (!newip) {
		//debugf(" dns: failed to get address for %s\n",host->name);
		host->checkiptime = getseconds() + 60;
		host->ip = newip;
	}
	else if (newip!=host->ip) {
		host->checkiptime = getseconds() + 300;
		host->ip = newip;
		//debugf(" dns: %s --> %s\n", host->name, ip2string(host->ip));
	}
	else {
		host->checkiptime = getseconds() + 600;
		//debugf(" dns: %s == %s\n", host->name, ip2string(host->ip));
	}
	return NULL;
}
示例#5
0
文件: th-dns.c 项目: jackuzzy/NewBox
void *dns_thread(void *param)
{
	do {
		pthread_mutex_lock(&prg.lockdnsth);

		struct host_data *host = cfg.host;
		while (host) {
			if (host->checkiptime<=getseconds()) {
				//pthread_t new_tid;
				//create_prio_thread(&new_tid, (threadfn)dns_child_thread,host, 50);
				dns_child_thread( host );
			}
			host = host->next;
		}

		pthread_mutex_unlock(&prg.lockdnsth);
		sleep(10);
	} while (1);
}
示例#6
0
文件: bench.c 项目: dolphinking/blosc
int main(int argc, char *argv[]) {
  int single = 1;
  int suite = 0;
  int hard_suite = 0;
  int extreme_suite = 0;
  int debug_suite = 0;
  int nthreads = 4;                     /* The number of threads */
  int size = 2*MB;                      /* Buffer size */
  int elsize = 8;                       /* Datatype size */
  int rshift = 19;                      /* Significant bits */
  int workingset = 256*MB;              /* The maximum allocated memory */
  int nthreads_, size_, elsize_, rshift_, i;
  FILE * output_file = stdout;
  struct timeval last, current;
  float totaltime;
  char *usage = "Usage: bench ['single' | 'suite' | 'hardsuite' | 'extremesuite' | 'debugsuite'] [nthreads [bufsize(bytes) [typesize [sbits ]]]]";


  if (argc == 1) {
    printf("%s\n", usage);
    exit(1);
  }

  if (strcmp(argv[1], "single") == 0) {
    single = 1;
  }
  else if (strcmp(argv[1], "suite") == 0) {
    suite = 1;
  }
  else if (strcmp(argv[1], "hardsuite") == 0) {
    hard_suite = 1;
    workingset = 64*MB;
    /* Values here are ending points for loops */
    nthreads = 2;
    size = 8*MB;
    elsize = 32;
    rshift = 32;
  }
  else if (strcmp(argv[1], "extremesuite") == 0) {
    extreme_suite = 1;
    workingset = 32*MB;
    niter = 1;
    /* Values here are ending points for loops */
    nthreads = 4;
    size = 16*MB;
    elsize = 32;
    rshift = 32;
  }
  else if (strcmp(argv[1], "debugsuite") == 0) {
    debug_suite = 1;
    workingset = 32*MB;
    niter = 1;
    /* Warning: values here are starting points for loops.  This is
       useful for debugging. */
    nthreads = 1;
    size = 16*KB;
    elsize = 1;
    rshift = 0;
  }
  else {
    printf("%s\n", usage);
    exit(1);
  }

  if (argc >= 3) {
    nthreads = atoi(argv[2]);
  }
  if (argc >= 4) {
    size = atoi(argv[3]);
  }
  if (argc >= 5) {
    elsize = atoi(argv[4]);
  }
  if (argc >= 6) {
    rshift = atoi(argv[5]);
  }

  if ((argc >= 7) || !(single || suite || hard_suite || extreme_suite)) {
    printf("%s\n", usage);
    exit(1);
  }

  nchunks = get_nchunks(size, workingset);
  gettimeofday(&last, NULL);

  blosc_init();

  if (suite) {
    for (nthreads_=1; nthreads_ <= nthreads; nthreads_++) {
        do_bench(nthreads_, size, elsize, rshift, output_file);
    }
  }
  else if (hard_suite) {
    /* Let's start the rshift loop by 4 so that 19 is visited.  This
       is to allow a direct comparison with the plain suite, that runs
       precisely at 19 significant bits. */
    for (rshift_ = 4; rshift_ <= rshift; rshift_ += 5) {
      for (elsize_ = 1; elsize_ <= elsize; elsize_ *= 2) {
        /* The next loop is for getting sizes that are not power of 2 */
        for (i = -elsize_; i <= elsize_; i += elsize_) {
          for (size_ = 32*KB; size_ <= size; size_ *= 2) {
            nchunks = get_nchunks(size_+i, workingset);
    	    niter = 1;
            for (nthreads_ = 1; nthreads_ <= nthreads; nthreads_++) {
              do_bench(nthreads_, size_+i, elsize_, rshift_, output_file);
              gettimeofday(&current, NULL);
              totaltime = getseconds(last, current);
              printf("Elapsed time:\t %6.1f s.  Processed data: %.1f GB\n",
                     totaltime, totalsize / GB);
            }
          }
        }
      }
    }
  }
  else if (extreme_suite) {
    for (rshift_ = 0; rshift_ <= rshift; rshift_++) {
      for (elsize_ = 1; elsize_ <= elsize; elsize_++) {
        /* The next loop is for getting sizes that are not power of 2 */
        for (i = -elsize_*2; i <= elsize_*2; i += elsize_) {
          for (size_ = 32*KB; size_ <= size; size_ *= 2) {
            nchunks = get_nchunks(size_+i, workingset);
            for (nthreads_ = 1; nthreads_ <= nthreads; nthreads_++) {
              do_bench(nthreads_, size_+i, elsize_, rshift_, output_file);
              gettimeofday(&current, NULL);
              totaltime = getseconds(last, current);
              printf("Elapsed time:\t %6.1f s.  Processed data: %.1f GB\n",
                     totaltime, totalsize / GB);
            }
          }
        }
      }
    }
  }
  else if (debug_suite) {
    for (rshift_ = rshift; rshift_ <= 32; rshift_++) {
      for (elsize_ = elsize; elsize_ <= 32; elsize_++) {
        /* The next loop is for getting sizes that are not power of 2 */
        for (i = -elsize_*2; i <= elsize_*2; i += elsize_) {
          for (size_ = size; size_ <= 16*MB; size_ *= 2) {
            nchunks = get_nchunks(size_+i, workingset);
            for (nthreads_ = nthreads; nthreads_ <= 6; nthreads_++) {
              do_bench(nthreads_, size_+i, elsize_, rshift_, output_file);
              gettimeofday(&current, NULL);
              totaltime = getseconds(last, current);
              printf("Elapsed time:\t %6.1f s.  Processed data: %.1f GB\n",
                     totaltime, totalsize / GB);
            }
          }
        }
      }
    }
  }
  /* Single mode */
  else {
    do_bench(nthreads, size, elsize, rshift, output_file);
  }

  /* Print out some statistics */
  gettimeofday(&current, NULL);
  totaltime = getseconds(last, current);
  printf("\nRound-trip compr/decompr on %.1f GB\n", totalsize / GB);
  printf("Elapsed time:\t %6.1f s, %.1f MB/s\n",
         totaltime, totalsize*2*1.1/(MB*totaltime));

  /* Free blosc resources */
  blosc_free_resources();
  blosc_destroy();
  return 0;
}
示例#7
0
文件: bench.c 项目: dolphinking/blosc
/* Given two timeval stamps, return the time per chunk in usec */
float get_usec_chunk(struct timeval last, struct timeval current) {
  return (float)(getseconds(last, current)/(niter*nchunks)*1e6);
}
示例#8
0
int main(int argc, char *argv[]) {
  char compressor[32];
  char shuffle[32] = "shuffle";
  char bsuite[32];
  int single = 1;
  int suite = 0;
  int hard_suite = 0;
  int extreme_suite = 0;
  int debug_suite = 0;
  int nthreads = 4;                     /* The number of threads */
  int size = 2*MB;                      /* Buffer size */
  int elsize = 8;                       /* Datatype size */
  int rshift = 19;                      /* Significant bits */
#if defined(__arm__)
  int workingset = 64*MB;              /* The maximum allocated memory */
#else
  int workingset = 256*MB;              /* The maximum allocated memory */
#endif
  int nthreads_, size_, elsize_, rshift_, i;
  FILE * output_file = stdout;
  blosc_timestamp_t last, current;
  float totaltime;
  char usage[256];

  print_compress_info();

  strncpy(usage, "Usage: bench [blosclz | lz4 | lz4hc | snappy | zlib] "
	  "[noshuffle | shuffle | bitshuffle] "
          "[single | suite | hardsuite | extremesuite | debugsuite] "
          "[nthreads] [bufsize(bytes)] [typesize] [sbits]", 255);

  if (argc < 2) {
    printf("%s\n", usage);
    exit(1);
  }

  strcpy(compressor, argv[1]);

  if (strcmp(compressor, "blosclz") != 0 &&
      strcmp(compressor, "lz4") != 0 &&
      strcmp(compressor, "lz4hc") != 0 &&
      strcmp(compressor, "snappy") != 0 &&
      strcmp(compressor, "zlib") != 0) {
    printf("No such compressor: '%s'\n", compressor);
    printf("%s\n", usage);
    exit(2);
  }

  if (argc >= 3) {
      strcpy(shuffle, argv[2]);
      if (strcmp(shuffle, "shuffle") != 0 &&
          strcmp(shuffle, "bitshuffle") != 0 &&
          strcmp(shuffle, "noshuffle") != 0) {
	printf("No such shuffler: '%s'\n", shuffle);
	printf("%s\n", usage);
	exit(2);
     }
  }

  if (argc < 4)
    strcpy(bsuite, "single");
  else
    strcpy(bsuite, argv[3]);

  if (strcmp(bsuite, "single") == 0) {
    single = 1;
  }
  else if (strcmp(bsuite, "test") == 0) {
    single = 1;
    workingset /= 2;
  }
  else if (strcmp(bsuite, "suite") == 0) {
    suite = 1;
  }
  else if (strcmp(bsuite, "hardsuite") == 0) {
    hard_suite = 1;
    workingset /= 4;
    /* Values here are ending points for loops */
    nthreads = 2;
    size = 8*MB;
    elsize = 32;
    rshift = 32;
  }
  else if (strcmp(bsuite, "extremesuite") == 0) {
    extreme_suite = 1;
    workingset /= 8;
    niter = 1;
    /* Values here are ending points for loops */
    nthreads = 4;
    size = 16*MB;
    elsize = 32;
    rshift = 32;
  }
  else if (strcmp(bsuite, "debugsuite") == 0) {
    debug_suite = 1;
    workingset /= 8;
    niter = 1;
    /* Warning: values here are starting points for loops.  This is
       useful for debugging. */
    nthreads = 1;
    size = 16*KB;
    elsize = 1;
    rshift = 0;
  }
  else {
    printf("%s\n", usage);
    exit(1);
  }

  printf("Using compressor: %s\n", compressor);
  printf("Using shuffle type: %s\n", shuffle);
  printf("Running suite: %s\n", bsuite);

  if (argc >= 5) {
    nthreads = atoi(argv[4]);
  }
  if (argc >= 6) {
    size = atoi(argv[5]);
  }
  if (argc >= 7) {
    elsize = atoi(argv[6]);
  }
  if (argc >= 8) {
    rshift = atoi(argv[7]);
  }

  if ((argc >= 9) || !(single || suite || hard_suite || extreme_suite)) {
    printf("%s\n", usage);
    exit(1);
  }

  nchunks = get_nchunks(size, workingset);
  blosc_set_timestamp(&last);

  blosc_init();

  if (suite) {
    for (nthreads_=1; nthreads_ <= nthreads; nthreads_++) {
      do_bench(compressor, shuffle, nthreads_, size, elsize, rshift, output_file);
    }
  }
  else if (hard_suite) {
    /* Let's start the rshift loop by 4 so that 19 is visited.  This
       is to allow a direct comparison with the plain suite, that runs
       precisely at 19 significant bits. */
    for (rshift_ = 4; rshift_ <= rshift; rshift_ += 5) {
      for (elsize_ = 1; elsize_ <= elsize; elsize_ *= 2) {
        /* The next loop is for getting sizes that are not power of 2 */
        for (i = -elsize_; i <= elsize_; i += elsize_) {
          for (size_ = 32*KB; size_ <= size; size_ *= 2) {
            nchunks = get_nchunks(size_+i, workingset);
    	    niter = 1;
            for (nthreads_ = 1; nthreads_ <= nthreads; nthreads_++) {
              do_bench(compressor, shuffle, nthreads_, size_+i, elsize_, rshift_, output_file);
              blosc_set_timestamp(&current);
              totaltime = (float)getseconds(last, current);
              printf("Elapsed time:\t %6.1f s.  Processed data: %.1f GB\n",
                     totaltime, totalsize / GB);
            }
          }
        }
      }
    }
  }
  else if (extreme_suite) {
    for (rshift_ = 0; rshift_ <= rshift; rshift_++) {
      for (elsize_ = 1; elsize_ <= elsize; elsize_++) {
        /* The next loop is for getting sizes that are not power of 2 */
        for (i = -elsize_*2; i <= elsize_*2; i += elsize_) {
          for (size_ = 32*KB; size_ <= size; size_ *= 2) {
            nchunks = get_nchunks(size_+i, workingset);
            for (nthreads_ = 1; nthreads_ <= nthreads; nthreads_++) {
              do_bench(compressor, shuffle, nthreads_, size_+i, elsize_, rshift_, output_file);
              blosc_set_timestamp(&current);
              totaltime = (float)getseconds(last, current);
              printf("Elapsed time:\t %6.1f s.  Processed data: %.1f GB\n",
                     totaltime, totalsize / GB);
            }
          }
        }
      }
    }
  }
  else if (debug_suite) {
    for (rshift_ = rshift; rshift_ <= 32; rshift_++) {
      for (elsize_ = elsize; elsize_ <= 32; elsize_++) {
        /* The next loop is for getting sizes that are not power of 2 */
        for (i = -elsize_*2; i <= elsize_*2; i += elsize_) {
          for (size_ = size; size_ <= 16*MB; size_ *= 2) {
            nchunks = get_nchunks(size_+i, workingset);
            for (nthreads_ = nthreads; nthreads_ <= 6; nthreads_++) {
              do_bench(compressor, shuffle, nthreads_, size_+i, elsize_, rshift_, output_file);
              blosc_set_timestamp(&current);
              totaltime = (float)getseconds(last, current);
              printf("Elapsed time:\t %6.1f s.  Processed data: %.1f GB\n",
                     totaltime, totalsize / GB);
            }
          }
        }
      }
    }
  }
  /* Single mode */
  else {
    do_bench(compressor, shuffle, nthreads, size, elsize, rshift, output_file);
  }

  /* Print out some statistics */
  blosc_set_timestamp(&current);
  totaltime = (float)getseconds(last, current);
  printf("\nRound-trip compr/decompr on %.1f GB\n", totalsize / GB);
  printf("Elapsed time:\t %6.1f s, %.1f MB/s\n",
         totaltime, totalsize*2*1.1/(MB*totaltime));

  /* Free blosc resources */
  blosc_free_resources();
  blosc_destroy();
  return 0;
}
示例#9
0
void *cs_connect_srv_th(struct cs_server_data *srv)
{
	int fd;
	int keep = 9000;
	// --->> FAST THREAD
	srv->keepalivetime = GetTickCount();
	struct host_data *host = srv->host;
	uint ip = host->ip;
	if (!ip) ip = host->clip;
	fd =  CreateClientSockTcp_nonb(ip, srv->port);
	if (fd<0) {
		// Setup Host Checking ip time
		if ( host->checkiptime > (getseconds()+60) ) host->checkiptime = getseconds()+60;
		//
		srv->error = errno;
		debugf(" server: socket connection failed to server (%s:%d)\n", srv->host->name,srv->port);
		if (errno==ECONNREFUSED) {
			keep = 60000;
			static char msg[]= "No-one listening on the remote address";
			srv->statmsg = msg;
		}
		else if (errno==ENETUNREACH) {
			static char msg[]= "Network is unreachable";
			srv->statmsg = msg;
		}
		else if (errno==ETIMEDOUT) {
			keep = 5000;
			static char msg[]= "Timeout while attempting connection";
			srv->statmsg = msg;
		}
		else {
			static char msg[]= "socket connection failed";
			srv->statmsg = msg;
		}
		srv->keepalivesent = keep;
		return NULL;
	}
	if (srv->keepalivesent<60000) srv->keepalivesent = srv->keepalivesent+keep;
	srv->error = 0; // No error

	if (srv->type==TYPE_NEWCAMD) {
		if ( cs_connect_srv(srv,fd)!=0 ) {
			debugf(" server: connection failed to newcamd server (%s:%d)\n", srv->host->name,srv->port);
			close(fd);
		}
	}
#ifdef CCCAM_CLI
	else if (srv->type==TYPE_CCCAM) {
		if ( cc_connect_srv(srv,fd)!=0 ) {
			debugf(" server: connection failed to CCcam server (%s:%d)\n", srv->host->name,srv->port);
			close(fd);
		}
	}
#endif
#ifdef RADEGAST_CLI
	else if (srv->type==TYPE_RADEGAST) {
		if ( rdgd_connect_srv(srv,fd)!=0 ) {
			debugf(" server: connection failed to Radegast server (%s:%d)\n", srv->host->name,srv->port);
			close(fd);
		}
	}
#endif
	else close(fd);
	return NULL;
}
示例#10
0
int main(int argc, char *argv[])
{
	/* find the argument to -c then strip the talon related front section */

	char *recipe = NULL;
	int talon_returncode = 0;

#ifdef HAS_WINSOCK2
	WSADATA wsaData;

	WSAStartup(MAKEWORD(2,2), &wsaData);

	/* We ignore the result as we are only doing this to use gethostname
	   and if that fails then leaving the host attribute blank is perfectly
	   acceptable.
	*/

#endif

#ifdef HAS_GETCOMMANDLINE
	char *commandline= GetCommandLine();
	/*
	 * 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.
	 */

	
	recipe = chompCommand(commandline);
	if (recipe)
	{
		/* there was a -c so extract the quoted commands */

		int recipelen = strlen(recipe);
		if (recipelen > 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));

	/* Make sure that the agent's hostname can be put into the host attribute */
	char hostname[HOSTNAME_MAX];
	int hostresult=0;
	
	hostresult = gethostname(hostname, HOSTNAME_MAX-1);
	if (0 != hostresult)
	{
		DEBUG(("talon: failed to get hostname: %d\n", hostresult));
		hostname[0] = '\0';
	}

	talon_setenv("HOSTNAME", hostname);
	DEBUG(("talon: setenv: hostname: %s\n", hostname));

	
	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;
		}
	}

	/* check command line lengths if a maximum is supplied */
	int shell_cl_max = 0;
	char *shell_cl_max_str = talon_getenv("TALON_SHELL_CL_MAX");
	if (shell_cl_max_str)
	{
		shell_cl_max = atoi(shell_cl_max_str);
		free(shell_cl_max_str); shell_cl_max_str = NULL;
	}


	/* Talon can look in a flags variable to alter its 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 <recipe> or <CDATA<[[ tags around the output. e.g. if it's XML already*/
		if (strstr(flags_str, "rawoutput"))
		{
			dotagging = 0;
		}

		free(flags_str); flags_str = NULL;
	}	

	/* Talon subprocesses need to have the "correct" shell variable set. */
	talon_setenv("SHELL", shell); 

	/* we have allowed some errors to build up so that the user
	 * can see all of them before we stop and force the user 
	 * to fix them
	 */
	if (enverrors)
	{
		return 1;
	}

	
	/* Run the recipe repeatedly until the retry count expires or
	 * it succeeds.
	 */
	int attempt = 0, retries = max_retries;
	proc *p = NULL;

	char *args[5];

	char *qrp=rp;

#ifdef HAS_GETCOMMANDLINE
	/* re-quote the argument to -c since this helps windows deal with it */
	int qrpsize = strlen(rp) + 3;
	qrp = malloc(qrpsize);
	qrp[0] = '"';
	strcpy(&qrp[1], rp);
	qrp[qrpsize-2] = '"';
	qrp[qrpsize-1] = '\0';
#endif

	int index = 0;
	args[index++] = shell;

	if (dotagging)  /* don't do bash -x for non-tagged commands e.g. $(shell output) */
		args[index++] = "-x";

	args[index++] = "-c";
	args[index++] = qrp;
	args[index++] = NULL;

	/* get the semaphore ready */
	talon_sem.name = buildid;
	talon_sem.timeout = timeout;
	do
	{
		char talon_attempt[TALON_ATTEMPT_STRMAX];
		double start_time = getseconds();
		
		attempt++;
		
		snprintf(talon_attempt, TALON_ATTEMPT_STRMAX-1, "%d", attempt);
		talon_attempt[TALON_ATTEMPT_STRMAX - 1] = '\0';

		talon_setenv("TALON_ATTEMPT", talon_attempt);
		
		p = process_run(shell, args, timeout);

		double end_time = getseconds();
		
		if (p) 
		{
			talon_returncode = p->returncode;

			if (dotagging) 
			{
				char status[STATUS_STRMAX];
				char timestat[STATUS_STRMAX];
				char warning[WARNING_STRMAX];
				warning[0] = '\0';

				if (shell_cl_max)
				{
					int cl_actual = strlen(qrp);
					if (cl_actual > shell_cl_max)
						{
						snprintf(warning, WARNING_STRMAX-1, \
							"\n<warning>Command line length '%d' exceeds the shell limit on this system of '%d'.  " \
							"If this recipe is a compile, try using the '.use_compilation_command_file' variant to reduce overall command line length.</warning>", \
							cl_actual, shell_cl_max);
						warning[WARNING_STRMAX-1] = '\0';
						}
				}

				char *flagsstr = force_success == 0 ? "" : " flags='FORCESUCCESS'";
				char *reasonstr = "" ;

				if (p->causeofdeath == PROC_TIMEOUTDEATH)
					reasonstr = " reason='timeout'";

				if (p->returncode != 0)
				{
					char *exitstr = (force_success || retries <= 0) ? "failed" : "retry";
					snprintf(status, STATUS_STRMAX - 1, "\n<status exit='%s' code='%d' attempt='%d'%s%s />", exitstr, p->returncode, attempt, flagsstr, reasonstr );
				} else {
					snprintf(status, STATUS_STRMAX - 1, "\n<status exit='ok' attempt='%d'%s%s />", attempt, flagsstr, reasonstr );
				}
				status[STATUS_STRMAX-1] = '\0';
	
				snprintf(timestat, STATUS_STRMAX - 1, "<time start='%.5f' elapsed='%.3f' />",start_time, end_time-start_time );
				timestat[STATUS_STRMAX-1] = '\0';

				prependattributes(p->output, attributes);
			
				buffer_append(p->output, "\n]]>", 4);
				buffer_append(p->output, timestat, strlen(timestat));
				buffer_append(p->output, status, strlen(status));
				buffer_append(p->output, warning, strlen(warning));
				buffer_append(p->output, "\n</recipe>\n", 11);
			}
		
			unsigned int iterator = 0;
			unsigned int written = 0;
			byteblock *bb;
			char sub[7] = "&#x00;";
			
			if (descramble)	
				sema_wait(&talon_sem);
			while ((bb = buffer_getbytes(p->output, &iterator)))
			{
				if (bb->fill < 1)
					continue;		/* empty buffer */
					
				if (dotagging)
				{
					/* the output is XML so we must replace any non-printable characters */
					char *ptr = &bb->byte0;
					char *end = ptr + bb->fill;

					char *start = ptr;
					
					while (ptr < end)
					{
						if ((*ptr < 32 || *ptr > 126) && *ptr != 9 && *ptr != 10 && *ptr != 13)
						{
							/* output any unwritten characters before this non-printable */
							if (ptr > start)
								write(STDOUT_FILENO, start, ptr - start);
							
							/* 0->&#x00; 1->&#x01; ... 255->&#xff; */
							sprintf(sub, "&#x%02x;", (unsigned char)*ptr);
							
							/* output the modified non-printable character */
							write(STDOUT_FILENO, sub, 6);
							start = ptr + 1;
						}
						ptr++;
					}
					if (ptr > start)
						write(STDOUT_FILENO, start, ptr - start);
				}
				else
				{
					/* the output isn't XML so write out the whole buffer as-is */
					
					written = write(STDOUT_FILENO, &bb->byte0, bb->fill);

					DEBUG(("talon: wrote %d bytes out of %d\n", written, 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;
}