diff --git a/slurm_drmaa/job.c b/slurm_drmaa/job.c index 303b3b3..fcf7a10 100644 --- a/slurm_drmaa/job.c +++ b/slurm_drmaa/job.c @@ -605,6 +605,7 @@ slurmdrmaa_job_create( for( i = vector, j = 2; *i; i++, j++ ) { char *arg_expanded = expand->expand( expand, fsd_strdup(*i), FSD_DRMAA_PH_HD | FSD_DRMAA_PH_WD ); + char *quoted_arg_expanded = repl_str(arg_expanded, "\'", "\'\"\'\"\'"); temp_script_old = fsd_strdup(temp_script); @@ -612,9 +613,10 @@ slurmdrmaa_job_create( fsd_free(temp_script); } /* add too script */ - temp_script = fsd_asprintf("%s '%s'", temp_script_old, arg_expanded); + temp_script = fsd_asprintf("%s '%s'", temp_script_old, quoted_arg_expanded); fsd_free(temp_script_old); fsd_free(arg_expanded); + fsd_free(quoted_arg_expanded); } } diff --git a/slurm_drmaa/util.c b/slurm_drmaa/util.c index 2241985..c7e7ebc 100644 --- a/slurm_drmaa/util.c +++ b/slurm_drmaa/util.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -723,3 +725,87 @@ slurmdrmaa_set_cluster(const char * value) fsd_log_return(( "" )); } + +// https://creativeandcritical.net/str-replace-c +char *repl_str(const char *str, const char *from, const char *to) { + + /* Adjust each of the below values to suit your needs. */ + + /* Increment positions cache size initially by this number. */ + size_t cache_sz_inc = 16; + /* Thereafter, each time capacity needs to be increased, + * multiply the increment by this factor. */ + const size_t cache_sz_inc_factor = 3; + /* But never increment capacity by more than this number. */ + const size_t cache_sz_inc_max = 1048576; + + char *pret, *ret = NULL; + const char *pstr2, *pstr = str; + size_t i, count = 0; + #if (__STDC_VERSION__ >= 199901L) + uintptr_t *pos_cache_tmp, *pos_cache = NULL; + #else + ptrdiff_t *pos_cache_tmp, *pos_cache = NULL; + #endif + size_t cache_sz = 0; + size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from); + + /* Find all matches and cache their positions. */ + while ((pstr2 = strstr(pstr, from)) != NULL) { + count++; + + /* Increase the cache size when necessary. */ + if (cache_sz < count) { + cache_sz += cache_sz_inc; + pos_cache_tmp = realloc(pos_cache, sizeof(*pos_cache) * cache_sz); + if (pos_cache_tmp == NULL) { + goto end_repl_str; + } else pos_cache = pos_cache_tmp; + cache_sz_inc *= cache_sz_inc_factor; + if (cache_sz_inc > cache_sz_inc_max) { + cache_sz_inc = cache_sz_inc_max; + } + } + + pos_cache[count-1] = pstr2 - str; + pstr = pstr2 + fromlen; + } + + orglen = pstr - str + strlen(pstr); + + /* Allocate memory for the post-replacement string. */ + if (count > 0) { + tolen = strlen(to); + retlen = orglen + (tolen - fromlen) * count; + } else retlen = orglen; + ret = malloc(retlen + 1); + if (ret == NULL) { + goto end_repl_str; + } + + if (count == 0) { + /* If no matches, then just duplicate the string. */ + strcpy(ret, str); + } else { + /* Otherwise, duplicate the string whilst performing + * the replacements using the position cache. */ + pret = ret; + memcpy(pret, str, pos_cache[0]); + pret += pos_cache[0]; + for (i = 0; i < count; i++) { + memcpy(pret, to, tolen); + pret += tolen; + pstr = str + pos_cache[i] + fromlen; + cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen; + memcpy(pret, pstr, cpylen); + pret += cpylen; + } + ret[retlen] = '\0'; + } + +end_repl_str: + /* Free the cache and return the post-replacement string, + * which will be NULL in the event of an error. */ + free(pos_cache); + return ret; +} diff --git a/slurm_drmaa/util.h b/slurm_drmaa/util.h index 9bad61f..80ce3d4 100644 --- a/slurm_drmaa/util.h +++ b/slurm_drmaa/util.h @@ -37,5 +37,6 @@ void slurmdrmaa_parse_native(job_desc_msg_t *job_desc, const char * value); char * slurmdrmaa_set_job_id(job_id_spec_t *job_id_spec); char * slurmdrmaa_unset_job_id(job_id_spec_t *job_id_spec); void slurmdrmaa_set_cluster(const char * value); +char * repl_str(const char *str, const char *from, const char *to); #endif /* __SLURM_DRMAA__UTIL_H */