+/* Special command: mkfile is a built-in creating a file with the input data as content */
+static void rctx_mkfile(void)
+{
+ char *filename = xbt_strdup(rctx->cmd + strlen("mkfile "));
+ FILE *OUT;
+ int err;
+ xbt_str_trim(filename, NULL);
+ OUT = fopen(filename, "w");
+ if (!OUT) {
+ THROW3(system_error, errno, "%s: Cannot create file %s: %s",
+ rctx->filepos, filename, strerror(errno));
+ }
+ err = (fprintf(OUT, "%s", rctx->input->data) < 0);
+ err = (fclose(OUT) == -1) || err;
+ if (err) {
+ THROW3(system_error, errno, "%s: Cannot write file %s: %s",
+ rctx->filepos, filename, strerror(errno));
+ }
+ free(filename);
+}
+
+/* function to be called from the child to start the actual process */
+static void start_command(rctx_t rctx)
+{
+ xbt_dynar_t cmd;
+ char *binary_name = NULL;
+ unsigned int it;
+ char *str;
+ char **args;
+ int errcode;
+
+ if (!strncmp(rctx->cmd, "mkfile ", strlen("mkfile "))) {
+ rctx_mkfile();
+ /* Valgrind detects memory leaks here.
+ * To correct those leaks, we must free objects allocated in main() or in
+ * handle_suite(), but we have no more reference to them at this point.
+ * A quick and dirty hack to make valgrind happy it to uncomment the
+ * following line.
+ */
+ /* execlp("true", "true", (const char *)0); */
+ exit(0); /* end the working child */
+ }
+
+ cmd = xbt_str_split_quoted(rctx->cmd);
+ xbt_dynar_get_cpy(cmd, 0, &binary_name);
+ args = xbt_new(char *, xbt_dynar_length(cmd) + 1);
+ xbt_dynar_foreach(cmd, it, str) {
+ args[it] = xbt_strdup(str);
+ }
+ args[it] = NULL;
+ xbt_dynar_free_container(&cmd);
+
+ /* To search for the right executable path when not trivial */
+ struct stat stat_buf;
+
+ /* build the command line */
+ if (stat(binary_name, &stat_buf)) {
+ /* Damn. binary not in current dir. We'll have to dig the PATH to find it */
+ int i;
+
+ for (i = 0; environ[i]; i++) {
+ if (!strncmp("PATH=", environ[i], 5)) {
+ xbt_dynar_t path = xbt_str_split(environ[i] + 5, ":");
+
+ xbt_dynar_foreach(path, it, str) {
+ if (binary_name)
+ free(binary_name);
+ binary_name = bprintf("%s/%s", str, args[0]);
+ if (!stat(binary_name, &stat_buf)) {
+ /* Found. */
+ DEBUG1("Looked in the PATH for the binary. Found %s",
+ binary_name);
+ xbt_dynar_free(&path);
+ break;
+ }
+ }
+ xbt_dynar_free(&path);
+ if (stat(binary_name, &stat_buf)) {
+ /* not found */
+ printf("TESH_ERROR Command %s not found\n", args[0]);
+ exit(127);
+ }
+ break;
+ }
+ }
+ } else {
+ binary_name = xbt_strdup(args[0]);
+ }
+
+ errcode = execve(binary_name, args, rctx->env);
+ printf("TESH_ERROR %s: Cannot start %s: %s\n", rctx->filepos, rctx->cmd,
+ strerror(errcode));
+ exit(127);
+}