1 /*****************************************************************************
2  *
3  *  Copyright (C) 2002-2007 The Regents of the University of California.
4  *  Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC.
5  *  Produced at Lawrence Livermore National Laboratory.
6  *  Written by Mark Grondona <mgrondona@llnl.gov>.
7  *
8  *  UCRL-CODE-235358
9  *
10  *  This file is part of chaos-spankings, a set of spank plugins for SLURM.
11  *
12  *  This is free software; you can redistribute it and/or modify it
13  *  under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This is distributed in the hope that it will be useful, but WITHOUT
18  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20  *  for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  ****************************************************************************
25  *  An option --core=<arg> is added for the srun command.
26  *  Valid arguments are normal, light, lcb and list.
27  ****************************************************************************/
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 
36 #include <slurm/spank.h>
37 
38 #define CORE_INVALID -1
39 #define CORE_NORMAL 0
40 #define CORE_LIGHT  1 /* Default lightweight corefile from liblwcf */
41 #define CORE_LCB    2 /* PTOOLS Lightweight Corefile Browser (LCB) compliant*/
42 #define CORE_LIST   3 /* List core format types to stdout and exit */
43 #define LIB_LIGHT   "liblwcf-preload.so"
44 
45 struct core_format_info {
46 	int type;
47 	const char *name;
48 	const char *descr;
49 };
50 
51 /*
52  * Supported types for core=%s
53  */
54 struct core_format_info core_types[] = {
55 	{ CORE_NORMAL,
56 	  "normal",
57 	  "Default full corefile (do nothing)"
58         },
59 	{ CORE_LIGHT,
60 	  "light",
61 	  "liblwcf default lightweight corefile format"
62         },
63 	{ CORE_LCB,
64 	  "lcb",
65 	  "liblwcf Lightweight Corefile Browser compliant"
66 	},
67 	{ CORE_LIST,
68 	  "list",
69 	  "list valid core format types"
70 	},
71 	{ CORE_INVALID,
72 	  NULL,
73 	  "Invalid format"
74 	}
75 };
76 
77 /*
78  * All spank plugins must define this macro for the Slurm plugin loader.
79  */
80 SPANK_PLUGIN(core, 1)
81 
82 static int core_mode = CORE_NORMAL;
83 
84 static int _opt_process (int val, const char *optarg, int remote);
85 
86 struct spank_option spank_option_array[] =
87 {
88 	{ "core", "format", "Core file format", 1, 0,
89 	  (spank_opt_cb_f) _opt_process },
90 	SPANK_OPTIONS_TABLE_END
91 };
92 
_print_valid_core_types(void)93 static void _print_valid_core_types (void)
94 {
95 	struct core_format_info *ci;
96 
97 	info ("Valid corefile format types:");
98 	for (ci = core_types; ci && ci->name; ci++) {
99 		if ((ci->type == CORE_LIGHT) ||
100 		    (ci->type == CORE_LCB)) {
101 			struct stat buf;
102 			if ((stat("/lib/"           LIB_LIGHT, &buf) < 0) &&
103 			    (stat("/usr/lib/"       LIB_LIGHT, &buf) < 0) &&
104 			    (stat("/usr/local/lib/" LIB_LIGHT, &buf) < 0))
105 				continue;
106 		}
107 		if (ci->type != CORE_LIST)
108 			info(" %-8s -- %s", ci->name, ci->descr);
109 	}
110 	return;
111 }
112 
_opt_process(int val,const char * optarg,int remote)113 static int _opt_process (int val, const char *optarg, int remote)
114 {
115 	int i;
116 	struct core_format_info *ci;
117 
118 	for (ci = core_types; ci && ci->name; ci++) {
119 		if (strcasecmp(optarg, ci->name))
120 			continue;
121 		core_mode = ci->type;
122 		if (core_mode == CORE_LIST) {
123 			_print_valid_core_types();
124 			exit(0);
125 		}
126 		return ESPANK_SUCCESS;
127 	}
128 
129 	slurm_error("Invalid core option: %s", optarg);
130 	exit(-1);
131 }
132 
slurm_spank_init(spank_t sp,int ac,char ** av)133 int slurm_spank_init(spank_t sp, int ac, char **av)
134 {
135 	spank_context_t context;
136 	int i, j, rc = ESPANK_SUCCESS;
137 	char *core_env;
138 
139 	for (i=0; spank_option_array[i].name; i++) {
140 		j = spank_option_register(sp, &spank_option_array[i]);
141 		if (j != ESPANK_SUCCESS) {
142 			slurm_error("Could not register Spank option %s",
143 				    spank_option_array[i].name);
144 			rc = j;
145 		}
146 	}
147 
148 	context = spank_context();
149 	if (context == S_CTX_LOCAL) {
150 		core_env = getenv("SLURM_CORE_FORMAT");
151 		if (core_env)
152 			rc = _opt_process(0, core_env, 0);
153 	}
154 
155 	return rc;
156 }
157 
slurm_spank_init_post_opt(spank_t sp,int ac,char ** av)158 int slurm_spank_init_post_opt (spank_t sp, int ac, char **av)
159 {
160 	spank_context_t context;
161 	int rc = ESPANK_SUCCESS;
162 
163 	context = spank_context();
164 	if (context != S_CTX_LOCAL)
165 		return rc;
166 
167 	switch (core_mode) {
168 	case CORE_NORMAL:
169 	case CORE_INVALID:
170 		break;
171 	case CORE_LCB:
172 		setenvfs("LWCF_CORE_FORMAT=LCB");
173 	case CORE_LIGHT:
174 		setenvfs("LD_PRELOAD=" LIB_LIGHT);
175 		break;
176 	}
177 
178 	return rc;
179 }
180