1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
10
* Sun Industry Standards Source License Version 1.2
11
* =================================================
12
* The contents of this file are subject to the Sun Industry Standards
13
* Source License Version 1.2 (the "License"); You may not use this file
14
* except in compliance with the License. You may obtain a copy of the
15
* License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
17
* Software provided under this License is provided on an "AS IS" basis,
18
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
19
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
20
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
21
* See the License for the specific provisions governing your rights and
22
* obligations concerning the Software.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
38
#include "sge_string.h"
40
#include "parse_qsubL.h"
42
#include "dispatcher.h"
43
#include "parse_job_cull.h"
44
#include "parse_qsub.h"
45
#include "parse_job_qsh.h"
48
#include "cull_parse_util.h"
50
#include "sge_path_alias.h"
51
#include "msg_common.h"
52
#include "sge_job_refL.h"
54
#include "sge_stdlib.h"
56
#include "setup_path.h"
58
#include "sge_answer.h"
59
#include "sge_range.h"
60
#include "sge_mailrec.h"
61
#include "sge_centry.h"
65
** cull_parse_qsh_parameter
67
** cmdline - NULL or SPA_Type, if NULL, *pjob is initialised with defaults
68
** pjob - pointer to job element, is filled according to cmdline
71
** answer list, AN_Type or NULL if everything ok, the following stati can occur:
72
** STATUS_EUNKNOWN - bad internal error like NULL pointer received or no memory
73
** STATUS_EDISK - getcwd() failed
74
** STATUS_ENOIMP - unknown switch or -help occurred
79
lList *cull_parse_qsh_parameter(u_long32 prog_number, u_long32 uid, const char *username, const char *cell_root,
80
const char *unqualified_hostname, const char *qualified_hostname, lList *cmdline, lListElem **pjob)
85
lList *path_alias = NULL;
88
DENTER(TOP_LAYER, "cull_parse_qsh_parameter");
91
answer_list_add(&answer, MSG_PARSE_NULLPOINTERRECEIVED,
92
STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR);
100
if (path_alias_list_initialize(&path_alias, &answer, cell_root, username,
101
qualified_hostname) == -1) {
102
lFreeList(&path_alias);
107
job_initialize_env(*pjob, &answer, path_alias, unqualified_hostname, qualified_hostname);
109
lFreeList(&path_alias);
114
lSetUlong(*pjob, JB_priority, BASE_PRIORITY);
115
lSetUlong(*pjob, JB_jobshare, 0);
116
lSetUlong(*pjob, JB_verify_suitable_queues, SKIP_VERIFY);
119
** it does not make sense to rerun interactive jobs
120
** the default is to decide via the queue configuration
121
** we turn this off here explicitly (2 is no)
123
job_now = lGetUlong(*pjob, JB_type);
124
if (JOB_TYPE_IS_QSH(job_now) || JOB_TYPE_IS_QLOGIN(job_now)
125
|| JOB_TYPE_IS_QRSH(job_now) || JOB_TYPE_IS_QRLOGIN(job_now)) {
126
lSetUlong(*pjob, JB_restart, 2);
129
while (JOB_TYPE_IS_QRSH(job_now)
130
&& (ep = lGetElemStr(cmdline, SPA_switch, "-notify"))) {
131
lSetBool(*pjob, JB_notify, true);
132
lRemoveElem(cmdline, &ep);
136
* turn on immediate scheduling as default
137
* can be overwriten by option -now n
140
u_long32 type = lGetUlong(*pjob, JB_type);
142
JOB_TYPE_SET_IMMEDIATE(type);
143
lSetUlong(*pjob, JB_type, type);
147
** -clear option is special, is sensitive to order
148
** kills all options that come before
149
** there might be more than one -clear
151
while ((ep = lGetElemStr(cmdline, SPA_switch, "-clear"))) {
153
const char *cp_switch;
155
for (ep_run = lFirst(cmdline); ep_run;) {
157
** remove -clear itsself
160
lRemoveElem(cmdline, &ep_run);
164
** lNext can never be NULL here, because the -clear
165
** element is the last one to delete
166
** in general, these two lines wont work!
168
ep_run = lNext(ep_run);
171
** remove switch only if it is not a pseudo-arg
173
cp_switch = lGetString(lPrev(ep_run), SPA_switch);
174
if (cp_switch && (*cp_switch == '-')) {
175
lListElem *prev = lPrev(ep_run);
176
lRemoveElem(cmdline, &prev);
183
** general remark: There is a while loop looping through the option
184
** list. So inside the while loop there must be made
185
** a decision if a second occurence of an option has
186
** to be handled as error, should be warned, overwritten
187
** or simply ignored.
190
while ((ep = lGetElemStr(cmdline, SPA_switch, "-A"))) {
191
/* the old account string is overwritten */
192
lSetString(*pjob, JB_account, lGetString(ep, SPA_argval_lStringT));
193
lRemoveElem(cmdline, &ep);
197
** the handling of the path lists is not so trivial
198
** if we have several path lists we have to check
199
** 1. is there only one path entry without host
200
** 2. do the entries collide, i.e. are there two
201
** entries for the same host with different paths
202
** These restrictions seem reasonable to me but are
203
** not addressed right now
207
** to use lAddList correctly we have to get the list out
208
** of the option struct otherwise we free the list once again
209
** in the lSetList(ep, SPA_argval_lListT, NULL); call
210
** this can lead to a core dump
211
** so a better method is to xchange the list in the option struct
212
** with a null pointer, this is not nice but safe
213
** a little redesign of cull would be nice
214
** see parse_list_simple
216
job_set_submit_task_ids(*pjob, 1, 1, 1);
217
job_initialize_id_lists(*pjob, &answer);
218
if (answer != NULL) {
219
lFreeList(&path_alias);
224
while ((ep = lGetElemStr(cmdline, SPA_switch, "-ar"))) {
225
/* the old advance reservation is overwritten */
226
lSetUlong(*pjob, JB_ar, lGetUlong(ep, SPA_argval_lUlongT));
227
lRemoveElem(cmdline, &ep);
230
while ((ep = lGetElemStr(cmdline, SPA_switch, "-e"))) {
231
lSetList(*pjob, JB_stderr_path_list, lCopyList("stderr_path_list", lGetList(ep, SPA_argval_lListT)));
232
lRemoveElem(cmdline, &ep);
235
while ((ep = lGetElemStr(cmdline, SPA_switch, "-h"))) {
236
if (lGetInt(ep, SPA_argval_lIntT) & MINUS_H_TGT_USER) {
237
lSetList(*pjob, JB_ja_u_h_ids, lCopyList("task_id_range",
238
lGetList(*pjob, JB_ja_n_h_ids)));
240
lSetList(*pjob, JB_ja_n_h_ids, NULL);
241
lRemoveElem(cmdline, &ep);
245
if (lGetElemStr(cmdline, SPA_switch, "-hold_jid")) {
247
lList *jref_list = NULL;
248
while ((ep = lGetElemStr(cmdline, SPA_switch, "-hold_jid"))) {
249
for_each(sep, lGetList(ep, SPA_argval_lListT)) {
250
DPRINTF(("-hold_jid %s\n", lGetString(sep, ST_name)));
251
lAddElemStr(&jref_list, JRE_job_name, lGetString(sep, ST_name), JRE_Type);
253
lRemoveElem(cmdline, &ep);
255
lSetList(*pjob, JB_jid_request_list, jref_list);
259
if (lGetElemStr(cmdline, SPA_switch, "-hold_jid_ad")) {
261
lList *jref_list = NULL;
262
while ((ep = lGetElemStr(cmdline, SPA_switch, "-hold_jid_ad"))) {
263
for_each(sep, lGetList(ep, SPA_argval_lListT)) {
264
DPRINTF(("-hold_jid_ad %s\n", lGetString(sep, ST_name)));
265
lAddElemStr(&jref_list, JRE_job_name, lGetString(sep, ST_name), JRE_Type);
267
lRemoveElem(cmdline, &ep);
269
lSetList(*pjob, JB_ja_ad_request_list, jref_list);
272
/* not needed in job struct */
273
while ((ep = lGetElemStr(cmdline, SPA_switch, "-hard"))) {
274
lRemoveElem(cmdline, &ep);
277
if ((ep = lGetElemStr(cmdline, SPA_switch, "-help"))) {
280
lRemoveElem(cmdline, &ep);
281
sprintf(str, MSG_ANSWER_HELPNOTALLOWEDINCONTEXT);
282
answer_list_add(&answer, str, STATUS_ENOIMP, ANSWER_QUALITY_ERROR);
283
lFreeList(&path_alias);
288
while ((ep = lGetElemStr(cmdline, SPA_switch, "-j"))) {
289
lSetBool(*pjob, JB_merge_stderr, lGetInt(ep, SPA_argval_lIntT));
290
lRemoveElem(cmdline, &ep);
293
parse_list_hardsoft(cmdline, "-l", *pjob,
294
JB_hard_resource_list, JB_soft_resource_list);
295
centry_list_remove_duplicates(lGetList(*pjob, JB_hard_resource_list));
296
centry_list_remove_duplicates(lGetList(*pjob, JB_soft_resource_list));
298
while ((ep = lGetElemStr(cmdline, SPA_switch, "-m"))) {
300
u_long32 old_mail_opts;
302
ul = lGetInt(ep, SPA_argval_lIntT);
303
if ((ul & NO_MAIL)) {
304
lSetUlong(*pjob, JB_mail_options, 0);
307
old_mail_opts = lGetUlong(*pjob, JB_mail_options);
308
lSetUlong(*pjob, JB_mail_options, ul | old_mail_opts);
310
lRemoveElem(cmdline, &ep);
313
parse_list_simple(cmdline, "-M", *pjob, JB_mail_list, MR_host, MR_user, FLG_LIST_MERGE);
315
if (!lGetList(*pjob, JB_mail_list)) {
316
ep = lAddSubStr(*pjob, MR_user, username, JB_mail_list, MR_Type);
317
lSetHost(ep, MR_host, qualified_hostname);
320
while ((ep = lGetElemStr(cmdline, SPA_switch, "-N"))) {
321
lSetString(*pjob, JB_job_name, lGetString(ep, SPA_argval_lStringT));
322
lRemoveElem(cmdline, &ep);
325
while ((ep = lGetElemStr(cmdline, SPA_switch, "-now"))) {
326
u_long32 jb_now = lGetUlong(*pjob, JB_type);
327
if(lGetInt(ep, SPA_argval_lIntT)) {
328
JOB_TYPE_SET_IMMEDIATE(jb_now);
330
JOB_TYPE_CLEAR_IMMEDIATE(jb_now);
333
lSetUlong(*pjob, JB_type, jb_now);
335
lRemoveElem(cmdline, &ep);
338
while ((ep = lGetElemStr(cmdline, SPA_switch, "-o"))) {
339
lSetList(*pjob, JB_stdout_path_list, lCopyList("stdout_path_list", lGetList(ep, SPA_argval_lListT)));
340
lRemoveElem(cmdline, &ep);
343
while ((ep = lGetElemStr(cmdline, SPA_switch, "-P"))) {
344
/* the old project string is overwritten */
345
lSetString(*pjob, JB_project, lGetString(ep, SPA_argval_lStringT));
346
lRemoveElem(cmdline, &ep);
349
while ((ep = lGetElemStr(cmdline, SPA_switch, "-p"))) {
350
lSetUlong(*pjob, JB_priority,
351
BASE_PRIORITY + lGetInt(ep, SPA_argval_lIntT));
352
lRemoveElem(cmdline, &ep);
355
while ((ep = lGetElemStr(cmdline, SPA_switch, "-js"))) {
356
lSetUlong(*pjob, JB_jobshare, lGetUlong(ep, SPA_argval_lUlongT));
357
lRemoveElem(cmdline, &ep);
360
while ((ep = lGetElemStr(cmdline, SPA_switch, "-pe"))) {
362
lSetString(*pjob, JB_pe, lGetString(ep, SPA_argval_lStringT));
364
/* put sublist from parsing into job */
365
lSwapList(*pjob, JB_pe_range, ep, SPA_argval_lListT);
366
lRemoveElem(cmdline, &ep);
369
parse_list_hardsoft(cmdline, "-q", *pjob,
370
JB_hard_queue_list, JB_soft_queue_list);
372
parse_list_hardsoft(cmdline, "-masterq", *pjob,
373
JB_master_hard_queue_list, 0);
375
while ((ep = lGetElemStr(cmdline, SPA_switch, "-R"))) {
376
lSetBool(*pjob, JB_reserve, lGetInt(ep, SPA_argval_lIntT));
377
lRemoveElem(cmdline, &ep);
380
parse_list_simple(cmdline, "-S", *pjob, JB_shell_list, PN_host, PN_path, FLG_LIST_MERGE);
382
/* context switches are sensitive to order */
383
ep = lFirst(cmdline);
385
if(!strcmp(lGetString(ep, SPA_switch), "-ac") ||
386
!strcmp(lGetString(ep, SPA_switch), "-dc") ||
387
!strcmp(lGetString(ep, SPA_switch), "-sc")) {
389
if(!lGetList(*pjob, JB_context)) {
390
lSetList(*pjob, JB_context, lCopyList("context", lGetList(ep, SPA_argval_lListT)));
393
lList *copy = lCopyList("context", lGetList(ep, SPA_argval_lListT));
394
lAddList(lGetList(*pjob, JB_context), ©);
397
lRemoveElem(cmdline, &ep);
403
/* not needed in job struct */
404
while ((ep = lGetElemStr(cmdline, SPA_switch, "-soft"))) {
405
lRemoveElem(cmdline, &ep);
409
** to be processed in original order, set -V equal to -v
411
while ((ep = lGetElemStr(cmdline, SPA_switch, "-V"))) {
412
lSetString(ep, SPA_switch, "-v");
414
parse_list_simple(cmdline, "-v", *pjob, JB_env_list, VA_variable, VA_value, FLG_LIST_MERGE);
416
/* -w e is default for interactive jobs */
417
/* JG: changed default behaviour: skip verify to be consistant to qsub */
418
lSetUlong(*pjob, JB_verify_suitable_queues, SKIP_VERIFY);
420
while ((ep = lGetElemStr(cmdline, SPA_switch, "-w"))) {
421
lSetUlong(*pjob, JB_verify_suitable_queues, lGetInt(ep, SPA_argval_lIntT));
422
lRemoveElem(cmdline, &ep);
425
while ((ep = lGetElemStr(cmdline, SPA_switch, "-wd"))) {
426
const char *path = lGetString(ep, SPA_argval_lStringT);
430
char tmp_str[SGE_PATH_MAX + 1];
433
if (!getcwd(tmp_str, sizeof(tmp_str))) {
434
/* If getcwd() fails... */
435
answer_list_add(&answer, MSG_ANSWER_GETCWDFAILED,
436
STATUS_EDISK, ANSWER_QUALITY_ERROR);
437
lFreeList(&path_alias);
441
path = reroot_path(*pjob, tmp_str, &answer);
444
lFreeList(&path_alias);
449
lSetString(*pjob, JB_cwd, path);
450
lRemoveElem(cmdline, &ep);
452
lSetList(*pjob, JB_path_aliases, lCopyList("PathAliases", path_alias));
459
lFreeList(&path_alias);
462
* handling for display:
463
* command line (-display) has highest priority
464
* then comes environment variable DISPLAY which was given via -v
465
* then comes environment variable DISPLAY read from environment
467
* If a value for DISPLAY is set, it is checked for completeness:
468
* In a GRID environment, it has to contain the name of the display host.
469
* DISPLAY variables of form ":id" are not allowed and are deleted.
471
* we put the display switch into the variable list
472
* otherwise, we'd have to add a field to the job structure
474
while ((ep = lGetElemStr(cmdline, SPA_switch, "-display"))) {
478
lp = lGetList(*pjob, JB_env_list);
479
vep = lCreateElem(VA_Type);
480
lSetString(vep, VA_variable, "DISPLAY");
481
lSetString(vep, VA_value, lGetString(ep, SPA_argval_lStringT));
483
lp = lCreateList("env list", VA_Type);
484
lSetList(*pjob, JB_env_list, lp);
486
lAppendElem(lp, vep);
488
lRemoveElem(cmdline, &ep);
490
cull_compress_definition_list(lGetList(*pjob, JB_env_list),
491
VA_variable, VA_value, 0);
494
while ((ep = lGetElemStr(cmdline, SPA_switch, "-verify"))) {
495
lSetUlong(*pjob, JB_verify, true);
496
lRemoveElem(cmdline, &ep);
502
lp = lCopyList("job args", lGetList(*pjob, JB_job_args));
504
while ((ep = lGetElemStr(cmdline, SPA_switch, STR_PSEUDO_JOBARG))) {
505
lAddElemStr(&lp, ST_name, lGetString(ep, SPA_argval_lStringT), ST_Type);
507
lRemoveElem(cmdline, &ep);
509
lSetList(*pjob, JB_job_args, lp);
513
for_each(ep, cmdline) {
516
sprintf(str, MSG_ANSWER_UNKOWNOPTIONX_S,
517
lGetString(ep, SPA_switch));
518
cp = lGetString(ep, SPA_switch_arg);
523
answer_list_add(&answer, str, STATUS_ENOIMP, ANSWER_QUALITY_ERROR);
529
ep = lGetSubStr(*pjob, VA_variable, "DISPLAY", JB_env_list);
531
/* if DISPLAY not set from -display or -v option,
532
* try to read it from the environment
536
display = getenv("DISPLAY");
538
if(display != NULL) {
539
ep = lAddSubStr(*pjob, VA_variable, "DISPLAY", JB_env_list, VA_Type);
540
lSetString(ep, VA_value, display);
545
/* check DISPLAY on the client side before submitting job to qmaster
546
* only needed for qsh
548
if(prog_number == QSH) {
549
job_check_qsh_display(*pjob, &answer, false);