1 /*****************************************************************************\
2  *  src/common/env.h - environment vector manipulation
3  *****************************************************************************
4  *  Copyright (C) 2002-2006 The Regents of the University of California.
5  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
6  *  Written by Mark Grondona <mgrondona@llnl.gov>.
7  *  CODE-OCEC-09-009. All rights reserved.
8  *
9  *  This file is part of Slurm, a resource management program.
10  *  For details, see <https://slurm.schedmd.com/>.
11  *  Please also read the included file: DISCLAIMER.
12  *
13  *  Slurm is free software; you can redistribute it and/or modify it under
14  *  the terms of the GNU General Public License as published by the Free
15  *  Software Foundation; either version 2 of the License, or (at your option)
16  *  any later version.
17  *
18  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
19  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
21  *  details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
25  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
26 \*****************************************************************************/
27 #ifndef _ENV_H
28 #define _ENV_H
29 
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <sys/utsname.h>
33 
34 #include "slurm/slurm.h"
35 #include "src/common/macros.h"
36 #include "src/common/slurm_opt.h"
37 #include "src/common/slurm_protocol_api.h"
38 
39 typedef struct env_options {
40 	int ntasks;		/* --ntasks=n,      -n n	*/
41 	char *task_count;
42 	bool ntasks_set;	/* true if ntasks explicitly set */
43 	bool cpus_set;		/* true if cpus_per_task explicitly set */
44 	task_dist_states_t distribution; /* --distribution=, -m dist	*/
45 	uint16_t plane_size;         /* plane_size for SLURM_DIST_PLANE */
46 	cpu_bind_type_t
47 		cpu_bind_type;	/* --cpu-bind=			*/
48 	char *cpu_bind;		/* binding map for map/mask_cpu	*/
49 	uint32_t cpu_freq_min;  /* Minimum cpu frequency  */
50 	uint32_t cpu_freq_max;  /* Maximum cpu frequency  */
51 	uint32_t cpu_freq_gov;  /* cpu frequency governor */
52 	mem_bind_type_t
53 		mem_bind_type;	/* --mem-bind=			*/
54 	char *mem_bind;		/* binding map for tasks to memory	*/
55 	bool overcommit;	/* --overcommit,   -O		*/
56 	int  slurmd_debug;	/* --slurmd-debug, -D           */
57 	bool labelio;		/* --label-output, -l		*/
58 	dynamic_plugin_data_t *select_jobinfo;
59 	int nhosts;
60 	char *nodelist;		/* nodelist in string form */
61 	char *partition;	/* partition name */
62 	char **env;             /* job environment */
63 	uint16_t comm_port;	/* srun's communication port */
64 	slurm_addr_t *cli;	/* launch node address */
65 	slurm_addr_t *self;
66 	char *job_name;		/* assigned job name */
67 	int jobid;		/* assigned job id */
68 	int stepid;	        /* assigned step id */
69 	int procid;		/* global task id (across nodes) */
70 	int localid;		/* local task id (within node) */
71 	int nodeid;
72 	int cpus_per_task;	/* --cpus-per-task=n, -c n	*/
73 	int ntasks_per_node;	/* --ntasks-per-node=n		*/
74 	int ntasks_per_socket;	/* --ntasks-per-socket=n	*/
75 	int ntasks_per_core;	/* --ntasks-per-core=n		*/
76 	int cpus_on_node;
77 	pid_t task_pid;
78 	char *sgtids;		/* global ranks array of integers */
79 	uint16_t pty_port;	/* used to communicate window size changes */
80 	uint16_t ws_col;	/* window size, columns */
81 	uint16_t ws_row;	/* window size, row count */
82 	uint16_t restart_cnt;	/* count of job restarts	*/
83 	uint16_t batch_flag;	/* 1 if batch: queued job with script */
84 	uint32_t uid;		/* user ID */
85 	char *user_name;	/* user name */
86 	char *account;          /* job's account */
87 	char *qos;              /* job's qos */
88 	char *resv_name;        /* job's reservation */
89 } env_t;
90 
91 
92 /* NOTE: These functions operate on the job's current environment
93  * if env is NULL, otherwise they operate on the argument array */
94 int	envcount (char **env);
95 char *	getenvp(char **env, const char *name);
96 int	setenvf(char ***envp, const char *name, const char *fmt, ...)
97 		__attribute__ ((format (printf, 3, 4)));
98 int	setenvfs(const char *fmt, ...);
99 void	unsetenvp(char **env, const char *name);
100 
101 int	setup_env(env_t *env, bool preserve_env);
102 
103 /**********************************************************************
104  * Newer environment variable handling scheme
105  **********************************************************************/
106 /*
107  * Set in "dest" the environment variables relevant to a Slurm job
108  * allocation, overwriting any environment variables of the same name.
109  * If the address pointed to by "dest" is NULL, memory will automatically be
110  * xmalloc'ed.  The array is terminated by a NULL pointer, and thus is
111  * suitable for use by execle() and other env_array_* functions.
112  *
113  * dest OUT - array in which to the set environment variables
114  * alloc IN - resource allocation response
115  * desc IN - job allocation request
116  * het_job_offset IN - component offset into hetjob, -1 if not hetjob
117  *
118  * Sets the variables:
119  *	SLURM_JOB_ID
120  *	SLURM_JOB_NUM_NODES
121  *	SLURM_JOB_NODELIST
122  *	SLURM_JOB_CPUS_PER_NODE
123  *	LOADLBATCH (AIX only)
124  *
125  * Sets OBSOLETE variables:
126  *	? probably only needed for users...
127  */
128 extern int env_array_for_job(char ***dest,
129 			     const resource_allocation_response_msg_t *alloc,
130 			     const job_desc_msg_t *desc, int het_job_offset);
131 
132 /*
133  * Set in "dest" the environment variables relevant to a Slurm batch
134  * job allocation, overwriting any environment variables of the same name.
135  * If the address pointed to by "dest" is NULL, memory will automatically be
136  * xmalloc'ed.  The array is terminated by a NULL pointer, and thus is
137  * suitable for use by execle() and other env_array_* functions.
138  *
139  * Sets the variables:
140  *	SLURM_JOB_ID
141  *	SLURM_JOB_NUM_NODES
142  *	SLURM_JOB_NODELIST
143  *	SLURM_JOB_CPUS_PER_NODE
144  *	ENVIRONMENT=BATCH
145  *	HOSTNAME
146  *	LOADLBATCH (AIX only)
147  *
148  * Sets OBSOLETE variables:
149  *	SLURM_JOBID
150  *	SLURM_NNODES
151  *	SLURM_NODELIST
152  *	SLURM_TASKS_PER_NODE <- poorly named, really CPUs per node
153  *	? probably only needed for users...
154  */
155 extern int env_array_for_batch_job(char ***dest,
156 				   const batch_job_launch_msg_t *batch,
157 				   const char* node_name);
158 
159 /*
160  * Set in "dest" the environment variables relevant to a Slurm job step,
161  * overwriting any environment variables of the same name.  If the address
162  * pointed to by "dest" is NULL, memory will automatically be xmalloc'ed.
163  * The array is terminated by a NULL pointer, and thus is suitable for
164  * use by execle() and other env_array_* functions.  If preserve_env is
165  * true, the variables SLURM_NNODES and SLURM_NTASKS remain unchanged.
166  *
167  * Sets variables:
168  *	SLURM_STEP_ID
169  *	SLURM_STEP_NUM_NODES
170  *	SLURM_STEP_NUM_TASKS
171  *	SLURM_STEP_TASKS_PER_NODE
172  *	SLURM_STEP_LAUNCHER_PORT
173  *	SLURM_STEP_LAUNCHER_IPADDR
174  *	SLURM_STEP_RESV_PORTS
175  *
176  * Sets OBSOLETE variables:
177  *	SLURM_STEPID
178  *      SLURM_NNODES
179  *	SLURM_NTASKS
180  *	SLURM_NODELIST
181  *	SLURM_TASKS_PER_NODE
182  *	SLURM_SRUN_COMM_HOST
183  *	SLURM_SRUN_COMM_PORT
184  *	SLURM_LAUNCH_NODE_IPADDR
185  *
186  */
187 extern void
188 env_array_for_step(char ***dest,
189 		   const job_step_create_response_msg_t *step,
190 		   launch_tasks_request_msg_t *launch,
191 		   uint16_t launcher_port,
192 		   bool preserve_env);
193 
194 /*
195  * Return an empty environment variable array (contains a single
196  * pointer to NULL).
197  */
198 char **env_array_create(void);
199 
200 /*
201  * Unset all of the environment variables in a user's current
202  * environment.
203  */
204 void env_unset_environment(void);
205 
206 /*
207  * Merge all of the environment variables in src_array into the
208  * array dest_array.  Any variables already found in dest_array
209  * will be overwritten with the value from src_array.
210  */
211 void env_array_merge(char ***dest_array, const char **src_array);
212 
213 /*
214  * Merge the environment variables in src_array beginning with "SLURM" into the
215  * array dest_array.  Any variables already found in dest_array will be
216  * overwritten with the value from src_array.
217  */
218 void env_array_merge_slurm(char ***dest_array, const char **src_array);
219 
220 /*
221  * Copy env_array must be freed by env_array_free
222  */
223 char **env_array_copy(const char **array);
224 
225 /*
226  * Free the memory used by an environment variable array.
227  */
228 void env_array_free(char **env_array);
229 
230 /*
231  * Append a single environment variable to an environment variable array,
232  * if and only if a variable by that name does not already exist in the
233  * array.
234  *
235  * Return 1 on success, and 0 on error.
236  */
237 int env_array_append(char ***array_ptr, const char *name,
238 		     const char *value);
239 
240 /*
241  * Append a single environment variable to an environment variable array,
242  * if and only if a variable by that name does not already exist in the
243  * array.
244  *
245  * "value_fmt" supports printf-style formatting.
246  *
247  * Return 1 on success, and 0 on error.
248  */
249 int env_array_append_fmt(char ***array_ptr, const char *name,
250 			 const char *value_fmt, ...)
251   __attribute__ ((format (printf, 3, 4)));
252 
253 /*
254  * Append a single environment variable to an environment variable array
255  * if a variable by that name does not already exist.  If a variable
256  * by the same name is found in the array, it is overwritten with the
257  * new value.
258  *
259  * Return 1 on success, and 0 on error.
260  */
261 int env_array_overwrite(char ***array_ptr, const char *name,
262 			const char *value);
263 
264 /*
265  * Append a single environment variable to an environment variable array
266  * if a variable by that name does not already exist.  If a variable
267  * by the same name is found in the array, it is overwritten with the
268  * new value.  The "value_fmt" string may contain printf-style options.
269  *
270  * "value_fmt" supports printf-style formatting.
271  *
272  * Return 1 on success, and 0 on error.
273  */
274 int env_array_overwrite_fmt(char ***array_ptr, const char *name,
275 			    const char *value_fmt, ...)
276   __attribute__ ((format (printf, 3, 4)));
277 
278 /*
279  * Append a single environment variable to an environment variable array
280  * if a variable by that name does not already exist.  If a variable
281  * by the same name is found in the array, it is overwritten with the
282  * new value.  The "value_fmt" string may contain printf-style options.
283  *
284  * "value_fmt" supports printf-style formatting.
285  *
286  * Return 1 on success, and 0 on error.
287  */
288 int env_array_overwrite_het_fmt(char ***array_ptr, const char *name,
289 				int het_job_offset,
290 				const char *value_fmt, ...)
291   __attribute__ ((format (printf, 4, 5)));
292 
293 /*
294  * Set in the running process's environment all of the environment
295  * variables in a supplied environment variable array.
296  */
297 void env_array_set_environment(char **env_array);
298 
299 /*
300  * load environment from specified file name.
301  */
302 char **env_array_from_file(const char *filename);
303 
304 /*
305  * Return an array of strings representing the specified user's default
306  * environment variables following a two-prongged approach.
307  * 1. Execute (more or less): "/bin/su - <username> -c /usr/bin/env"
308  *    Depending upon the user's login scripts, this may take a very
309  *    long time to complete or possibly never return
310  * 2. Load the user environment from a cache file. This is used
311  *    in the event that option 1 times out.  This only happens if no_cache isn't
312  *    set.  If it is set then NULL will be returned if the normal load fails.
313  *
314  * timeout value is in seconds or zero for default (8 secs)
315  * mode is 1 for short ("su <user>"), 2 for long ("su - <user>")
316  * On error, returns NULL.
317  *
318  * NOTE: The calling process must have an effective uid of root for
319  * this function to succeed.
320  */
321 char **env_array_user_default(const char *username, int timeout, int mode,
322 			      bool no_cache);
323 
324 /*
325  * Return a string representation of an array of uint16_t elements.
326  * Each value in the array is printed in decimal notation and elements
327  * are separated by a comma.  If sequential elements in the array
328  * contain the same value, the value is written out just once followed
329  * by "(xN)", where "N" is the number of times the value is repeated.
330  *
331  * Example:
332  *   The array "1, 2, 1, 1, 1, 3, 2" becomes the string "1,2,1(x3),3,2"
333  *
334  * Returns an xmalloc'ed string.  Free with xfree().
335  */
336 extern char *uint16_array_to_str(int array_len, const uint16_t *array);
337 
338 /*
339  * The cpus-per-node representation in Slurm (and perhaps tasks-per-node
340  * in the future) is stored in a compressed format comprised of two
341  * equal-length arrays, and an integer holding the array length. In one
342  * array an element represents a count (number of cpus, number of tasks,
343  * etc.), and the corresponding element in the other array contains the
344  * number of times the count is repeated sequentially in the uncompressed
345  * something-per-node array.
346  *
347  * This function returns the string representation of the compressed
348  * array.  Free with xfree().
349  */
350 char *uint32_compressed_to_str(uint32_t array_len,
351 			       const uint16_t *array,
352 			       const uint32_t *array_reps);
353 
354 /*
355  * Set TRES related env vars. Set here rather than env_array_for_job() since
356  * we don't have array of opt values and the raw values are not stored in the
357  * job_desc_msg_t structure (only the strings with possibly combined TRES)
358  *
359  * opt IN - options set by command parsing
360  * dest IN/OUT - location to write environment variables
361  * het_job_offset IN - component offset into hetjob, -1 if not hetjob
362  */
363 extern void set_env_from_opts(slurm_opt_t *opt, char ***dest,
364 			      int het_job_offset);
365 
366 /*
367  * Parse token's skipping nested commas.
368  *
369  * Similar to strtok_r but handles nested commas.
370  *
371  * e.g. FOO='a,b,c',BAR='d,e,f'
372  */
373 extern char *find_quote_token(char *tmp, char *sep, char **last);
374 
375 #endif
376