Skip to content

Commit

Permalink
Fix qsub with multiple arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
vstumpf committed Dec 4, 2018
1 parent 71a1311 commit bd75e3a
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 15 deletions.
48 changes: 33 additions & 15 deletions src/cmds/qsub.c
Expand Up @@ -2346,21 +2346,15 @@ process_opts(int argc, char **argv, int passet)
int ddash_index = -1;

#ifdef WIN32
#define GETOPT_ARGS_ORIG "a:A:c:C:e:fGhIj:J:k:l:m:M:N:o:p:q:r:R:S:u:v:VW:zP:"
#define GETOPT_ARGS "a:A:c:C:e:fGhIj:J:k:l:m:M:N:o:p:q:r:R:S:u:v:VW:zP:"
#else
#if !defined(PBS_NO_POSIX_VIOLATION)
#define GETOPT_ARGS_ORIG "a:A:c:C:e:fhIj:J:k:l:m:M:N:o:p:q:r:R:S:u:v:VW:XzP:"
#define GETOPT_ARGS "a:A:c:C:e:fhIj:J:k:l:m:M:N:o:p:q:r:R:S:u:v:VW:XzP:"
#else
#define GETOPT_ARGS_ORIG "a:A:c:C:e:fhj:J:k:l:m:M:N:o:p:q:r:R:S:u:v:VW:zP:"
#define GETOPT_ARGS "a:A:c:C:e:fhj:J:k:l:m:M:N:o:p:q:r:R:S:u:v:VW:zP:"
#endif /* PBS_NO_POSIX_VIOLATION */
#endif /* WIN32 */

#ifdef PBS_GNU_GETOPTS
#define GETOPT_ARGS "+"GETOPT_ARGS_ORIG
#else
#define GETOPT_ARGS GETOPT_ARGS_ORIG
#endif /* PBS_GNU_GETOPTS */

/*
* The following macro, together the value of passet is used
* to enforce the following rules:
Expand Down Expand Up @@ -2954,6 +2948,11 @@ process_special_args(int argc, char **argv, char *script)
if (!N_opt) /* '-N' is not set */
set_attr(&attrib, ATTR_N, "STDIN");
} else {
if (optind + 1 != argc) {
/* argument is a job script, it should be last */
print_usage();
exit_qsub(2);
}
snprintf(script, MAXPATHLEN, "%s", argv[optind]);
}
}
Expand Down Expand Up @@ -4470,7 +4469,7 @@ do_connect(char *server_out, char *retmsg)
* @retval 0 - Success
* @retval 1/-1/pbs_errno - Failure, retmsg paramter is set
* @retval DMN_REFUSE_EXIT - If daemon can't submit the job
*
*
*/
static int
do_submit(char *retmsg)
Expand Down Expand Up @@ -4498,7 +4497,7 @@ do_submit(char *retmsg)
return (rc);
}

/*
/*
* get environment variable if -V option is set. Return the code
* DMN_REFUSE_EXIT if -V option is detected in background qsub.
*/
Expand Down Expand Up @@ -5548,7 +5547,7 @@ fork_and_stay(void)
pbs_client_thread_set_single_threaded_mode();

/* set when background qsub is running */
is_background = 1;
is_background = 1;
do_daemon_stuff();
/*
* Control should never reach here.
Expand Down Expand Up @@ -5718,6 +5717,8 @@ main(int argc, char **argv, char **envp) /* qsub */
char qsub_exe[MAXPATHLEN + 1];
#endif
int daemon_up = 0;
char **argv_cpy; /* copy argv for getopt */
int i;

/* Set signal handlers */
set_sig_handlers();
Expand Down Expand Up @@ -5784,14 +5785,31 @@ main(int argc, char **argv, char **envp) /* qsub */
}

/* Process options */
errflg = process_opts(argc, argv, CMDLINE); /* get cmd-line options */
if (errflg) {
argv_cpy = calloc(argc + 1, sizeof(char *));
if (argv_cpy == NULL) {
fprintf(stderr, "qsub: out of memory\n");
exit_qsub(2);
}
for (i = 0; i < argc; i++) {
argv_cpy[i] = argv[i];
}
argv_cpy[argc] = NULL;

errflg = process_opts(argc, argv_cpy, CMDLINE); /* get cmd-line options */
if (errflg || ((optind < argc) && (strcmp(argv[optind], argv_cpy[optind]) != 0))) {
/*
* The arguments changed, the script and "--" must have been present.
* getopt will move all non-options to the end of the array. In qsub's
* case, it will only happen if both the "script" and "-- executable"
* were present in the qsub command. This is unsupported usage and
* should exit.
*/
print_usage();
exit_qsub(2);
}
free(argv_cpy);
/* Process special arguments */
command_flag = process_special_args(argc, argv, script);

#ifdef WIN32
back2forward_slash(script);
#endif
Expand Down
113 changes: 113 additions & 0 deletions test/tests/functional/pbs_qsub_opts_args.py
@@ -0,0 +1,113 @@
# coding: utf-8

# Copyright (C) 1994-2018 Altair Engineering, Inc.
# For more information, contact Altair at www.altair.com.
#
# This file is part of the PBS Professional ("PBS Pro") software.
#
# Open Source License Information:
#
# PBS Pro is free software. You can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Commercial License Information:
#
# For a copy of the commercial license terms and conditions,
# go to: (http://www.pbspro.com/UserArea/agreement.html)
# or contact the Altair Legal Department.
#
# Altair’s dual-license business model allows companies, individuals, and
# organizations to create proprietary derivative works of PBS Pro and
# distribute them - whether embedded or bundled with other software -
# under a commercial license agreement.
#
# Use of Altair’s trademarks, including but not limited to "PBS™",
# "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
# trademark licensing policies.

from tests.functional import *


class TestQsubOptionsArguments(TestFunctional):
"""
validate qsub submission with a script and executable.
note: The no-arg test is an interactive job, which is tested in
SmokeTest.test_interactive_job
"""
fn = None

def setUp(self):
TestFunctional.setUp(self)
script = '/bin/hostname'
self.fn = self.du.create_temp_file(body=script)
self.qsub_cmd = os.path.join(
self.server.pbs_conf['PBS_EXEC'], 'bin', 'qsub')

def test_qsub_with_script_executable(self):
"""
submit a job with a script and executable
"""
cmd = [self.qsub_cmd, self.fn, '--', '/bin/sleep 10']
rv = self.du.run_cmd(self.server.hostname, cmd=cmd)
failed = rv['rc'] == 2 and rv['err'][0].split(' ')[0] == 'usage:'
self.assertTrue(failed, 'qsub should have failed, but did not fail')

def test_qsub_with_script_dashes(self):
"""
submit a job with a script and dashes
"""
cmd = [self.qsub_cmd, self.fn, '--']
rv = self.du.run_cmd(self.server.hostname, cmd=cmd)
failed = rv['rc'] == 2 and rv['err'][0].split(' ')[0] == 'usage:'
self.assertTrue(failed, 'qsub should have failed, but did not fail')

def test_qsub_with_dashes(self):
"""
submit a job with only dashes
"""
cmd = [self.qsub_cmd, '--']
rv = self.du.run_cmd(self.server.hostname, cmd=cmd)
failed = rv['rc'] == 2 and rv['err'][0].split(' ')[0] == 'usage:'
self.assertTrue(failed, 'qsub should have failed, but did not fail')

def test_qsub_with_script(self):
"""
submit a job with only a script
"""
cmd = [self.qsub_cmd, self.fn]
rv = self.du.run_cmd(self.server.hostname, cmd=cmd)
self.assertEquals(rv['rc'], 0, 'qsub failed')

def test_qsub_with_executable(self):
"""
submit a job with only an executable
"""
cmd = [self.qsub_cmd, '--', '/bin/sleep 10']
rv = self.du.run_cmd(self.server.hostname, cmd=cmd)
self.assertEquals(rv['rc'], 0, 'qsub failed')

def test_qsub_with_option_executable(self):
"""
submit a job with an option and executable
"""
cmd = [self.qsub_cmd, '-V', '--', '/bin/sleep', '10']
rv = self.du.run_cmd(self.server.hostname, cmd=cmd)
self.assertEquals(rv['rc'], 0, 'qsub failed')

def test_qsub_with_option_script(self):
"""
submit a job with an option and script
"""
cmd = [self.qsub_cmd, '-V', self.fn]
rv = self.du.run_cmd(self.server.hostname, cmd=cmd)
self.assertEquals(rv['rc'], 0, 'qsub failed')

0 comments on commit bd75e3a

Please sign in to comment.