Esempio n. 1
0
// Apply single quotes to prevent shell from evaluating special chars
char *quote_for_remote(const char *arg) {
  const char *p;
  int c;

  for (p=arg, c=0; NULL != (p = strchr(p, '\'')); ++c, ++p) { /*empty*/ }

  size_t old_len = strlen(arg);
  size_t new_len = old_len + 2 + 3 * c;
  char *result = (char *)AMUDP_malloc(1 + new_len);
  result[0] = '\'';
  result[1] = '\0';
  char *end = result+1;

  if (c) {
    char *dup = (char *)AMUDP_malloc(1 + old_len);
    p = strcpy(dup, arg);
    while (c--) {
      char *q = strchr((char *)p, '\'');
      *q = '\0';
      strcpy(end, p);       end += q-p;
      strcpy(end, "'\\''"); end += 4;
      p = q + 1;
    }
    AMUDP_free(dup);
  } else {
    p = arg;
  }
  strcpy(end, p);

  AMUDP_assert(strlen(result) == new_len-1);
  result[new_len-1] = '\'';
  result[new_len]   = '\0';

  return result;
}
Esempio n. 2
0
// Apply quotes to protect against the shell spawned by system()
// Note this is for use *inside* the double quotes we place around a command run by system.
// shell docs tells us:
//   Inside double-quotes, '$' and '`' remain special unconditionally,
//   and '\' remains special only if followed by another special
char *quote_for_local(const char *arg) {
  const char specials[] = "$`\\\"";

  char *tmp = quote_for_remote(arg);

  // count specials (assume every backslash is special)
  const char *p;
  int c;
  for (p=tmp, c=0; NULL != (p = strpbrk(p, specials)); ++c, ++p) { /*empty*/ }

  if (!c) return tmp; // Nothing to protect from local shell

  size_t old_len = strlen(tmp);
  size_t new_len = old_len + c;
  char *result = (char *)AMUDP_malloc(1 + new_len);
  char *end = result;

  if (c) {
    char *q, *dup = (char *)AMUDP_malloc(1 + old_len);
    p = strcpy(dup, tmp);
    while (NULL != (q = strpbrk((char *)p, specials))) {
      size_t len = q-p;
      strncpy(end, p, len);   end += len;
      end[0] = '\\';          end += 1;
      if (q[0] != '\\' || strchr(specials, q[1])) {
        end[0] = q[0];        end += 1;
      }
      p = q + 1;
    }
    AMUDP_free(dup);
  } else {
    p = tmp;
  }
  strcpy(end, p);
  AMUDP_free(tmp);

  AMUDP_assert(strlen(result) <= new_len);

  return result;
}
Esempio n. 3
0
/* ------------------------------------------------------------------------------------ 
 *  spawn jobs on local machine
 * ------------------------------------------------------------------------------------ */
extern int AMUDP_SPMDLocalSpawn(int nproc, int argc, char **argv) {
  /* just a simple fork/exec */
  int i;

  if (!AMUDP_SPMDSpawnRunning) {
    AMUDP_Err("Spawn functions should never be run directly - only passed to AMUDP_SPMDStartup()"); 
    return FALSE;
  }

  for (i = 0; i < nproc; i++) {
    #if PLATFORM_OS_MSWINDOWS && !PLATFORM_OS_CYGWIN
      if (_spawnv(_P_NOWAIT, argv[0], argv) == -1)
        AMUDP_FatalErr("failed _spawnv()");
    #elif PLATFORM_ARCH_CRAYX1
      { char **nargv = (char **)AMUDP_malloc(sizeof(char *)*(argc+2));
        nargv[0] = argv[0];
        memcpy(nargv+1,argv,argc*sizeof(char *));
        nargv[argc+1] = NULL;
        if (execsp(nargv, environ, NULL) == -1)
          AMUDP_FatalErr("failed execsp()");
      }
    #else
      int forkRet = fork();
      if (forkRet == -1) {
        perror("fork");
        return FALSE;
      } else if (forkRet != 0) continue;  /*  this is the parent, will go back to the top of the loop */
      else {  /*  this is the child - exec the new process */
        /*  could close some resources here (like AMUDP_SPMDListenSocket) but not strictly necessary */

        #if 0
          /*  put new process in a separate process group */
          if (setsid() == -1) perror("setsid"); 
        #endif

        /*  exec the program, with the given arguments  */
        execv(argv[0], argv);

        /*  if execv returns, an error occurred */
        perror("execv");
        _exit(1); /*  use _exit() to prevent corrupting parent's io buffers */
      } /*  child */
    #endif
  }
  return TRUE;
}
Esempio n. 4
0
int AMUDP_SPMDSshSpawn(int nproc, int argc, char **argv, char **extra_env) {
  int i;
  const char *ssh_servers;
  const char *ssh_cmd;
  const char *ssh_options;
  const char *ssh_remote_path;
  char cwd[1024];
  const char *p;
  char *cmd1, *cmd2;
  size_t cmd1_sz, cmd2_sz;
  int pid;

  if (!AMUDP_SPMDSpawnRunning) {
    AMUDP_Err("Spawn functions should never be run directly - only passed to AMUDP_SPMDStartup()"); 
    return FALSE;
  }

  pid = getpid();

  ssh_servers = AMUDP_getenv_prefixed_withdefault("SSH_SERVERS","");
  if (!strlen(ssh_servers)) {
    printf("Environment variable SSH_SERVERS is missing.\n");
    return FALSE;
  }


  if (!getcwd(cwd, 1024)) {
    printf("Error calling getcwd()\n");
    return FALSE;
  }
  ssh_remote_path = quote_for_local(AMUDP_getenv_prefixed_withdefault("SSH_REMOTE_PATH", cwd));
  ssh_cmd = AMUDP_getenv_prefixed_withdefault("SSH_CMD", "ssh");

  int isOpenSSH = 0; /* figure out if we're using OpenSSH */
  { char cmdtmp[1024];
    sprintf(cmdtmp,"%s -v 2>&1 | grep OpenSSH", ssh_cmd);
    FILE *pop = popen(cmdtmp,"r");
    while (!feof(pop) && !ferror(pop)) {
      int next = fgetc(pop);
      if (next != EOF && !isspace(next)) {
        isOpenSSH = 1;
        break;
      }
    }
    pclose(pop);
  }

  ssh_options = AMUDP_getenv_prefixed_withdefault("SSH_OPTIONS","");

  p = ssh_servers;
  for (i = 0; i < nproc; i++) { /* check we have enough servers */
    const char *end;
    while (*p && strchr(SSH_SERVERS_DELIM_CHARS, *p)) p++;
    end = p + strcspn(p, SSH_SERVERS_DELIM_CHARS);
    if (p == end) {
      printf("Not enough machines in environment variable SSH_SERVERS to satisfy request for (%i).\n"
       "Only (%i) machines available: %s\n", nproc, i, ssh_servers);
      return FALSE;
    }
    if (*end) p = end+1;
    else p = end;
  } 

  const char *envcmd = AMUDP_getenv_prefixed_withdefault("ENV_CMD", "env");

  cmd1_sz = 1; /* terminating nul */
  if (extra_env && extra_env[0]) {
    cmd1_sz += 1 + strlen(envcmd); // "env "
    for (i=0; extra_env[i]; ++i) {
      cmd1_sz += strlen(extra_env[i]) + 3; // "'%s' "
    }
  }
  char **quoted_args = (char**)AMUDP_malloc(argc * sizeof(char*));
  for (i = 0; i < argc; i++) {
    AMUDP_assert(argv[i]);
    quoted_args[i] = quote_for_local(argv[i]);
    cmd1_sz += strlen(quoted_args[i]) + 1; // +1 for trailing space
  }
  cmd1 = (char *)AMUDP_malloc(cmd1_sz);
  { char *tmp = cmd1;
    if (extra_env && extra_env[0]) {
      tmp += sprintf(tmp, "%s ", envcmd);
      for (i=0; extra_env[i]; ++i) {
        tmp += sprintf(tmp, "'%s' ", extra_env[i]);
      }
    }
    for (i = 0; i < argc; i++) {
      AMUDP_assert(quoted_args[i]);
      tmp += sprintf(tmp, "%s ", quoted_args[i]);
      AMUDP_free(quoted_args[i]);
    }
    AMUDP_free(quoted_args);
    AMUDP_assert(!argv[i]);
    *tmp = '\0';
    AMUDP_assert(strlen(cmd1) == cmd1_sz - 1);
  }
  cmd2_sz = cmd1_sz + strlen(ssh_remote_path) + 1024; /* estimated */
  cmd2 =  (char *)AMUDP_malloc(cmd2_sz);

  p = ssh_servers;
  for (i = 0; i < nproc; i++) {
    char ssh_server[255];
    const char *end;
    while (*p && strchr(SSH_SERVERS_DELIM_CHARS, *p)) p++;
    end = p + strcspn(p, SSH_SERVERS_DELIM_CHARS);
    AMUDP_assert(p != end);

    strncpy(ssh_server, p, (end-p));
    ssh_server[end-p] = '\0'; 

    /* build the ssh command */
    snprintf(cmd2, cmd2_sz, "%s %s %s %s %s %s \" %s cd %s ; %s\" "
      " || ( echo \"connection to %s failed.\" ; kill %i ) "
      "%s", 
      ssh_cmd,

      (isOpenSSH?"-f":""),    /* go into background and nullify stdin */

      #if SSH_SUPRESSNEWKEYPROMPT
        (isOpenSSH?"-o 'StrictHostKeyChecking no'":""),
      #else 
        "",
      #endif

      #if SSH_PREVENTRSHFALLBACK
        (isOpenSSH?"-o 'FallBackToRsh no'":""),
      #else 
        "",
      #endif

      ssh_options, ssh_server, 
      
      (AMUDP_SilentMode?"":"echo connected to \\$HOST... ;"),

      ssh_remote_path, cmd1, ssh_server, pid,

      #if SSH_PARALLELSPAWN
        "&"
      #else
        ""
      #endif
    );

    if (!AMUDP_SilentMode) 
      printf("system(%s)\n", cmd2); fflush(stdout);
    if (system(cmd2) == -1) {
      printf("Failed to call system() to spawn");
      AMUDP_free(cmd1);
      AMUDP_free(cmd2);
      return FALSE;
    }
    if (*end) p = end+1;
    else p = end;
  } 

  AMUDP_free(cmd1);
  AMUDP_free(cmd2);
  return TRUE;
}
Esempio n. 5
0
/* ------------------------------------------------------------------------------------ 
 *  spawn jobs on local machine
 * ------------------------------------------------------------------------------------ */
extern int AMUDP_SPMDLocalSpawn(int nproc, int argc, char **argv, char **extra_env) {
  /* just a simple fork/exec */
  int i;

  if (!AMUDP_SPMDSpawnRunning) {
    AMUDP_Err("Spawn functions should never be run directly - only passed to AMUDP_SPMDStartup()"); 
    return FALSE;
  }

  /* Temporarily assume values from extra_env[] (which we modify in-place) */
  char **save_env = NULL;
  int envc = 0;
  if (extra_env && extra_env[0]) {
    for (envc=0; extra_env[envc]; ++envc) {/*empty*/}
    save_env = (char **)AMUDP_malloc(sizeof(char *)*envc);
    for (i=0;i<envc;++i) {
      char *var = extra_env[i];
      char *delim = strchr(var,'=');
      AMUDP_assert(delim);
      *delim = '\0';
      save_env[i] = getenv(var);
      setenv(var,delim+1,1);
    }
  }

  for (i = 0; i < nproc; i++) {
    #if PLATFORM_OS_MSWINDOWS && !PLATFORM_OS_CYGWIN
      if (_spawnv(_P_NOWAIT, argv[0], argv) == -1)
        AMUDP_FatalErr("failed _spawnv()");
    #elif PLATFORM_ARCH_CRAYX1
      { char **nargv = (char **)AMUDP_malloc(sizeof(char *)*(argc+2));
        nargv[0] = argv[0];
        memcpy(nargv+1,argv,argc*sizeof(char *));
        nargv[argc+1] = NULL;
        if (execsp(nargv, environ, NULL) == -1)
          AMUDP_FatalErr("failed execsp()");
      }
    #else
      int forkRet = fork();
      if (forkRet == -1) {
        perror("fork");
        return FALSE;
      } else if (forkRet != 0) continue;  /*  this is the parent, will go back to the top of the loop */
      else {  /*  this is the child - exec the new process */
        /*  could close some resources here (like AMUDP_SPMDListenSocket) but not strictly necessary */

        #if 0
          /*  put new process in a separate process group */
          if (setsid() == -1) perror("setsid"); 
        #endif

        /*  exec the program, with the given arguments  */
        execv(argv[0], argv);

        /*  if execv returns, an error occurred */
        perror("execv");
        _exit(1); /*  use _exit() to prevent corrupting parent's io buffers */
      } /*  child */
    #endif
  }

  /* Restore saved environment var(s) */
  for (i=0;i<envc;++i) {
    char *name = extra_env[i];
    if (save_env[i]) {
      setenv(name,save_env[i],1);
    } else {
      unsetenv(name);
    }
    /* Revert our in-place modification of extra_env[]: */
    name[strlen(name)] = '=';
  }
  AMUDP_free(save_env);

  return TRUE;
}