PageRenderTime 74ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sprio/opts.c

https://github.com/cfenoy/slurm
C | 514 lines | 398 code | 44 blank | 72 comment | 90 complexity | d1efb75c8ded4ecc15cc830efe821aad MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /****************************************************************************\
  2. * opts.c - sprio command line option parsing
  3. *****************************************************************************
  4. * Copyright (C) 2009 Lawrence Livermore National Security.
  5. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  6. * Written by Don Lipari <lipari1@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 <http://www.schedmd.com/slurmdocs/>.
  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. * In addition, as a special exception, the copyright holders give permission
  19. * to link the code of portions of this program with the OpenSSL library under
  20. * certain conditions as described in each individual source file, and
  21. * distribute linked combinations including the two. You must obey the GNU
  22. * General Public License in all respects for all of the code used other than
  23. * OpenSSL. If you modify file(s) with this exception, you may extend this
  24. * exception to your version of the file(s), but you are not obligated to do
  25. * so. If you do not wish to do so, delete this exception statement from your
  26. * version. If you delete this exception statement from all source files in
  27. * the program, then also delete it here.
  28. *
  29. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  30. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  31. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  32. * details.
  33. *
  34. * You should have received a copy of the GNU General Public License along
  35. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  36. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  37. \*****************************************************************************/
  38. #ifndef _GNU_SOURCE
  39. # define _GNU_SOURCE
  40. #endif
  41. #ifdef HAVE_CONFIG_H
  42. # include "config.h"
  43. #endif
  44. #if HAVE_GETOPT_H
  45. # include <getopt.h>
  46. #else
  47. # include "src/common/getopt.h"
  48. #endif
  49. #include <pwd.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <sys/types.h>
  53. #include <unistd.h>
  54. #include "src/common/proc_args.h"
  55. #include "src/common/read_config.h"
  56. #include "src/common/uid.h"
  57. #include "src/common/xstring.h"
  58. #include "src/sprio/sprio.h"
  59. /* getopt_long options, integers but not characters */
  60. #define OPT_LONG_HELP 0x100
  61. #define OPT_LONG_USAGE 0x101
  62. /* FUNCTIONS */
  63. static List _build_job_list( char* str );
  64. static List _build_user_list( char* str );
  65. static char *_get_prefix(char *token);
  66. static void _help( void );
  67. static void _parse_token( char *token, char *field, int *field_size,
  68. bool *right_justify, char **suffix);
  69. static void _print_options( void );
  70. static void _usage( void );
  71. static void _opt_env(void)
  72. {
  73. char *env_val;
  74. if ((env_val = getenv("SLURM_CLUSTERS"))) {
  75. if (!(params.clusters = slurmdb_get_info_cluster(env_val))) {
  76. error("'%s' can't be reached now, "
  77. "or it is an invalid entry for "
  78. "SLURM_CLUSTERS. Use 'sacctmgr --list "
  79. "cluster' to see available clusters.",
  80. env_val);
  81. exit(1);
  82. }
  83. }
  84. }
  85. /*
  86. * parse_command_line
  87. */
  88. extern void
  89. parse_command_line( int argc, char* argv[] )
  90. {
  91. int opt_char;
  92. int option_index;
  93. static struct option long_options[] = {
  94. {"noheader", no_argument, 0, 'h'},
  95. {"jobs", optional_argument, 0, 'j'},
  96. {"long", no_argument, 0, 'l'},
  97. {"cluster", required_argument, 0, 'M'},
  98. {"clusters", required_argument, 0, 'M'},
  99. {"norm", no_argument, 0, 'n'},
  100. {"format", required_argument, 0, 'o'},
  101. {"user", required_argument, 0, 'u'},
  102. {"users", required_argument, 0, 'u'},
  103. {"verbose", no_argument, 0, 'v'},
  104. {"version", no_argument, 0, 'V'},
  105. {"weights", no_argument, 0, 'w'},
  106. {"help", no_argument, 0, OPT_LONG_HELP},
  107. {"usage", no_argument, 0, OPT_LONG_USAGE},
  108. {NULL, 0, 0, 0}
  109. };
  110. /* get defaults from environment */
  111. _opt_env();
  112. while((opt_char = getopt_long(argc, argv, "hj::lM:no:u:vVw",
  113. long_options, &option_index)) != -1) {
  114. switch (opt_char) {
  115. case (int)'?':
  116. fprintf(stderr, "Try \"sprio --help\" "
  117. "for more information\n");
  118. exit(1);
  119. case (int)'h':
  120. params.no_header = true;
  121. break;
  122. case (int) 'j':
  123. if (optarg) {
  124. params.jobs = xstrdup(optarg);
  125. params.job_list = _build_job_list(params.jobs);
  126. }
  127. params.job_flag = true;
  128. break;
  129. case (int) 'l':
  130. params.long_list = true;
  131. break;
  132. case (int) 'M':
  133. if(params.clusters)
  134. list_destroy(params.clusters);
  135. if(!(params.clusters =
  136. slurmdb_get_info_cluster(optarg))) {
  137. error("'%s' can't be reached now, "
  138. "or it is an invalid entry for "
  139. "--cluster. Use 'sacctmgr --list "
  140. "cluster' to see available clusters.",
  141. optarg);
  142. exit(1);
  143. }
  144. break;
  145. case (int) 'n':
  146. params.normalized = true;
  147. break;
  148. case (int) 'o':
  149. xfree(params.format);
  150. params.format = xstrdup(optarg);
  151. break;
  152. case (int) 'u':
  153. xfree(params.users);
  154. params.users = xstrdup(optarg);
  155. params.user_list = _build_user_list(params.users);
  156. break;
  157. case (int) 'v':
  158. params.verbose++;
  159. break;
  160. case (int) 'V':
  161. print_slurm_version ();
  162. exit(0);
  163. case (int) 'w':
  164. params.weights = true;
  165. break;
  166. case OPT_LONG_HELP:
  167. _help();
  168. exit(0);
  169. case OPT_LONG_USAGE:
  170. _usage();
  171. exit(0);
  172. }
  173. }
  174. if (optind < argc) {
  175. if (params.job_flag) {
  176. params.jobs = xstrdup(argv[optind++]);
  177. params.job_list = _build_job_list(params.jobs);
  178. }
  179. if (optind < argc) {
  180. error("Unrecognized option: %s",argv[optind]);
  181. _usage();
  182. exit(1);
  183. }
  184. }
  185. if (params.verbose)
  186. _print_options();
  187. if (params.clusters) {
  188. if (list_count(params.clusters) > 1) {
  189. fatal("Only one cluster can be used at a time with "
  190. "sprio");
  191. }
  192. working_cluster_rec = list_peek(params.clusters);
  193. }
  194. }
  195. /*
  196. * parse_format - Take the user's format specification and use it to build
  197. * build the format specifications (internalize it to print.c data
  198. * structures)
  199. * IN format - user's format specification
  200. * RET zero or error code
  201. */
  202. extern int parse_format( char* format )
  203. {
  204. int field_size;
  205. bool right_justify;
  206. char *prefix = NULL, *suffix = NULL, *token = NULL;
  207. char *tmp_char = NULL, *tmp_format = NULL;
  208. char field[1];
  209. if (format == NULL) {
  210. error ("Format option lacks specification.");
  211. exit( 1 );
  212. }
  213. params.format_list = list_create( NULL );
  214. if ((prefix = _get_prefix(format))) {
  215. job_format_add_prefix( params.format_list, 0, 0, prefix);
  216. }
  217. field_size = strlen( format );
  218. tmp_format = xmalloc( field_size + 1 );
  219. strcpy( tmp_format, format );
  220. token = strtok_r( tmp_format, "%", &tmp_char);
  221. if (token && (format[0] != '%')) /* toss header */
  222. token = strtok_r( NULL, "%", &tmp_char );
  223. while (token) {
  224. _parse_token( token, field, &field_size, &right_justify,
  225. &suffix);
  226. if (field[0] == 'a')
  227. job_format_add_age_priority_normalized(params.format_list,
  228. field_size,
  229. right_justify,
  230. suffix );
  231. else if (field[0] == 'A')
  232. job_format_add_age_priority_weighted(params.format_list,
  233. field_size,
  234. right_justify,
  235. suffix );
  236. else if (field[0] == 'f')
  237. job_format_add_fs_priority_normalized(params.format_list,
  238. field_size,
  239. right_justify,
  240. suffix );
  241. else if (field[0] == 'F')
  242. job_format_add_fs_priority_weighted(params.format_list,
  243. field_size,
  244. right_justify,
  245. suffix );
  246. else if (field[0] == 'i')
  247. job_format_add_job_id(params.format_list,
  248. field_size,
  249. right_justify,
  250. suffix );
  251. else if (field[0] == 'j')
  252. job_format_add_js_priority_normalized(params.format_list,
  253. field_size,
  254. right_justify,
  255. suffix );
  256. else if (field[0] == 'J')
  257. job_format_add_js_priority_weighted(params.format_list,
  258. field_size,
  259. right_justify,
  260. suffix );
  261. else if (field[0] == 'N')
  262. job_format_add_job_nice(params.format_list,
  263. field_size,
  264. right_justify,
  265. suffix );
  266. else if (field[0] == 'p')
  267. job_format_add_part_priority_normalized(params.format_list,
  268. field_size,
  269. right_justify,
  270. suffix );
  271. else if (field[0] == 'P')
  272. job_format_add_part_priority_weighted(params.format_list,
  273. field_size,
  274. right_justify,
  275. suffix );
  276. else if (field[0] == 'q')
  277. job_format_add_qos_priority_normalized(params.format_list,
  278. field_size,
  279. right_justify,
  280. suffix );
  281. else if (field[0] == 'Q')
  282. job_format_add_qos_priority_weighted(params.format_list,
  283. field_size,
  284. right_justify,
  285. suffix );
  286. else if (field[0] == 'u')
  287. job_format_add_user_name(params.format_list,
  288. field_size,
  289. right_justify,
  290. suffix );
  291. else if (field[0] == 'y')
  292. job_format_add_job_priority_normalized(params.format_list,
  293. field_size,
  294. right_justify,
  295. suffix );
  296. else if (field[0] == 'Y')
  297. job_format_add_job_priority_weighted(params.format_list,
  298. field_size,
  299. right_justify,
  300. suffix );
  301. else
  302. error( "Invalid job format specification: %c",
  303. field[0] );
  304. token = strtok_r( NULL, "%", &tmp_char);
  305. }
  306. xfree( tmp_format );
  307. return SLURM_SUCCESS;
  308. }
  309. /* Take a format specification and copy out it's prefix
  310. * IN/OUT token - input specification, everything before "%" is removed
  311. * RET - everything before "%" in the token
  312. */
  313. static char *
  314. _get_prefix( char *token )
  315. {
  316. char *pos, *prefix;
  317. if (token == NULL)
  318. return NULL;
  319. pos = strchr(token, (int) '%');
  320. if (pos == NULL) /* everything is prefix */
  321. return xstrdup(token);
  322. if (pos == token) /* no prefix */
  323. return NULL;
  324. pos[0] = '\0'; /* some prefix */
  325. prefix = xstrdup(token);
  326. pos[0] = '%';
  327. memmove(token, pos, (strlen(pos)+1));
  328. return prefix;
  329. }
  330. /* Take a format specification and break it into its components
  331. * IN token - input specification without leading "%", eg. ".5u"
  332. * OUT field - the letter code for the data type
  333. * OUT field_size - byte count
  334. * OUT right_justify - true of field to be right justified
  335. * OUT suffix - string containing everthing after the field specification
  336. */
  337. static void
  338. _parse_token( char *token, char *field, int *field_size, bool *right_justify,
  339. char **suffix)
  340. {
  341. int i = 0;
  342. assert (token != NULL);
  343. if (token[i] == '.') {
  344. *right_justify = true;
  345. i++;
  346. } else
  347. *right_justify = false;
  348. *field_size = 0;
  349. while ((token[i] >= '0') && (token[i] <= '9'))
  350. *field_size = (*field_size * 10) + (token[i++] - '0');
  351. field[0] = token[i++];
  352. *suffix = xstrdup(&token[i]);
  353. }
  354. /* print the parameters specified */
  355. static void
  356. _print_options()
  357. {
  358. ListIterator iterator;
  359. int i;
  360. uint32_t *job_id;
  361. uint32_t *user;
  362. printf( "-----------------------------\n" );
  363. printf( "format = %s\n", params.format );
  364. printf( "job_flag = %d\n", params.job_flag );
  365. printf( "jobs = %s\n", params.jobs );
  366. printf( "users = %s\n", params.users );
  367. printf( "verbose = %d\n", params.verbose );
  368. if ((params.verbose > 1) && params.job_list) {
  369. i = 0;
  370. iterator = list_iterator_create( params.job_list );
  371. while ( (job_id = list_next( iterator )) ) {
  372. printf( "job_list[%d] = %u\n", i++, *job_id);
  373. }
  374. list_iterator_destroy( iterator );
  375. }
  376. if ((params.verbose > 1) && params.user_list) {
  377. i = 0;
  378. iterator = list_iterator_create( params.user_list );
  379. while ( (user = list_next( iterator )) ) {
  380. printf( "user_list[%d] = %u\n", i++, *user);
  381. }
  382. list_iterator_destroy( iterator );
  383. }
  384. printf( "-----------------------------\n\n\n" );
  385. } ;
  386. /*
  387. * _build_job_list- build a list of job_ids
  388. * IN str - comma separated list of job_ids
  389. * RET List of job_ids (uint32_t)
  390. */
  391. static List
  392. _build_job_list( char* str )
  393. {
  394. List my_list;
  395. char *job = NULL, *tmp_char = NULL, *my_job_list = NULL;
  396. int i;
  397. uint32_t *job_id = NULL;
  398. if ( str == NULL)
  399. return NULL;
  400. my_list = list_create( NULL );
  401. my_job_list = xstrdup( str );
  402. job = strtok_r( my_job_list, ",", &tmp_char );
  403. while (job)
  404. {
  405. i = strtol( job, (char **) NULL, 10 );
  406. if (i <= 0) {
  407. error( "Invalid job id: %s", job );
  408. exit( 1 );
  409. }
  410. job_id = xmalloc( sizeof( uint32_t ) );
  411. *job_id = (uint32_t) i;
  412. list_append( my_list, job_id );
  413. job = strtok_r (NULL, ",", &tmp_char);
  414. }
  415. return my_list;
  416. }
  417. /*
  418. * _build_user_list- build a list of UIDs
  419. * IN str - comma separated list of user names
  420. * RET List of UIDs (uint32_t)
  421. */
  422. static List
  423. _build_user_list( char* str )
  424. {
  425. List my_list;
  426. char *user = NULL;
  427. char *tmp_char = NULL, *my_user_list = NULL;
  428. uid_t uid = (uid_t) 0;
  429. if ( str == NULL)
  430. return NULL;
  431. my_list = list_create( NULL );
  432. my_user_list = xstrdup( str );
  433. user = strtok_r( my_user_list, ",", &tmp_char );
  434. while (user) {
  435. if (uid_from_string (user, &uid) < 0) {
  436. error( "Invalid user: %s\n", user);
  437. } else {
  438. uint32_t *u_tmp = xmalloc( sizeof( uint32_t ));
  439. *u_tmp = (uint32_t) uid;
  440. list_append( my_list, u_tmp );
  441. }
  442. user = strtok_r (NULL, ",", &tmp_char);
  443. }
  444. return my_list;
  445. }
  446. static void _usage(void)
  447. {
  448. printf("Usage: sprio [-j jid[s]] [-u user_name[s]] [-o format] [--usage] [-hlnvVw]\n");
  449. }
  450. static void _help(void)
  451. {
  452. printf("\
  453. Usage: sprio [OPTIONS]\n\
  454. -h, --noheader no headers on output\n\
  455. -j, --jobs comma separated list of jobs\n\
  456. to view, default is all\n\
  457. -l, --long long report\n\
  458. -M, --cluster=cluster_name cluster to issue commands to. Default is\n\
  459. current cluster. cluster with no name will\n\
  460. reset to default.\n\
  461. -n, --norm display normalized values\n\
  462. -o, --format=format format specification\n\
  463. -u, --user=user_name comma separated list of users to view\n\
  464. -v, --verbose verbosity level\n\
  465. -V, --version output version information and exit\n\
  466. -w, --weights show the weights for each priority factor\n\
  467. \nHelp options:\n\
  468. --help show this help message\n\
  469. --usage display a brief summary of sprio options\n");
  470. }