~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/libs/gdi/sge_qtcsh.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 * 
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 * 
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 * 
 
9
 * 
 
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
 
16
 * 
 
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.
 
23
 * 
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 * 
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 * 
 
28
 *   All Rights Reserved.
 
29
 * 
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
#include <stdio.h>
 
33
#include <string.h>
 
34
#include <stdlib.h>
 
35
#include <unistd.h>
 
36
#include <ctype.h>
 
37
#include <sys/types.h>
 
38
#include <pwd.h>
 
39
#include <errno.h>
 
40
#include <pthread.h>
 
41
 
 
42
#include "lck/sge_mtutil.h"
 
43
 
 
44
#include "rmon/sgermon.h"
 
45
 
 
46
#include "uti/setup_path.h"
 
47
#include "uti/sge_log.h"
 
48
#include "uti/sge_uidgid.h"
 
49
#include "uti/sge_prog.h"
 
50
#include "uti/sge_stdio.h"
 
51
#include "uti/sge_string.h"
 
52
 
 
53
#include "sgeobj/sge_answer.h"
 
54
#include "sgeobj/config.h"
 
55
#include "sgeobj/sge_conf.h"
 
56
 
 
57
#include "gdi/sge_gdi.h"
 
58
#include "gdi/sge_gdi_ctx.h"
 
59
 
 
60
#include "sge_qtcsh.h"
 
61
 
 
62
#include "msg_common.h"
 
63
 
 
64
 
 
65
/* module global variables */
 
66
static pthread_mutex_t qtask_mutex = PTHREAD_MUTEX_INITIALIZER;
 
67
static lList *task_config = NULL;
 
68
static int mode_verbose = 0;
 
69
static int mode_remote = 1;
 
70
static int force_remote = 0;
 
71
static int mode_immediate = 1;
 
72
 
 
73
static int init_qtask_config(sge_gdi_ctx_class_t *ctx, lList **alpp, print_func_t ostream);
 
74
 
 
75
/****** sge_qtcsh/init_qtask_config() ******************************************
 
76
*  NAME
 
77
*     init_qtask_config() -- ??? 
 
78
*
 
79
*  SYNOPSIS
 
80
*     static int init_qtask_config(lList **alpp, print_func_t ostream) 
 
81
*
 
82
*  FUNCTION
 
83
*     ??? 
 
84
*
 
85
*  INPUTS
 
86
*     sge_gdi_ctx_class_t *ctx        - ???
 
87
*     lList **alpp         - ??? 
 
88
*     print_func_t ostream - ??? 
 
89
*
 
90
*  RESULT
 
91
*     static int - 0 - success
 
92
*                 -1 - failed
 
93
*
 
94
*  EXAMPLE
 
95
*     ??? 
 
96
*
 
97
*  NOTES
 
98
*     MT-NOTES: init_qtask_config() is not MT safe as it uses global variables
 
99
*
 
100
*  BUGS
 
101
*     ??? 
 
102
*
 
103
*  SEE ALSO
 
104
*     ???/???
 
105
*******************************************************************************/
 
106
static int init_qtask_config(
 
107
sge_gdi_ctx_class_t *ctx,
 
108
lList **alpp,
 
109
print_func_t ostream 
 
110
) {
 
111
   struct passwd *pwd;
 
112
   char fname[SGE_PATH_MAX + 1];
 
113
   char buffer[10000];
 
114
   FILE *fp;
 
115
   lList *clp_cluster = NULL, *clp_user = NULL;
 
116
   lListElem *nxt, *cep_dest, *cep, *next;
 
117
   const char *task_name;
 
118
   struct passwd pw_struct;
 
119
   const char* user_name = ctx->get_username(ctx);
 
120
   const char* cell_root = ctx->get_cell_root(ctx);
 
121
 
 
122
   /* cell global settings */
 
123
   sprintf(fname, "%s/common/qtask", cell_root);
 
124
 
 
125
   if (!(fp = fopen(fname, "r")) && errno != ENOENT) {
 
126
      SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_SGETEXT_CANT_OPEN_SS, fname, strerror(errno)));
 
127
      answer_list_add(alpp, SGE_EVENT, STATUS_EDISK, ANSWER_QUALITY_ERROR);
 
128
      (*ostream)("%s", SGE_EVENT);
 
129
      goto Error;
 
130
   }
 
131
   if (fp) {
 
132
      /* read in config file */
 
133
      if (read_config_list(fp, &clp_cluster, alpp, CF_Type, CF_name, CF_value,
 
134
                        CF_sublist, NULL, RCL_NO_VALUE, buffer, sizeof(buffer)-1)) {
 
135
         FCLOSE(fp);
 
136
         goto Error;
 
137
      }
 
138
      FCLOSE(fp);
 
139
   }
 
140
 
 
141
   /* skip tasknames containing '/' */
 
142
   nxt = lFirst(clp_cluster);
 
143
   while ((cep=nxt)) {
 
144
      nxt = lNext(cep);
 
145
      if (strrchr(lGetString(cep, CF_name), '/')) 
 
146
         lRemoveElem(clp_cluster, &cep);
 
147
 
 
148
   }
 
149
 
 
150
   pwd = sge_getpwnam_r(user_name, &pw_struct, buffer, sizeof(buffer));
 
151
   
 
152
   /* user settings */
 
153
   if (pwd == NULL) {
 
154
      SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_USER_INVALIDNAMEX_S , user_name));
 
155
      answer_list_add(alpp, SGE_EVENT, STATUS_ENOSUCHUSER, ANSWER_QUALITY_ERROR);
 
156
      (*ostream)("%s", SGE_EVENT);
 
157
      goto Error;
 
158
   }
 
159
   if (!pwd->pw_dir) {
 
160
      SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_USER_NOHOMEDIRFORUSERX_S , user_name));
 
161
      answer_list_add(alpp, SGE_EVENT, STATUS_EDISK, ANSWER_QUALITY_ERROR);
 
162
      (*ostream)("%s", SGE_EVENT);
 
163
      goto Error;
 
164
   }
 
165
   sprintf(fname, "%s/.qtask", pwd->pw_dir);
 
166
   
 
167
   if (!(fp = fopen(fname, "r")) && errno != ENOENT) {
 
168
      SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_SGETEXT_CANT_OPEN_SS, fname, strerror(errno)));
 
169
      answer_list_add(alpp, SGE_EVENT, STATUS_EDISK, ANSWER_QUALITY_ERROR);
 
170
      (*ostream)("%s", SGE_EVENT);
 
171
      goto Error;
 
172
   }
 
173
   if (fp) {
 
174
      /* read in config file */
 
175
      if (read_config_list(fp, &clp_user, alpp, CF_Type, CF_name, CF_value,
 
176
                           CF_sublist, NULL, RCL_NO_VALUE, buffer, sizeof(buffer)-1)) {
 
177
         FCLOSE(fp);
 
178
         goto Error;
 
179
      }
 
180
      FCLOSE(fp);
 
181
   }
 
182
 
 
183
   /* skip tasknames containing '/' */
 
184
   nxt = lFirst(clp_user);
 
185
   while ((cep=nxt)) {
 
186
      nxt = lNext(cep);
 
187
      if (strrchr(lGetString(cep, CF_name), '/')) 
 
188
         lRemoveElem(clp_user, &cep);
 
189
   }
 
190
 
 
191
#if 0
 
192
   if (clp_user)
 
193
      for_each (cep, clp_user) {
 
194
         (*ostream) ("info: user: command %s request %s\n", lGetString(cep, CF_name), (s=lGetString(cep, CF_value))?s:"");
 
195
      }
 
196
   else 
 
197
      (*ostream) ("info: empty user task list\n");
 
198
#endif
 
199
 
 
200
   /* merge contents of user list into cluster list */
 
201
   next = lFirst(clp_user);
 
202
   while ((cep=next)) {
 
203
      char *ro_task_name;
 
204
      next = lNext(cep);
 
205
      task_name = lGetString(cep, CF_name);
 
206
   
 
207
      /* build task name with leading '!' for search operation */
 
208
      ro_task_name = (char *)malloc(strlen(task_name) + 2);
 
209
      ro_task_name[0] = '!';
 
210
      strcpy(&ro_task_name[1], task_name);
 
211
 
 
212
      if ((cep_dest=lGetElemStr(clp_cluster, CF_name, ro_task_name))) {
 
213
         /* do not override cluster global task entry */
 
214
         lRemoveElem(clp_user, &cep);
 
215
      } else if ((cep_dest=lGetElemStr(clp_cluster, CF_name, task_name))) {
 
216
         /* override cluster global task entry */
 
217
         lSetString(cep_dest, CF_value, lGetString(cep, CF_value));
 
218
         lRemoveElem(clp_user, &cep);
 
219
      } else {
 
220
         /* no entry in cluster global task list 
 
221
            use entry from user task list */
 
222
         lDechainElem(clp_user, cep);
 
223
         if (!clp_cluster) 
 
224
            clp_cluster = lCreateList("cluster config", CF_Type);
 
225
         lAppendElem(clp_cluster, cep); 
 
226
      }
 
227
 
 
228
      free(ro_task_name);
 
229
   }
 
230
   lFreeList(&clp_user);
 
231
 
 
232
   
 
233
   lFreeList(&task_config);
 
234
   task_config = clp_cluster;
 
235
 
 
236
   /* remove leading '!' from command names */
 
237
   for_each (cep, clp_cluster) {
 
238
      task_name = lGetString(cep, CF_name);
 
239
      if (task_name[0] == '!') {
 
240
         char *t = (char *)malloc(strlen(task_name));
 
241
         strcpy(t, &task_name[1]);
 
242
         lSetString(cep, CF_name, t);
 
243
         free(t);
 
244
      }
 
245
   }
 
246
 
 
247
 
 
248
#if 0
 
249
   if (task_config)
 
250
      for_each (cep, task_config) {
 
251
         (*ostream) ("info: session: command %s request %s\n", lGetString(cep, CF_name), (s=lGetString(cep, CF_value))?s:"");
 
252
      }
 
253
   else 
 
254
      (*ostream) ("info: empty task list\n");
 
255
#endif
 
256
 
 
257
   return 0;
 
258
 
 
259
FCLOSE_ERROR:
 
260
Error:
 
261
   lFreeList(&clp_cluster);
 
262
   lFreeList(&clp_user);
 
263
   return -1;
 
264
}
 
265
 
 
266
int sge_execv(
 
267
char *path,    /* this is how tcsh tries to start the command */
 
268
char *argv[],
 
269
char *expath,  /* this is how user typed in the command */
 
270
int close_stdin /* use of qrsh's -nostdin option */
 
271
) {
 
272
   const char *value; 
 
273
   char *taskname = NULL;
 
274
   lListElem *task = NULL;
 
275
   int i = 0;
 
276
   int narg_resreq = 0;
 
277
   int narg_argv = 0;
 
278
   int newargv_size = 0;
 
279
   char **argv_iter = NULL;
 
280
   char **newargv = NULL;
 
281
   /* TODO: This should be SGE_PATH_MAX. */
 
282
   char qrsh_path[2048];
 
283
 
 
284
   /* remote execution only for commands without any path information */
 
285
   if (!strchr(expath, '/')) {
 
286
      taskname = expath;
 
287
   }
 
288
 
 
289
   if (mode_verbose) {
 
290
      fprintf(stderr, "sge_execv(path = %s, taskname = %s, expath = %s, close_stdin = %d)\n", 
 
291
         path, taskname?taskname:"<no remote execution>", expath, close_stdin);
 
292
   }
 
293
 
 
294
   if (!mode_remote || 
 
295
         !taskname ||
 
296
         !(task=lGetElemStr(task_config, CF_name, taskname))) {
 
297
      if (mode_verbose)
 
298
         fprintf(stderr, "local execution of "SFQ"\n", expath);
 
299
      return execv(path, argv);
 
300
   }
 
301
  
 
302
   if ((value = lGetString(task, CF_value))) {
 
303
      narg_resreq = sge_quick_count_num_args (value);
 
304
   }
 
305
 
 
306
   for (argv_iter=argv; argv_iter[0] != NULL; argv_iter++) {
 
307
      narg_argv++; 
 
308
   }
 
309
   
 
310
   newargv_size =
 
311
      1 +                                /* qrsh */
 
312
      (close_stdin?1:0) +                /* -nostdin */
 
313
      (mode_verbose?1:0) +               /* -verbose */
 
314
      2 +                                /* -now [y|n] */
 
315
      narg_resreq +                      /* resource requests to qrsh */
 
316
      narg_argv +                        /* argv of command to be started */
 
317
      1;                                 /* NULL */
 
318
   newargv = (char **)malloc(sizeof(char *) * newargv_size);
 
319
   memset(newargv, 0, newargv_size);
 
320
 
 
321
   /* build argv for qrsh */
 
322
   i = 0;
 
323
   newargv[i++] = strdup("qrsh");
 
324
 
 
325
   if (close_stdin) 
 
326
      newargv[i++] = strdup("-nostdin");
 
327
 
 
328
   if (mode_verbose) 
 
329
      newargv[i++] = strdup("-verbose");
 
330
 
 
331
   if (mode_immediate) {
 
332
      newargv[i++] = strdup("-now");
 
333
      newargv[i++] = strdup("y");
 
334
   } else {
 
335
      newargv[i++] = strdup("-now");
 
336
      newargv[i++] = strdup("n");
 
337
   }
 
338
 
 
339
   /* add optional qrsh arguments from qtask file */
 
340
   if (value) {
 
341
      sge_parse_args (value, &newargv[i]);
 
342
      i += narg_resreq;
 
343
   }
 
344
         
 
345
   /* add command's arguments */
 
346
   for (argv_iter=argv; argv_iter[0] != NULL; argv_iter++) {
 
347
      newargv[i++] = argv_iter[0];
 
348
   }
 
349
 
 
350
   newargv[i] = NULL;
 
351
      
 
352
   sprintf(qrsh_path, "%s/bin/%s/qrsh", sge_get_root_dir(1, NULL, 0, 1), sge_get_arch());
 
353
 
 
354
   return execvp(qrsh_path, newargv);
 
355
}
 
356
 
 
357
/* This method counts the number of arguments in the string using a quick and
 
358
 * dirty algorithm.  The algorithm may incorrectly report the number of arguments
 
359
 * to be too large because it does not parse quotations correctly. 
 
360
 * MT-NOTE: sge_quick_count_num_args() is MT safe
 
361
 */
 
362
int sge_quick_count_num_args (
 
363
const char* args /* The argument string to count by whitespace tokens */
 
364
) {
 
365
   int num_args = 0;
 
366
   char *resreq = (char *)malloc (strlen (args)+1);
 
367
   char *s;
 
368
   struct saved_vars_s *context = NULL;
 
369
   
 
370
   DENTER (TOP_LAYER, "count_num_qtask_args");
 
371
   
 
372
   /* This function may return a larger number than required since it does not
 
373
    * parse quotes.  This is ok, however, since it's current usage is for
 
374
    * mallocing arrays, and a little too big is fine. */
 
375
   strcpy(resreq, args);
 
376
   for (s=sge_strtok_r(resreq, " \t", &context); s; s=sge_strtok_r(NULL, " \t", &context))
 
377
      num_args++;
 
378
   free(resreq);
 
379
   sge_free_saved_vars(context);
 
380
   
 
381
   DEXIT;
 
382
   return num_args;
 
383
}
 
384
 
 
385
/* This method should probably be moved out of this file into somewhere more
 
386
 * common so that other routines can use it. */
 
387
void sge_parse_args (
 
388
const char* args, /* The argument string to parse by whitespace and quotes */
 
389
char** pargs /* The array to contain the parsed arguments */
 
390
) {
 
391
   const char *s; 
 
392
   char *d;
 
393
   char quote;
 
394
   char *start;
 
395
   char *resreq;
 
396
   int finished, count = 0;
 
397
 
 
398
   DENTER (TOP_LAYER, "sge_parse_args");
 
399
   
 
400
   resreq = malloc (strlen (args) + 1);
 
401
   d = resreq;
 
402
   s = args;
 
403
   start = resreq;
 
404
   finished = 0;
 
405
   
 
406
   while(!finished) {
 
407
      if(*s == '"' || *s == '\'') {      /* copy quoted arguments */
 
408
         quote = *s++;                   /* without quotes */
 
409
         while(*s && *s != quote) 
 
410
           *d++ = *s++;
 
411
         if(*s == quote) 
 
412
            s++;
 
413
      }
 
414
 
 
415
      if(*s == 0) finished = 1;          /* line end ? */
 
416
 
 
417
      if(finished || isspace(*s)) {      /* found delimiter or line end */
 
418
         *d++ = 0;                       /* terminate token */
 
419
         pargs[count++] = strdup(start);   /* assign argument */
 
420
         if(!finished) {
 
421
            while(isspace(*(++s)));      /* skip any number whitespace */
 
422
         }   
 
423
         start = d;                      /* assign start of next token */
 
424
      } else {
 
425
         *d++ = *s++;                    /* copy one character */
 
426
      }
 
427
   } 
 
428
   free(resreq);
 
429
   
 
430
   DEXIT;
 
431
}
 
432
 
 
433
/****** QTCSH/sge_get_qtask_args() *********************************************
 
434
*  NAME
 
435
*     sge_get_qtask_args() -- get args for a qtask entry
 
436
*
 
437
*  SYNOPSIS
 
438
*     char** sge_get_qtask_args(void *ctx, char *taskname, lList **answer_list)
 
439
*
 
440
*  FUNCTION
 
441
*     This function reads the qtask files and returns an array of args for the
 
442
*     given qtask entry.  Calling this function will initialize the qtask
 
443
*     framework, if it has not already been initialized.
 
444
*
 
445
*  INPUTS
 
446
*     void *ctx           - the communication context (sge_gdi_ctx_class_t *)
 
447
*     char *taskname      - The name of the entry for which to look in the qtask
 
448
*                           files
 
449
*     lList **answer_list - For returning error information
 
450
*
 
451
*  RESULT
 
452
*     char **           A NULL-terminated array of args for the given qtask
 
453
*                       entry
 
454
*
 
455
*  NOTES
 
456
*     MT-NOTE: sge_get_qtask_args() is MT safe with respect to itself, but it is
 
457
*              not thread safe to use this function in conjuction with the
 
458
*              init_qtask_config() or sge_init() functions or accessing the
 
459
*              task_config global variable.
 
460
*
 
461
*******************************************************************************/
 
462
char **sge_get_qtask_args(void *context, char *taskname, lList **answer_list)
 
463
{
 
464
   const char *value = NULL; 
 
465
   int num_args = 0;
 
466
   lListElem *task = NULL;
 
467
   char** args = NULL;
 
468
   sge_gdi_ctx_class_t *ctx = (sge_gdi_ctx_class_t *)context;
 
469
   
 
470
   DENTER (TOP_LAYER, "sge_get_qtask_args");
 
471
   
 
472
   if (mode_verbose) {
 
473
      fprintf(stderr, "sge_get_qtask_args(taskname = %s)\n", taskname);
 
474
   }
 
475
 
 
476
   /* If the task_config has not been filled yet, fill it.  We call
 
477
    * init_qtask_config() instead of sge_init() because we don't need to setup
 
478
    * the GDI.  We just need the qtask arguments. */
 
479
   /* We lock this part because multi-threaded DRMAA apps can have problems
 
480
    * here.  Once we're past this part, qtask_config's read-only, so we don't
 
481
    * have any more problems. */
 
482
   sge_mutex_lock("qtask_mutex", SGE_FUNC, __LINE__, &qtask_mutex);
 
483
    
 
484
   if (task_config == NULL) {
 
485
      /* Just using printf here since we don't really have an exciting function
 
486
       * like xprintf to pass in.  This was really meant for use with qtsch. */
 
487
      if (init_qtask_config(ctx, answer_list, (print_func_t)printf) != 0) {
 
488
         sge_mutex_unlock("qtask_mutex", SGE_FUNC, __LINE__, &qtask_mutex);
 
489
         DEXIT;
 
490
         return args;
 
491
      }
 
492
   }
 
493
 
 
494
   sge_mutex_unlock("qtask_mutex", SGE_FUNC, __LINE__, &qtask_mutex);
 
495
   
 
496
   task = lGetElemStr(task_config, CF_name, taskname);
 
497
   
 
498
   if (task == NULL) {
 
499
      DEXIT;
 
500
      return args;
 
501
   }
 
502
  
 
503
   value = lGetString(task, CF_value);
 
504
   
 
505
   if (value != NULL) {
 
506
      num_args = sge_quick_count_num_args(value);
 
507
   }
 
508
   
 
509
   args = (char **)malloc(sizeof(char *) * (num_args + 1));   
 
510
   memset(args, 0, sizeof(char *) * (num_args + 1));
 
511
   sge_parse_args (value, args);
 
512
   
 
513
   DEXIT;
 
514
   return args;
 
515
}
 
516
 
 
517
void sge_init(
 
518
print_func_t ostream 
 
519
) {
 
520
   lList *alp = NULL;
 
521
   sge_gdi_ctx_class_t *ctx = NULL;
 
522
 
 
523
   /* TODO:
 
524
    *  sge_gdi_param(SET_EXIT_ON_ERROR, 0, NULL);
 
525
    */
 
526
   if (sge_gdi2_setup(&ctx, QTCSH, MAIN_THREAD, NULL) == AE_OK) {
 
527
      if (init_qtask_config(ctx, &alp, ostream) != 0 ) {
 
528
         mode_remote = 0;          
 
529
      } else {
 
530
         /* Remote execution is default.
 
531
 
 
532
            Turn off remote execution only in case we were 
 
533
            started in the context of an already running job.
 
534
            This is done to prevent recursive 
 
535
 
 
536
              qrsh -> qtcsh -> qrsh -> qtcsh -> ...
 
537
 
 
538
            submission via SGE/SGE in case qtcsh
 
539
            is the login shell at the execution server.
 
540
          */
 
541
         if ( mode_remote != 0 ) {
 
542
            mode_remote = force_remote?mode_remote:!getenv("JOB_ID");          
 
543
         }
 
544
/*          (*ostream) ("mode_remote = %d\n", mode_remote); */
 
545
      }
 
546
      lFreeList(&alp);
 
547
   } else {
 
548
      mode_remote = 0;          
 
549
/*       (*ostream) ("no $SGE_ROOT, running as normal tcsh\n"); */
 
550
   }
 
551
 
 
552
   return;
 
553
}
 
554
 
 
555
void set_sgemode(
 
556
int addr,
 
557
int value 
 
558
) {
 
559
   switch (addr) {
 
560
   case CATCH_EXEC_MODE_REMOTE:
 
561
      mode_remote = value;
 
562
      break;
 
563
   case CATCH_EXEC_MODE_VERBOSE:
 
564
      mode_verbose = value;
 
565
      break;
 
566
   case CATCH_EXEC_MODE_IMMEDIATE:
 
567
      mode_immediate = value;
 
568
      break;
 
569
   case CATCH_EXEC_MODE_FORCE_REMOTE:
 
570
      force_remote = value;
 
571
      break;
 
572
   default:
 
573
      break;
 
574
  }      
 
575
  return;
 
576
}
 
577
 
 
578
int get_sgemode(
 
579
int addr 
 
580
) {
 
581
   int value = -1;
 
582
 
 
583
   switch (addr) {
 
584
   case CATCH_EXEC_MODE_REMOTE:
 
585
      value = mode_remote;
 
586
      break;
 
587
   case CATCH_EXEC_MODE_VERBOSE:
 
588
      value = mode_verbose;
 
589
      break;
 
590
   case CATCH_EXEC_MODE_IMMEDIATE:
 
591
      value = mode_immediate;
 
592
   default:
 
593
      break;
 
594
  }      
 
595
  return value;
 
596
}