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

« back to all changes in this revision

Viewing changes to source/libs/uti/sge_smf.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
 
 
33
#if defined(SOLARIS)
 
34
 
 
35
#include <string.h>
 
36
#include <stdlib.h>
 
37
#include <stdio.h>
 
38
#include <fcntl.h>
 
39
#include <errno.h>
 
40
#include <limits.h>
 
41
#include <dlfcn.h>
 
42
#include <pthread.h>
 
43
 
 
44
#include "sge_smf.h"
 
45
#include "sge_string.h"
 
46
#include "sge_log.h"
 
47
#include "sgermon.h"
 
48
#include "sge_uidgid.h"
 
49
#include "msg_utilib.h"
 
50
 
 
51
#if defined(__SunOS_5_7) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
 
52
   /* Redefinitions from S10+ sys/types.h */
 
53
   typedef id_t    ctid_t;
 
54
   /* Missing in SunOS < 10 */
 
55
   static int unsetenv(const char *var) {
 
56
      /* dummy */
 
57
      return 0;
 
58
   }
 
59
#else
 
60
   #include <stdlib.h>
 
61
#endif
 
62
 
 
63
/* Redefinitions from libcontract.h */
 
64
typedef void *ct_stathdl_t;
 
65
 
 
66
/* Redefinitions from sys/contract.h */
 
67
#define CTD_COMMON      0       /* No additional detail */
 
68
#define CTD_FIXED       1       /* O(1) info */
 
69
#define CTD_ALL         2       /* O(n) info */
 
70
 
 
71
 
 
72
/* Redefinitions from sys/contract/process.h */
 
73
#define CT_PR_INHERIT   0x1     /* give contract to parent */
 
74
#define CT_PR_NOORPHAN  0x2     /* kill when contract is abandoned */
 
75
#define CT_PR_PGRPONLY  0x4     /* only kill process group on fatal errors */
 
76
#define CT_PR_REGENT    0x8     /* automatically detach inherited contracts */
 
77
#define CT_PR_ALLPARAM  0xf
 
78
 
 
79
#define CT_PR_EV_EMPTY  0x1     /* contract is empty */
 
80
#define CT_PR_EV_FORK   0x2     /* process was forked (and was added) */
 
81
#define CT_PR_EV_EXIT   0x4     /* process exited (and left contract) */
 
82
#define CT_PR_EV_CORE   0x8     /* process dumps core */
 
83
#define CT_PR_EV_SIGNAL 0x10    /* process received fatal signal */
 
84
#define CT_PR_EV_HWERR  0x20    /* process experienced uncorrectable error */
 
85
#define CT_PR_ALLEVENT  0x3f
 
86
#define CT_PR_ALLFATAL  (CT_PR_EV_CORE | CT_PR_EV_SIGNAL | CT_PR_EV_HWERR)
 
87
 
 
88
/* Redefinitions from sys/ctfs.h */
 
89
#define CTFS_ROOT       "/system/contract"
 
90
 
 
91
/* Redefinitions from libscf.h */
 
92
typedef struct scf_handle scf_handle_t;
 
93
typedef struct scf_simple_prop scf_simple_prop_t;
 
94
 
 
95
#define SMF_IMMEDIATE                   0x1
 
96
#define SMF_TEMPORARY                   0x2
 
97
#define SMF_AT_NEXT_BOOT                0x4
 
98
 
 
99
typedef enum scf_error {
 
100
        SCF_ERROR_NONE = 1000,          /* no error */
 
101
        SCF_ERROR_NOT_BOUND,            /* handle not bound */
 
102
        SCF_ERROR_NOT_SET,              /* cannot use unset argument */
 
103
        SCF_ERROR_NOT_FOUND,            /* nothing of that name found */
 
104
        SCF_ERROR_TYPE_MISMATCH,        /* type does not match value */
 
105
        SCF_ERROR_IN_USE,               /* cannot modify while in-use */
 
106
        SCF_ERROR_CONNECTION_BROKEN,    /* repository connection gone */
 
107
        SCF_ERROR_INVALID_ARGUMENT,     /* bad argument */
 
108
        SCF_ERROR_NO_MEMORY,            /* no memory available */
 
109
        SCF_ERROR_CONSTRAINT_VIOLATED,  /* required constraint not met */
 
110
        SCF_ERROR_EXISTS,               /* object already exists */
 
111
        SCF_ERROR_NO_SERVER,            /* repository server unavailable */
 
112
        SCF_ERROR_NO_RESOURCES,         /* server has insufficient resources */
 
113
        SCF_ERROR_PERMISSION_DENIED,    /* insufficient privileges for action */
 
114
        SCF_ERROR_BACKEND_ACCESS,       /* backend refused access */
 
115
        SCF_ERROR_HANDLE_MISMATCH,      /* mismatched SCF handles */
 
116
        SCF_ERROR_HANDLE_DESTROYED,     /* object bound to destroyed handle */
 
117
        SCF_ERROR_VERSION_MISMATCH,     /* incompatible SCF version */
 
118
        SCF_ERROR_BACKEND_READONLY,     /* backend is read-only */
 
119
        SCF_ERROR_DELETED,              /* object has been deleted */
 
120
 
 
121
        SCF_ERROR_CALLBACK_FAILED = 1080, /* user callback function failed */
 
122
 
 
123
        SCF_ERROR_INTERNAL = 1101       /* internal error */
 
124
} scf_error_t;
 
125
 
 
126
 
 
127
/* Our new defines */
 
128
#define QMASTER_FMRI "svc:/application/sge/qmaster:"
 
129
#define SHADOWD_FMRI "svc:/application/sge/shadowd:"
 
130
#define EXECD_FMRI   "svc:/application/sge/execd:"
 
131
 
 
132
static int libsLoaded             = -1;
 
133
static int libscfLoaded           = -1;
 
134
static int libcontractLoaded      = -1;
 
135
static char *FMRI                 = NULL;
 
136
static int useSMF                 = -1;
 
137
 
 
138
pthread_once_t FMRIcontrol        = PTHREAD_ONCE_INIT;
 
139
pthread_once_t useSMFcontrol      = PTHREAD_ONCE_INIT;
 
140
pthread_once_t libscontrol        = PTHREAD_ONCE_INIT;
 
141
pthread_once_t libscfcontrol      = PTHREAD_ONCE_INIT;
 
142
pthread_once_t libcontractcontrol = PTHREAD_ONCE_INIT;
 
143
 
 
144
/* LIBSCF */
 
145
static void* scf_lib = NULL;
 
146
/* Used libscf function pointers */
 
147
static scf_error_t (*shared_scf_func__scf_error)(void);
 
148
static const char *(*shared_scf_func__scf_strerror)(scf_error_t);
 
149
static scf_simple_prop_t *(*shared_scf_func__scf_simple_prop_get)(scf_handle_t *handle, 
 
150
        const char *instance, const char *pgname, const char *propname);
 
151
static char *(*shared_scf_func__scf_simple_prop_next_astring)(scf_simple_prop_t *prop);
 
152
static void (*shared_scf_func__scf_simple_prop_free)(scf_simple_prop_t *prop);
 
153
static char *(*shared_scf_func__smf_get_state)(const char *fmri);
 
154
static int (*shared_scf_func__smf_disable_instance)(const char *fmri, int flag);
 
155
 
 
156
/* LIBCONTRACT */
 
157
static void* contract_lib = NULL;
 
158
/* Used libcontract function pointers */
 
159
static int (*shared_contract_func__ct_tmpl_activate)(int ctfd);
 
160
static int (*shared_contract_func__ct_tmpl_clear)(int ctfd);
 
161
static int (*shared_contract_func__ct_tmpl_set_critical)(int ctfd, uint_t flag);
 
162
static int (*shared_contract_func__ct_tmpl_set_informative)(int ctfd, uint_t flag);
 
163
static int (*shared_contract_func__ct_ctl_abandon)(int ctfd);
 
164
static int (*shared_contract_func__ct_status_read)(int ctfd, int flag, ct_stathdl_t *st);
 
165
static void (*shared_contract_func__ct_status_free)(ct_stathdl_t st);
 
166
static ctid_t(*shared_contract_func__ct_status_get_id)(ct_stathdl_t st);
 
167
static int (*shared_contract_func__ct_pr_tmpl_set_fatal)(int ctfd, uint_t flag);
 
168
static int (*shared_contract_func__ct_pr_tmpl_set_param)(int ctfd, uint_t flag);
 
169
 
 
170
 
 
171
/************************** sge_init_lib() *************************************
 
172
*  NAME
 
173
*    sge_init_lib() -- loads func_name symbols from shared library lib_name
 
174
*                       and stores the func_ptr
 
175
*  SYNOPSIS
 
176
*    static int sge_init_lib(void *lib_ptr, 
 
177
*                            char *lib_name, 
 
178
*                            const char *func_name[],
 
179
*                            const void *func_ptr[])
 
180
*
 
181
*  FUNCTION
 
182
*    loads func_name symbols from shared lib lib_name and stores the func_ptr
 
183
*
 
184
*  INPUTS
 
185
*    void *lib_ptr           - pointer to the opened shared lib (dlopen())
 
186
*    char *lib_name          - name of the library (e.g: "libcontract.so")
 
187
*    const char *func_name[] - array of library function names to be loaded
 
188
*    const void *func_ptr[]  - destination array for each function
 
189
*
 
190
*  RESULT
 
191
*     int - error state
 
192
*         0 - no error
 
193
*         1 - error
 
194
*
 
195
*  NOTES
 
196
*     LOCAL helper function
 
197
*
 
198
*  SEE ALSO
 
199
*     init_scf_lib()
 
200
*     init_contract_lib()
 
201
*******************************************************************************/
 
202
static int sge_init_lib(void *lib_ptr, char *lib_name, 
 
203
                        const char *func_name[], const void *func_ptr[]) 
 
204
{
 
205
    int ret;
 
206
    
 
207
    DENTER(TOP_LAYER, "sge_init_lib");
 
208
    
 
209
    if (lib_ptr == NULL) {
 
210
        lib_ptr = dlopen(lib_name, RTLD_LAZY | RTLD_NODELETE);
 
211
        if (lib_ptr != NULL) {
 
212
            int i = 0;
 
213
            while (func_name[i] != NULL) {
 
214
                *((int**)(func_ptr[i])) = (int*)dlsym(lib_ptr, func_name[i]);
 
215
                
 
216
                if (*((int**)(func_ptr[i])) == NULL) {
 
217
                    DPRINTF(("%s: unable to initialize function %s\n",
 
218
                            "sge_init_lib", func_name[i]));
 
219
                    DRETURN(1);
 
220
                } else {
 
221
                    DPRINTF(("function "SFQ" successfully initialized\n",
 
222
                            func_name[i]));
 
223
                }
 
224
                i++;
 
225
            }
 
226
            ret = 0;
 
227
        } else {
 
228
            DPRINTF(("Can't open %s library\n", lib_name));
 
229
            ret = 1;
 
230
        }
 
231
    } else {
 
232
        ret = 1;
 
233
    }
 
234
    DRETURN(ret);
 
235
}
 
236
 
 
237
 
 
238
/************************** init_scf_lib() *************************************
 
239
*  NAME
 
240
*    init_scf_lib() -- initialize shared SCF library
 
241
*
 
242
*  SYNOPSIS
 
243
*    static void init_scf_lib(void)
 
244
*
 
245
*  FUNCTION
 
246
*    Stores the required SCF library functions to the appropriate function 
 
247
*    pointers.
 
248
*
 
249
*  INPUTS
 
250
*    void
 
251
*
 
252
*  RESULT
 
253
*    void
 
254
*
 
255
*  NOTES
 
256
*     LOCAL helper function, to be called only in once_libscf_init() as
 
257
*     pthread_once init function
 
258
*
 
259
*  SEE ALSO
 
260
*     once_libscf_init()
 
261
*******************************************************************************/
 
262
static void init_scf_lib(void) 
 
263
{
 
264
    const char *func_name[] = {
 
265
        "scf_error",
 
266
        "scf_strerror",
 
267
        "scf_simple_prop_get",
 
268
        "scf_simple_prop_next_astring",
 
269
        "scf_simple_prop_free",
 
270
        "smf_get_state",
 
271
        "smf_disable_instance",
 
272
        NULL
 
273
    };
 
274
    
 
275
    const void *func_ptr[] = {
 
276
        &shared_scf_func__scf_error,
 
277
        &shared_scf_func__scf_strerror,
 
278
        &shared_scf_func__scf_simple_prop_get,
 
279
        &shared_scf_func__scf_simple_prop_next_astring,
 
280
        &shared_scf_func__scf_simple_prop_free,
 
281
        &shared_scf_func__smf_get_state,
 
282
        &shared_scf_func__smf_disable_instance,
 
283
        NULL
 
284
    };
 
285
    
 
286
    DENTER(TOP_LAYER, "init_scf_lib");
 
287
    if (sge_init_lib(scf_lib, "libscf.so", func_name, func_ptr) == 0) {
 
288
        libscfLoaded = 1;
 
289
    } else {
 
290
        libscfLoaded = 0;
 
291
    }
 
292
    DEXIT;
 
293
}
 
294
 
 
295
 
 
296
/********************** once_libscf_init() *************************************
 
297
*  NAME
 
298
*    once_libscf_init() -- initialize shared SCF library
 
299
*
 
300
*  SYNOPSIS
 
301
*    static int once_libscf_init(void)
 
302
*
 
303
*  FUNCTION
 
304
*    Stores the required SCF library functions to the appropriate function 
 
305
*    pointers.
 
306
*
 
307
*  INPUTS
 
308
*    void
 
309
*
 
310
*  RESULT
 
311
*    int - result
 
312
*        0 - libscf was not loaded (ERROR)
 
313
*        1 - libscf was loaded (SUCCESS)
 
314
*
 
315
*  NOTES
 
316
*     LOCAL helper function, to be called as pthread_once init function
 
317
*
 
318
*  SEE ALSO
 
319
*     sge_smf_init_libs()
 
320
*     sge_smf_temporary_disable_instance()
 
321
*******************************************************************************/
 
322
static int once_libscf_init(void) 
 
323
{
 
324
    DENTER(TOP_LAYER, "once_libscf_init");
 
325
    /* Init scf lib ONCE */
 
326
    if (pthread_once(&libscfcontrol, init_scf_lib) != 0) {
 
327
        DPRINTF(("once_libscf_init() -> pthread_once call failed: useSMF=%d, libscf=%d, libcontract=%d\n",
 
328
                 useSMF, libscfLoaded, libcontractLoaded));
 
329
        DRETURN(1);
 
330
    }
 
331
    DPRINTF(("once_libscf_init() -> useSMF=%d, libscf=%d, libcontract=%d\n", 
 
332
             useSMF, libscfLoaded, libcontractLoaded));
 
333
    DRETURN((libscfLoaded == 1) ? 0 : 1);
 
334
}
 
335
 
 
336
 
 
337
/********************* init_contract_lib() *************************************
 
338
*  NAME
 
339
*    init_contract_lib() -- initialize shared CONTRACT library
 
340
*
 
341
*  SYNOPSIS
 
342
*    static void init_contract_lib(void)
 
343
*
 
344
*  FUNCTION
 
345
*    Stores the required CONTRACT library functions to the appropriate function 
 
346
*    pointers.
 
347
*
 
348
*  INPUTS
 
349
*    void
 
350
*
 
351
*  RESULT
 
352
*    void
 
353
*
 
354
*  NOTES
 
355
*     LOCAL helper function, to be called as pthread_once init function
 
356
*
 
357
*  SEE ALSO
 
358
*     sge_smf_init_libs()
 
359
*******************************************************************************/
 
360
static void init_contract_lib(void) 
 
361
{
 
362
    const char *func_name[] = {
 
363
        "ct_tmpl_activate",
 
364
        "ct_tmpl_clear",
 
365
        "ct_tmpl_set_critical",
 
366
        "ct_tmpl_set_informative",
 
367
        "ct_ctl_abandon",
 
368
        "ct_status_read",
 
369
        "ct_status_free",
 
370
        "ct_status_get_id",
 
371
        "ct_pr_tmpl_set_fatal",
 
372
        "ct_pr_tmpl_set_param",
 
373
        NULL
 
374
    };
 
375
    
 
376
    const void *func_ptr[] = {
 
377
        &shared_contract_func__ct_tmpl_activate,
 
378
        &shared_contract_func__ct_tmpl_clear,
 
379
        &shared_contract_func__ct_tmpl_set_critical,
 
380
        &shared_contract_func__ct_tmpl_set_informative,
 
381
        &shared_contract_func__ct_ctl_abandon,
 
382
        &shared_contract_func__ct_status_read,
 
383
        &shared_contract_func__ct_status_free,
 
384
        &shared_contract_func__ct_status_get_id,
 
385
        &shared_contract_func__ct_pr_tmpl_set_fatal,
 
386
        &shared_contract_func__ct_pr_tmpl_set_param,
 
387
        NULL
 
388
    };
 
389
    
 
390
    DENTER(TOP_LAYER, "init_contract_lib");
 
391
    if (sge_init_lib(contract_lib, "libcontract.so", func_name, func_ptr) == 0) {
 
392
        libcontractLoaded = 1;
 
393
    } else {
 
394
        libcontractLoaded = 0;
 
395
    }
 
396
    DEXIT;
 
397
}
 
398
 
 
399
 
 
400
/************************** init_scf_lib() *************************************
 
401
*  NAME
 
402
*    init_smf_libs() -- initialize shared SCF library
 
403
*
 
404
*  SYNOPSIS
 
405
*    static void init_smf_libs(void)
 
406
*
 
407
*  FUNCTION
 
408
*    Stores the required SCF library functions to the appropriate function 
 
409
*    pointers.
 
410
*
 
411
*  INPUTS
 
412
*    void
 
413
*
 
414
*  RESULT
 
415
*    void
 
416
*
 
417
*  NOTES
 
418
*     LOCAL helper function, to be called only in as pthread_once init function
 
419
*
 
420
*  SEE ALSO
 
421
*     sge_smf_init_libs()
 
422
*******************************************************************************/
 
423
static void init_smf_libs(void) 
 
424
{   
 
425
    DENTER(TOP_LAYER, "init_smf_libs");
 
426
    /* Init shared libs ONCE */
 
427
    once_libscf_init();
 
428
    pthread_once(&libcontractcontrol, init_contract_lib);
 
429
    if (libscfLoaded && libcontractLoaded) {
 
430
        libsLoaded = 1;
 
431
    } else {
 
432
        libsLoaded = 0;
 
433
    }
 
434
    DEXIT;
 
435
}
 
436
 
 
437
 
 
438
/********************** sge_smf_init_libs() ************************************
 
439
*  NAME
 
440
*    sge_smf_init_libs() -- initialize SCF and CONTRACT shared libraries
 
441
*
 
442
*  SYNOPSIS
 
443
*    int sge_smf_init_libs(void)
 
444
*
 
445
*  FUNCTION
 
446
*    Try once to initialize SCF and CONTRACT shared libraries
 
447
*
 
448
*  INPUTS
 
449
*    void
 
450
*
 
451
*  RESULT
 
452
*    int - result
 
453
*        0 - loading was successful
 
454
*        1 - loading failed (ERROR)
 
455
*
 
456
*  NOTES
 
457
*     MT-NOTES: sge_smf_init_libs is MT-safe because it modifies once 
 
458
*               static variables (libsLoaded) and returns it's value next time
 
459
*
 
460
*  SEE ALSO
 
461
*     sge_smf_init_libs()
 
462
*     sge_smf_temporary_disable_instance()
 
463
*******************************************************************************/
 
464
int sge_smf_init_libs(void) 
 
465
{
 
466
    DENTER(TOP_LAYER, "sge_smf_init_libs");
 
467
    /* Init shared libs ONCE */
 
468
    pthread_once(&libscontrol, init_smf_libs);
 
469
    DRETURN((libsLoaded == 1) ? 0 : 1);
 
470
}
 
471
 
 
472
 
 
473
/********************** is_valid_sge_fmri() ************************************
 
474
*  NAME
 
475
*    sge_smf_init_libs() -- initialize SCF and CONTRACT shared libraries
 
476
*
 
477
*  SYNOPSIS
 
478
*    static int is_valid_sge_fmri(char *fmri)
 
479
*
 
480
*  FUNCTION
 
481
*    Checks if service's fmri starts with valid sge service name
 
482
*
 
483
*  INPUTS
 
484
*    char* fmri - service fmri to be validated
 
485
*
 
486
*  RESULT
 
487
*    int - result
 
488
*        0 - invalid fmri (ERROR)
 
489
*        1 - valid fmri (OK)
 
490
*
 
491
*  NOTES
 
492
*     LOCAL helper function
 
493
*
 
494
*  SEE ALSO
 
495
*     init_fmri()
 
496
*     get_fmri()
 
497
*******************************************************************************/
 
498
static int is_valid_sge_fmri(char *fmri) 
 
499
{
 
500
    DENTER(TOP_LAYER, "is_valid_sge_fmri");
 
501
    
 
502
    /* Test for execd */
 
503
    if (strncmp(EXECD_FMRI, fmri, strlen(EXECD_FMRI)) == 0) {
 
504
        DRETURN(1);
 
505
    }
 
506
    /* Test for qmaster */
 
507
    if (strncmp(QMASTER_FMRI, fmri, strlen(QMASTER_FMRI)) == 0) {
 
508
        DRETURN(1);
 
509
    }
 
510
    /* Test for shadowd */
 
511
    if (strncmp(SHADOWD_FMRI, fmri, strlen(SHADOWD_FMRI)) == 0) {
 
512
        DRETURN(1);
 
513
    }
 
514
    DRETURN(0);
 
515
}
 
516
 
 
517
/***************************** init_fmri() *************************************
 
518
*  NAME
 
519
*    init_fmri() -- initialize shared SCF library
 
520
*
 
521
*  SYNOPSIS
 
522
*    static void init_fmri(void) 
 
523
*
 
524
*  FUNCTION
 
525
*    Detects service FMRI if process was started over SMF and stores the name
 
526
*    to static variable called FMRI.
 
527
*
 
528
*  INPUTS
 
529
*    void
 
530
*
 
531
*  RESULT
 
532
*    void
 
533
*
 
534
*  NOTES
 
535
*     LOCAL helper function, to be called only in as pthread_once init function
 
536
*
 
537
*  SEE ALSO
 
538
*     get_fmri()
 
539
*******************************************************************************/
 
540
static void init_fmri(void) 
 
541
{
 
542
    DENTER(TOP_LAYER, "init_fmri");
 
543
    /* Will be set is started over SMF */
 
544
    char *temp = getenv("SMF_FMRI");
 
545
    /* We explicitly check the fmri for valid service names */
 
546
    if (temp && is_valid_sge_fmri(temp)) {
 
547
        FMRI = sge_strdup(NULL, temp);
 
548
        DPRINTF(("init_fmri() - FMRI set to %s\n", (FMRI==NULL) ? "NULL" : FMRI));
 
549
    }
 
550
    DEXIT;
 
551
}
 
552
 
 
553
 
 
554
/******************************* get_fmri() ************************************
 
555
*  NAME
 
556
*    get_fmri() -- initialize fmri and return the value
 
557
*
 
558
*  SYNOPSIS
 
559
*    static char *get_fmri(void)
 
560
*
 
561
*  FUNCTION
 
562
*    Once initializes service fmri and always returns the initialized value.
 
563
*     
 
564
*  INPUTS
 
565
*    void
 
566
*
 
567
*  RESULT
 
568
*    char* - result
 
569
*        NULL - no FMRI, smf was/can not be used
 
570
*        other - valid service fmri of this process
 
571
*
 
572
*  NOTES
 
573
*     LOCAL helper function
 
574
*
 
575
*  SEE ALSO
 
576
*     init_use_smf()
 
577
*******************************************************************************/
 
578
static char *get_fmri(void) 
 
579
{
 
580
    DENTER(TOP_LAYER, "get_fmri");
 
581
    if (pthread_once(&FMRIcontrol, init_fmri) != 0) {
 
582
        ERROR((SGE_EVENT, MSG_SMF_PTHREAD_ONCE_FAILED_S, "get_fmri()"));
 
583
    }
 
584
    DPRINTF(("get_fmri() -> useSMF=%d, FMRI=%s\n",
 
585
             useSMF, (FMRI==NULL) ? "NULL" : FMRI));
 
586
    DRETURN(FMRI);
 
587
}
 
588
 
 
589
 
 
590
/***************************** init_use_smf() **********************************
 
591
*  NAME
 
592
*    init_use_smf() -- initialize useSMF variable
 
593
*
 
594
*  SYNOPSIS
 
595
*    static void init_use_smf(void) 
 
596
*
 
597
*  FUNCTION
 
598
*    Initialize useSMF variable. Set to 1 only if system is SMF capable and
 
599
*    process was started over SMF. 0 otherwise.
 
600
*
 
601
*  INPUTS
 
602
*    void
 
603
*
 
604
*  RESULT
 
605
*    void
 
606
*
 
607
*  NOTES
 
608
*     LOCAL helper function, to be called only in as pthread_once init function
 
609
*
 
610
*  SEE ALSO
 
611
*     sge_smf_used()
 
612
*******************************************************************************/
 
613
static void init_use_smf(void) 
 
614
{
 
615
    struct stat buff;
 
616
    int fd, status;
 
617
    
 
618
    DENTER(TOP_LAYER, "init_use_smf");
 
619
    
 
620
    if (get_fmri() == NULL) {
 
621
        useSMF = 0;
 
622
        DRETURN_VOID;
 
623
    }
 
624
    /* We check if we use SMF */
 
625
    fd = open("/etc/svc/volatile/repository_door", O_RDONLY);
 
626
    if (fd == -1) {
 
627
        /* File does not exist - no SMF */
 
628
        useSMF = 0;
 
629
    } else {
 
630
        status = fstat(fd, &buff);
 
631
        if (status == -1) {
 
632
            if (errno == ENOENT) {
 
633
                /* File does not exist - no SMF */
 
634
                useSMF = 0;
 
635
            } else {
 
636
                ERROR((SGE_EVENT, "Repository stat call failed: %s", *strerror(errno)));
 
637
                useSMF = 0;
 
638
                /* What now disable queues or just disable SMF ? */
 
639
            }
 
640
        } else {
 
641
            /* USING SMF ONLY if having sge FMRI and repository_door is really a door */
 
642
            useSMF = S_ISDOOR(buff.st_mode);
 
643
        }
 
644
        close(fd);
 
645
    }
 
646
    DEXIT;
 
647
}
 
648
 
 
649
 
 
650
/*************************** sge_smf_used() ************************************
 
651
*  NAME
 
652
*    sge_smf_used() -- once initialize useSMF ad return it's value
 
653
*
 
654
*  SYNOPSIS
 
655
*    int sge_smf_used(void)
 
656
*
 
657
*  FUNCTION
 
658
*    Once initialize useSMF ad return it's value
 
659
*
 
660
*  INPUTS
 
661
*    void
 
662
*
 
663
*  RESULT
 
664
*    int - result
 
665
*        0 - smf is not being used
 
666
*        1 - smf is being used
 
667
*
 
668
*  NOTES
 
669
*     MT-NOTES: sge_smf_used is MT-safe because it modifies once 
 
670
*               static variables (useSMF) and returns it's value next time
 
671
*
 
672
*  SEE ALSO
 
673
*     sge_smf_contract_fork()
 
674
*******************************************************************************/
 
675
int sge_smf_used(void) 
 
676
{
 
677
    DENTER(TOP_LAYER, "sge_smf_used");
 
678
    if (pthread_once(&useSMFcontrol, init_use_smf) != 0) {
 
679
        ERROR((SGE_EVENT, MSG_SMF_PTHREAD_ONCE_FAILED_S, "sge_smf_used()"));
 
680
    }
 
681
    DPRINTF(("sge_smf_used() -> useSMF=%d\n", useSMF));
 
682
    DRETURN(useSMF);
 
683
}
 
684
 
 
685
 
 
686
/********************** contracts_pre_fork() ***********************************
 
687
*  NAME
 
688
*    contracts_pre_fork() -- initialize contract template
 
689
*
 
690
*  SYNOPSIS
 
691
*    static int contracts_pre_fork(void)
 
692
*
 
693
*  FUNCTION
 
694
*    Initialize contract template
 
695
*
 
696
*  INPUTS
 
697
*    void
 
698
*
 
699
*  RESULT
 
700
*    int - result
 
701
*          -1 - contract template creation failed
 
702
*       other - fd to the contract template
 
703
*
 
704
*  NOTES
 
705
*     LOCAL helper function
 
706
*
 
707
*  SEE ALSO
 
708
*     sge_smf_contract_fork()
 
709
*******************************************************************************/
 
710
static int contracts_pre_fork(void) 
 
711
{
 
712
    int fd;
 
713
    int err = 0;
 
714
    
 
715
    DENTER(TOP_LAYER, "contracts_pre_fork");
 
716
    
 
717
    fd = open64(CTFS_ROOT "/process/template", O_RDWR);
 
718
    if (fd == -1) {
 
719
        DRETURN(-1);
 
720
    }
 
721
    /*
 
722
     * Execd doesn't do anything with the new contract.
 
723
     * Deliver no events, don't inherit, and allow it to be orphaned.
 
724
     */
 
725
    err |= shared_contract_func__ct_tmpl_set_critical(fd, 0);
 
726
    err |= shared_contract_func__ct_tmpl_set_informative(fd, 0);
 
727
    err |= shared_contract_func__ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
 
728
    err |= shared_contract_func__ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY);
 
729
    if (err || shared_contract_func__ct_tmpl_activate(fd)) {
 
730
        close(fd);
 
731
        DRETURN(-1);
 
732
    }
 
733
    DRETURN(fd);
 
734
}
 
735
 
 
736
 
 
737
/********************** contracts_post_fork() **********************************
 
738
*  NAME
 
739
*    contracts_post_fork() -- close template, abandon new contract in parent
 
740
*
 
741
*  SYNOPSIS
 
742
*    static int contracts_post_fork(int ctfd, 
 
743
*                                   int pid, 
 
744
*                                   char *err_str, 
 
745
*                                   int err_length)
 
746
*
 
747
*  FUNCTION
 
748
*    To be called after fork(). Close the contract templated created in 
 
749
*    contract_pre_fork(). In parent process we abandon the new contract.
 
750
*
 
751
*  INPUTS
 
752
*    int ctfd       - contract template fd
 
753
*    int pid        - result of fork()
 
754
*    char *err_str  - pointer for error message
 
755
*    int err_length - max error message length
 
756
*
 
757
*  RESULT
 
758
*    int - result
 
759
*          -1 - fork() failed
 
760
*          -2 - contracts_post_fork() failed
 
761
*          input pid otherwise
 
762
*
 
763
*  NOTES
 
764
*     LOCAL helper function
 
765
*
 
766
*  SEE ALSO
 
767
*     sge_smf_contract_fork()
 
768
*******************************************************************************/
 
769
static int contracts_post_fork(int ctfd, int pid, char *err_str, int err_length) 
 
770
{
 
771
    char path[PATH_MAX]; /* PATH_MAX defined in limits.h */
 
772
    int cfd, n;
 
773
    ct_stathdl_t st;
 
774
    ctid_t latest;
 
775
    DENTER(TOP_LAYER, "contracts_post_fork");
 
776
    /* Clear active template, abandon latest contract. */
 
777
    if (ctfd == -1) {
 
778
        DRETURN(-1);
 
779
    }
 
780
    shared_contract_func__ct_tmpl_clear(ctfd);
 
781
    close(ctfd);
 
782
    if (pid == 0) {
 
783
       /* We modify the child env not to contain SMF vars (not part of the service) */
 
784
       unsetenv("SMF_FMRI");
 
785
       unsetenv("SMF_METHOD");
 
786
       unsetenv("SMF_RESTARTER");
 
787
       DRETURN(pid);
 
788
    } else if (pid < 0) {
 
789
       DRETURN(pid);
 
790
    }
 
791
    /* Parent has to explicitly abandon the new contract */
 
792
    if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1) {
 
793
        snprintf(err_str,err_length, MSG_SMF_CONTRACT_CREATE_FAILED_S, 
 
794
                 *strerror(errno));
 
795
        DRETURN(-2);
 
796
    }
 
797
    if ((errno = shared_contract_func__ct_status_read(cfd, CTD_COMMON, &st)) != 0) {
 
798
        snprintf(err_str, err_length, MSG_SMF_CONTRACT_CREATE_FAILED_S, 
 
799
                 *strerror(errno));
 
800
        close(cfd);
 
801
        DRETURN(-2);
 
802
    }
 
803
    latest = shared_contract_func__ct_status_get_id(st);
 
804
    shared_contract_func__ct_status_free(st);
 
805
    close(cfd);
 
806
    n = snprintf(path, PATH_MAX, CTFS_ROOT "/all/%ld/ctl", latest);
 
807
    if (n >= PATH_MAX) {
 
808
        snprintf(err_str, err_length, MSG_SMF_CONTRACT_CONTROL_OPEN_FAILED_S,
 
809
                 *strerror(ENAMETOOLONG));
 
810
        DRETURN(-2);
 
811
    }
 
812
    if ((cfd = open64(path, O_WRONLY)) == -1) {
 
813
        snprintf(err_str, err_length, MSG_SMF_CONTRACT_CONTROL_OPEN_FAILED_S,
 
814
                 *strerror(errno));
 
815
        DRETURN(-2);
 
816
    }
 
817
    if (shared_contract_func__ct_ctl_abandon(cfd)) {
 
818
        snprintf(err_str, err_length, MSG_SMF_CONTRACT_ABANDON_FAILED_US,
 
819
                 cfd, *strerror(errno));
 
820
        (void) close(cfd);
 
821
        DRETURN(-2);
 
822
    }
 
823
    close(cfd);
 
824
    DRETURN(pid);
 
825
}
 
826
 
 
827
 
 
828
/*************************** sge_smf_contract_fork() ***************************
 
829
*  NAME
 
830
*    sge_smf_contract_fork() -- fork() with child in new contract
 
831
*
 
832
*  SYNOPSIS
 
833
*    int sge_smf_contract_fork(char *err_str, int err_length)
 
834
*
 
835
*  FUNCTION
 
836
*    Once initialize useSMF ad return it's value
 
837
*
 
838
*  INPUTS
 
839
*    char *err_str  - error message
 
840
*    int err_length - max error message length
 
841
*
 
842
*  RESULT
 
843
*    int - result
 
844
*          -1 - fork failed
 
845
*          -2 - contract_pre_fork failed
 
846
*          -3 - contract_post_fork failed
 
847
*          -4 - smflibs could not be loaded
 
848
*          result of fork() otherwise
 
849
*
 
850
*  NOTES
 
851
*     MT-NOTES: sge_smf_contract_fork is not MT-safe
 
852
*
 
853
*  SEE ALSO
 
854
*     
 
855
*******************************************************************************/
 
856
int sge_smf_contract_fork(char *err_str, int err_length)
 
857
{
 
858
    int pid;
 
859
    int ctfd;
 
860
    DENTER(TOP_LAYER, "sge_smf_contract_fork");
 
861
    
 
862
    if (sge_smf_used() == 0) {
 
863
        pid=fork();
 
864
        DPRINTF(("normally forked %d\n", pid));
 
865
        DRETURN(pid);
 
866
    } else {
 
867
        /* Check if shared libs were loaded */
 
868
        if (libsLoaded == 0) {
 
869
            snprintf(err_str, err_length, MSG_SMF_LOAD_LIB_FAILED);
 
870
            DRETURN(-4);
 
871
        }
 
872
        /* Create new contract template */
 
873
        ctfd = contracts_pre_fork();
 
874
        if (ctfd == -1) {
 
875
            /* Could not create new contract template */
 
876
            snprintf(err_str, err_length, MSG_SMF_CONTRACT_CREATE_FAILED);
 
877
            DRETURN(-2);
 
878
        } else {
 
879
        /* fork */
 
880
            pid = fork();
 
881
        /* Dispose of the template and immediatelly abandon the contract */
 
882
            pid = contracts_post_fork(ctfd, pid, err_str, err_length);
 
883
            if (pid == -2) {
 
884
                /* post_fork failed */
 
885
                DRETURN(-3);
 
886
            }
 
887
            DPRINTF(("contract forked %d\n", pid));
 
888
        }
 
889
    }
 
890
    DRETURN(pid);
 
891
}
 
892
 
 
893
 
 
894
/******************** sge_smf_temporary_disable_instance() *********************
 
895
*  NAME
 
896
*    sge_smf_temporary_disable_instance() -- temporary disable smf instance
 
897
*
 
898
*  SYNOPSIS
 
899
*    void sge_smf_temporary_disable_instance(void)
 
900
*
 
901
*  FUNCTION
 
902
*    Temporary disable this service instance in smf
 
903
*
 
904
*  INPUTS
 
905
*    void
 
906
*
 
907
*  RESULT
 
908
*    void
 
909
*
 
910
*  NOTES
 
911
*     Can be called only if sge_smf_used() return 1 and sge_smf_used() was 
 
912
*     previously called.
 
913
*
 
914
*     MT-NOTES: sge_smf_temporary_disable_instance is MT-safe because it 
 
915
*               modifies once static variables (libscfLoaded)
 
916
*               changes user id
 
917
*
 
918
*  SEE ALSO
 
919
*     execd/execd_exit_func()
 
920
*******************************************************************************/
 
921
void sge_smf_temporary_disable_instance(void)
 
922
{
 
923
    uid_t old_euid = NULL;
 
924
    int change_user = 1;
 
925
    DENTER(TOP_LAYER, "sge_smf_temporary_disable_instance");
 
926
    if (once_libscf_init() != 0) {
 
927
        ERROR((SGE_EVENT, MSG_SMF_LOAD_LIBSCF_FAILED_S, "sge_smf_temporary_disable_instance()"));
 
928
        DRETURN_VOID;
 
929
    }
 
930
    /* We need to be root */
 
931
    if (!sge_is_start_user_superuser()) {
 
932
       change_user = 0;
 
933
    } else {
 
934
       old_euid = geteuid();
 
935
       seteuid(SGE_SUPERUSER_UID);
 
936
    }
 
937
    int ret = shared_scf_func__smf_disable_instance(FMRI, SMF_TEMPORARY);
 
938
    if (change_user == 1) {
 
939
       seteuid(old_euid);
 
940
    }
 
941
    if (ret != 0 ) {
 
942
        ERROR((SGE_EVENT, MSG_SMF_DISABLE_FAILED_SSUU,
 
943
               FMRI,shared_scf_func__scf_strerror(shared_scf_func__scf_error()), geteuid(), getuid()));
 
944
        DRETURN_VOID;
 
945
    }
 
946
    DPRINTF(("Service %s temporary disabled.\n", FMRI));
 
947
    DEXIT;
 
948
}
 
949
 
 
950
 
 
951
/******************** sge_smf_get_instance_state() *****************************
 
952
*  NAME
 
953
*    sge_smf_get_instance_state() -- get instance state
 
954
*
 
955
*  SYNOPSIS
 
956
*    char *sge_smf_get_instance_state(void)
 
957
*
 
958
*  FUNCTION
 
959
*    Get this instance state from SMF.
 
960
*
 
961
*  INPUTS
 
962
*    void
 
963
*
 
964
*  RESULT
 
965
*    char * -- state
 
966
*
 
967
*  NOTES
 
968
*    MT-NOTES: sge_smf_get_instance_state is MT-safe
 
969
*
 
970
*  SEE ALSO
 
971
*     sge_smf_get_instance_next_state()
 
972
*******************************************************************************/
 
973
char *sge_smf_get_instance_state(void) {
 
974
    return shared_scf_func__smf_get_state(FMRI);
 
975
}
 
976
 
 
977
 
 
978
/******************** sge_smf_get_instance_next_state() ***********************
 
979
*  NAME
 
980
*    sge_smf_get_instance_next_state() -- get instance state
 
981
*
 
982
*  SYNOPSIS
 
983
*    char *sge_smf_get_instance_next_state(void)
 
984
*
 
985
*  FUNCTION
 
986
*    Get this instance state from SMF.
 
987
*
 
988
*  INPUTS
 
989
*    void
 
990
*
 
991
*  RESULT
 
992
*    char * -- state
 
993
*
 
994
*  NOTES
 
995
*    MT-NOTES: sge_smf_get_instance_state is MT-safe
 
996
*
 
997
*  SEE ALSO
 
998
*     sge_smf_get_instance_next_state()
 
999
*******************************************************************************/
 
1000
char *sge_smf_get_instance_next_state()
 
1001
{
 
1002
    scf_simple_prop_t *prop;
 
1003
    const char *state_str;
 
1004
    char *ret;
 
1005
 
 
1006
    DENTER(TOP_LAYER, "sge_smf_get_instance_next_state");
 
1007
    
 
1008
    if ((prop = shared_scf_func__scf_simple_prop_get(NULL, FMRI, SCF_PG_RESTARTER, SCF_PROPERTY_NEXT_STATE)) == NULL) {
 
1009
       DRETURN(NULL);
 
1010
    }
 
1011
 
 
1012
    if ((state_str = shared_scf_func__scf_simple_prop_next_astring(prop)) == NULL) {
 
1013
       shared_scf_func__scf_simple_prop_free(prop);
 
1014
       DRETURN(NULL);
 
1015
    }
 
1016
 
 
1017
    if ((ret = strdup(state_str)) == NULL) {
 
1018
        ERROR((SGE_EVENT, "Out of memory"));
 
1019
        DRETURN(NULL);
 
1020
    }
 
1021
    
 
1022
    shared_scf_func__scf_simple_prop_free(prop);
 
1023
    DRETURN(ret);
 
1024
}
 
1025
 
 
1026
#else
 
1027
void dummy(void)
 
1028
{
 
1029
    /* Just a dummy function */
 
1030
    return;
 
1031
}
 
1032
#endif