PageRenderTime 72ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sinfo/opts.c

https://github.com/cfenoy/slurm
C | 900 lines | 753 code | 67 blank | 80 comment | 203 complexity | dd204d2a6111cc5f68f65d8a8d89f90f MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /****************************************************************************\
  2. * opts.c - sinfo command line option processing functions
  3. *****************************************************************************
  4. * Copyright (C) 2002-2007 The Regents of the University of California.
  5. * Copyright (C) 2008-2010 Lawrence Livermore National Security.
  6. * Portions Copyright (C) 2010 SchedMD <http://www.schedmd.com>.
  7. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  8. * Written by Joey Ekstrom <ekstrom1@llnl.gov>, Morris Jette <jette1@llnl.gov>
  9. * CODE-OCEC-09-009. All rights reserved.
  10. *
  11. * This file is part of SLURM, a resource management program.
  12. * For details, see <http://www.schedmd.com/slurmdocs/>.
  13. * Please also read the included file: DISCLAIMER.
  14. *
  15. * SLURM is free software; you can redistribute it and/or modify it under
  16. * the terms of the GNU General Public License as published by the Free
  17. * Software Foundation; either version 2 of the License, or (at your option)
  18. * any later version.
  19. *
  20. * In addition, as a special exception, the copyright holders give permission
  21. * to link the code of portions of this program with the OpenSSL library under
  22. * certain conditions as described in each individual source file, and
  23. * distribute linked combinations including the two. You must obey the GNU
  24. * General Public License in all respects for all of the code used other than
  25. * OpenSSL. If you modify file(s) with this exception, you may extend this
  26. * exception to your version of the file(s), but you are not obligated to do
  27. * so. If you do not wish to do so, delete this exception statement from your
  28. * version. If you delete this exception statement from all source files in
  29. * the program, then also delete it here.
  30. *
  31. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  32. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  33. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  34. * details.
  35. *
  36. * You should have received a copy of the GNU General Public License along
  37. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  38. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  39. \*****************************************************************************/
  40. #if HAVE_CONFIG_H
  41. # include "config.h"
  42. #endif
  43. #ifndef _GNU_SOURCE
  44. # define _GNU_SOURCE
  45. #endif
  46. #if HAVE_GETOPT_H
  47. # include <getopt.h>
  48. #else
  49. # include "src/common/getopt.h"
  50. #endif
  51. #include <stdlib.h>
  52. #include <unistd.h>
  53. #include "src/common/xstring.h"
  54. #include "src/common/proc_args.h"
  55. #include "src/sinfo/print.h"
  56. #include "src/sinfo/sinfo.h"
  57. /* getopt_long options, integers but not characters */
  58. #define OPT_LONG_HELP 0x100
  59. #define OPT_LONG_USAGE 0x101
  60. #define OPT_LONG_HIDE 0x102
  61. /* FUNCTIONS */
  62. static List _build_state_list( char* str );
  63. static List _build_all_states_list( void );
  64. static char *_get_prefix(char *token);
  65. static void _help( void );
  66. static int _parse_format( char* );
  67. static bool _node_state_equal (int state_id, const char *state_str);
  68. static int _node_state_id (char *str);
  69. static const char * _node_state_list (void);
  70. static void _parse_token( char *token, char *field, int *field_size,
  71. bool *right_justify, char **suffix);
  72. static void _print_options( void );
  73. static void _usage( void );
  74. /*
  75. * parse_command_line, fill in params data structure with data
  76. */
  77. extern void parse_command_line(int argc, char *argv[])
  78. {
  79. char *env_val = NULL;
  80. int opt_char;
  81. int option_index;
  82. hostlist_t host_list;
  83. static struct option long_options[] = {
  84. {"all", no_argument, 0, 'a'},
  85. {"bg", no_argument, 0, 'b'},
  86. {"dead", no_argument, 0, 'd'},
  87. {"exact", no_argument, 0, 'e'},
  88. {"noheader", no_argument, 0, 'h'},
  89. {"iterate", required_argument, 0, 'i'},
  90. {"long", no_argument, 0, 'l'},
  91. {"cluster", required_argument, 0, 'M'},
  92. {"clusters", required_argument, 0, 'M'},
  93. {"nodes", required_argument, 0, 'n'},
  94. {"Node", no_argument, 0, 'N'},
  95. {"format", required_argument, 0, 'o'},
  96. {"partition", required_argument, 0, 'p'},
  97. {"responding",no_argument, 0, 'r'},
  98. {"list-reasons", no_argument, 0, 'R'},
  99. {"summarize", no_argument, 0, 's'},
  100. {"sort", required_argument, 0, 'S'},
  101. {"states", required_argument, 0, 't'},
  102. {"reservation",no_argument, 0, 'T'},
  103. {"verbose", no_argument, 0, 'v'},
  104. {"version", no_argument, 0, 'V'},
  105. {"help", no_argument, 0, OPT_LONG_HELP},
  106. {"usage", no_argument, 0, OPT_LONG_USAGE},
  107. {"hide", no_argument, 0, OPT_LONG_HIDE},
  108. {NULL, 0, 0, 0}
  109. };
  110. if (getenv("SINFO_ALL"))
  111. params.all_flag = true;
  112. if ( ( env_val = getenv("SINFO_PARTITION") ) ) {
  113. params.partition = xstrdup(env_val);
  114. params.all_flag = true;
  115. }
  116. if ( ( env_val = getenv("SINFO_SORT") ) )
  117. params.sort = xstrdup(env_val);
  118. if ( ( env_val = getenv("SLURM_CLUSTERS") ) ) {
  119. if (!(params.clusters = slurmdb_get_info_cluster(env_val))) {
  120. error("'%s' can't be reached now, "
  121. "or it is an invalid entry for "
  122. "SLURM_CLUSTERS. Use 'sacctmgr --list "
  123. "cluster' to see available clusters.",
  124. env_val);
  125. exit(1);
  126. }
  127. working_cluster_rec = list_peek(params.clusters);
  128. }
  129. while((opt_char = getopt_long(argc, argv, "abdehi:lM:n:No:p:rRsS:t:TvV",
  130. long_options, &option_index)) != -1) {
  131. switch (opt_char) {
  132. case (int)'?':
  133. fprintf(stderr,
  134. "Try \"sinfo --help\" for more information\n");
  135. exit(1);
  136. break;
  137. case (int)'a':
  138. params.all_flag = true;
  139. break;
  140. case (int)'b':
  141. params.cluster_flags = slurmdb_setup_cluster_flags();
  142. if (params.cluster_flags & CLUSTER_FLAG_BG)
  143. params.bg_flag = true;
  144. else {
  145. error("Must be on a BG system to use --bg "
  146. "option, if using --cluster option "
  147. "put the --bg option "
  148. "after the --cluster option.");
  149. exit(1);
  150. }
  151. break;
  152. case (int)'d':
  153. params.dead_nodes = true;
  154. break;
  155. case (int)'e':
  156. params.exact_match = true;
  157. break;
  158. case (int)'h':
  159. params.no_header = true;
  160. break;
  161. case (int) 'i':
  162. params.iterate= atoi(optarg);
  163. if (params.iterate <= 0) {
  164. error ("Error: invalid entry for "
  165. "--iterate=%s", optarg);
  166. exit(1);
  167. }
  168. break;
  169. case (int) 'l':
  170. params.long_output = true;
  171. break;
  172. case (int) 'M':
  173. if (params.clusters)
  174. list_destroy(params.clusters);
  175. if (!(params.clusters =
  176. slurmdb_get_info_cluster(optarg))) {
  177. error("'%s' can't be reached now, "
  178. "or it is an invalid entry for "
  179. "--cluster. Use 'sacctmgr --list "
  180. "cluster' to see available clusters.",
  181. optarg);
  182. exit(1);
  183. }
  184. working_cluster_rec = list_peek(params.clusters);
  185. break;
  186. case (int) 'n':
  187. xfree(params.nodes);
  188. params.nodes= xstrdup(optarg);
  189. /*
  190. * confirm valid nodelist entry
  191. */
  192. host_list = hostlist_create(params.nodes);
  193. if (!host_list) {
  194. error("'%s' invalid entry for --nodes",
  195. optarg);
  196. exit(1);
  197. }
  198. hostlist_destroy(host_list);
  199. break;
  200. case (int) 'N':
  201. params.node_flag = true;
  202. break;
  203. case (int) 'o':
  204. xfree(params.format);
  205. params.format = xstrdup(optarg);
  206. break;
  207. case (int) 'p':
  208. xfree(params.partition);
  209. params.partition = xstrdup(optarg);
  210. params.all_flag = true;
  211. break;
  212. case (int) 'r':
  213. params.responding_nodes = true;
  214. break;
  215. case (int) 'R':
  216. params.list_reasons = true;
  217. break;
  218. case (int) 's':
  219. params.summarize = true;
  220. break;
  221. case (int) 'S':
  222. xfree(params.sort);
  223. params.sort = xstrdup(optarg);
  224. break;
  225. case (int) 't':
  226. xfree(params.states);
  227. params.states = xstrdup(optarg);
  228. if (!(params.state_list = _build_state_list(optarg))) {
  229. error ("valid states: %s", _node_state_list ());
  230. exit (1);
  231. }
  232. break;
  233. case (int) 'T':
  234. params.reservation_flag = true;
  235. break;
  236. case (int) 'v':
  237. params.verbose++;
  238. break;
  239. case (int) 'V':
  240. print_slurm_version ();
  241. exit(0);
  242. case (int) OPT_LONG_HELP:
  243. _help();
  244. exit(0);
  245. case (int) OPT_LONG_USAGE:
  246. _usage();
  247. exit(0);
  248. case OPT_LONG_HIDE:
  249. params.all_flag = false;
  250. break;
  251. }
  252. }
  253. params.cluster_flags = slurmdb_setup_cluster_flags();
  254. if ( params.format == NULL ) {
  255. if ( params.summarize ) {
  256. params.part_field_flag = true; /* compute size later */
  257. if (params.cluster_flags & CLUSTER_FLAG_BG)
  258. params.format = "%9P %.5a %.10l %.32F %N";
  259. else
  260. params.format = "%9P %.5a %.10l %.16F %N";
  261. } else if ( params.node_flag ) {
  262. params.node_field_flag = true; /* compute size later */
  263. params.part_field_flag = true; /* compute size later */
  264. params.format = params.long_output ?
  265. "%N %.6D %.9P %.11T %.4c %.8z %.6m %.8d %.6w %.8f %20E" :
  266. "%N %.6D %.9P %6t";
  267. } else if (params.list_reasons) {
  268. params.format = params.long_output ?
  269. "%20E %12U %19H %6t %N" :
  270. "%20E %9u %19H %N";
  271. } else if ((env_val = getenv ("SINFO_FORMAT"))) {
  272. params.format = xstrdup(env_val);
  273. } else {
  274. params.part_field_flag = true; /* compute size later */
  275. params.format = params.long_output ?
  276. "%9P %.5a %.10l %.10s %.4r %.5h %.10g %.6D %.11T %N" :
  277. "%9P %.5a %.10l %.6D %.6t %N";
  278. }
  279. }
  280. _parse_format( params.format );
  281. if (params.list_reasons && (params.state_list == NULL)) {
  282. params.states = xstrdup ("down,drain,error");
  283. if (!(params.state_list = _build_state_list (params.states)))
  284. fatal ("Unable to build state list for -R!");
  285. }
  286. if (params.dead_nodes || params.nodes || params.partition ||
  287. params.responding_nodes ||params.state_list)
  288. params.filtering = true;
  289. if (params.verbose)
  290. _print_options();
  291. }
  292. static char *
  293. _next_tok (char *sep, char **str)
  294. {
  295. char *tok;
  296. /* push str past any leading separators */
  297. while ((**str != '\0') && (strchr(sep, **str) != '\0'))
  298. (*str)++;
  299. if (**str == '\0')
  300. return NULL;
  301. /* assign token ptr */
  302. tok = *str;
  303. /* push str past token and leave pointing to first separator */
  304. while ((**str != '\0') && (strchr(sep, **str) == '\0'))
  305. (*str)++;
  306. /* nullify consecutive separators and push str beyond them */
  307. while ((**str != '\0') && (strchr(sep, **str) != '\0'))
  308. *(*str)++ = '\0';
  309. return (tok);
  310. }
  311. /*
  312. * _build_state_list - build a list of node states
  313. * IN str - comma separated list of job states
  314. * RET List of enum job_states values
  315. */
  316. static List
  317. _build_state_list (char *state_str)
  318. {
  319. List state_ids;
  320. char *orig, *str, *state;
  321. if (state_str == NULL)
  322. return NULL;
  323. if (strcasecmp (state_str, "all") == 0 )
  324. return _build_all_states_list ();
  325. orig = str = xstrdup (state_str);
  326. state_ids = list_create (NULL);
  327. while ((state = _next_tok (",", &str))) {
  328. int *id = xmalloc (sizeof (*id));
  329. if ((*id = _node_state_id (state)) < 0) {
  330. error ("Bad state string: \"%s\"", state);
  331. return (NULL);
  332. }
  333. list_append (state_ids, id);
  334. }
  335. xfree (orig);
  336. return (state_ids);
  337. }
  338. /*
  339. * _build_all_states_list - build a list containing all possible node states
  340. * RET List of enum job_states values
  341. */
  342. static List
  343. _build_all_states_list( void )
  344. {
  345. List my_list;
  346. int i;
  347. uint16_t *state_id;
  348. my_list = list_create( NULL );
  349. for (i = 0; i < NODE_STATE_END; i++) {
  350. state_id = xmalloc( sizeof( uint16_t ) );
  351. *state_id = (uint16_t) i;
  352. list_append( my_list, state_id );
  353. }
  354. state_id = xmalloc( sizeof( uint16_t ) );
  355. *state_id = NODE_STATE_DRAIN;
  356. list_append( my_list, state_id );
  357. state_id = xmalloc( sizeof( uint16_t ) );
  358. *state_id = NODE_STATE_COMPLETING;
  359. list_append( my_list, state_id );
  360. return my_list;
  361. }
  362. static const char *
  363. _node_state_list (void)
  364. {
  365. int i;
  366. static char *all_states = NULL;
  367. if (all_states)
  368. return (all_states);
  369. all_states = xstrdup (node_state_string_compact (0));
  370. for (i = 1; i < NODE_STATE_END; i++) {
  371. xstrcat (all_states, ",");
  372. xstrcat (all_states, node_state_string(i));
  373. }
  374. xstrcat(all_states, ",DRAIN,DRAINED,DRAINING,NO_RESPOND");
  375. xstrcat(all_states, ",");
  376. xstrcat(all_states, node_state_string(NODE_STATE_COMPLETING));
  377. xstrcat(all_states, ",");
  378. xstrcat(all_states, node_state_string(NODE_STATE_POWER_SAVE));
  379. xstrcat(all_states, ",");
  380. xstrcat(all_states, node_state_string(NODE_STATE_FAIL));
  381. xstrcat(all_states, ",");
  382. xstrcat(all_states, node_state_string(NODE_STATE_MAINT));
  383. for (i = 0; i < strlen (all_states); i++)
  384. all_states[i] = tolower (all_states[i]);
  385. return (all_states);
  386. }
  387. static bool
  388. _node_state_equal (int i, const char *str)
  389. {
  390. int len = strlen (str);
  391. if ((strncasecmp(node_state_string_compact(i), str, len) == 0) ||
  392. (strncasecmp(node_state_string(i), str, len) == 0))
  393. return (true);
  394. return (false);
  395. }
  396. /*
  397. * _parse_state - convert node state name string to numeric value
  398. * IN str - state name
  399. * OUT states - node_state value corresponding to str
  400. * RET 0 or error code
  401. */
  402. static int
  403. _node_state_id (char *str)
  404. {
  405. int i;
  406. int len = strlen (str);
  407. for (i = 0; i < NODE_STATE_END; i++) {
  408. if (_node_state_equal (i, str))
  409. return (i);
  410. }
  411. if (strncasecmp("DRAIN", str, len) == 0)
  412. return NODE_STATE_DRAIN;
  413. if (strncasecmp("DRAINED", str, len) == 0)
  414. return NODE_STATE_DRAIN | NODE_STATE_IDLE;
  415. if (strncasecmp("ERROR", str, len) == 0)
  416. return NODE_STATE_ERROR;
  417. if ((strncasecmp("DRAINING", str, len) == 0) ||
  418. (strncasecmp("DRNG", str, len) == 0))
  419. return NODE_STATE_DRAIN | NODE_STATE_ALLOCATED;
  420. if (_node_state_equal (NODE_STATE_COMPLETING, str))
  421. return NODE_STATE_COMPLETING;
  422. if (strncasecmp("NO_RESPOND", str, len) == 0)
  423. return NODE_STATE_NO_RESPOND;
  424. if (_node_state_equal (NODE_STATE_POWER_SAVE, str))
  425. return NODE_STATE_POWER_SAVE;
  426. if (_node_state_equal (NODE_STATE_FAIL, str))
  427. return NODE_STATE_FAIL;
  428. if (_node_state_equal (NODE_STATE_MAINT, str))
  429. return NODE_STATE_MAINT;
  430. return (-1);
  431. }
  432. /* Take the user's format specification and use it to build build the
  433. * format specifications (internalize it to print.c data structures) */
  434. static int
  435. _parse_format( char* format )
  436. {
  437. int field_size;
  438. bool right_justify;
  439. char *prefix = NULL, *suffix = NULL, *token = NULL,
  440. *tmp_char = NULL, *tmp_format = NULL;
  441. char field[1];
  442. if (format == NULL) {
  443. fprintf( stderr, "Format option lacks specification\n" );
  444. exit( 1 );
  445. }
  446. params.format_list = list_create( NULL );
  447. if ((prefix = _get_prefix(format)))
  448. format_add_prefix( params.format_list, 0, 0, prefix);
  449. tmp_format = xstrdup( format );
  450. token = strtok_r( tmp_format, "%", &tmp_char);
  451. if (token && (format[0] != '%')) /* toss header */
  452. token = strtok_r( NULL, "%", &tmp_char );
  453. while (token) {
  454. _parse_token( token, field, &field_size, &right_justify,
  455. &suffix);
  456. if (field[0] == 'a') {
  457. params.match_flags.avail_flag = true;
  458. format_add_avail( params.format_list,
  459. field_size,
  460. right_justify,
  461. suffix );
  462. } else if (field[0] == 'A') {
  463. format_add_nodes_ai( params.format_list,
  464. field_size,
  465. right_justify,
  466. suffix );
  467. } else if (field[0] == 'c') {
  468. params.match_flags.cpus_flag = true;
  469. format_add_cpus( params.format_list,
  470. field_size,
  471. right_justify,
  472. suffix );
  473. } else if (field[0] == 'C') {
  474. params.match_flags.cpus_flag = true;
  475. format_add_cpus_aiot( params.format_list,
  476. field_size,
  477. right_justify,
  478. suffix );
  479. } else if (field[0] == 'd') {
  480. params.match_flags.disk_flag = true;
  481. format_add_disk( params.format_list,
  482. field_size,
  483. right_justify,
  484. suffix );
  485. } else if (field[0] == 'D') {
  486. format_add_nodes( params.format_list,
  487. field_size,
  488. right_justify,
  489. suffix );
  490. } else if (field[0] == 'E') {
  491. params.match_flags.reason_flag = true;
  492. format_add_reason( params.format_list,
  493. field_size,
  494. right_justify,
  495. suffix );
  496. } else if (field[0] == 'f') {
  497. params.match_flags.features_flag = true;
  498. format_add_features( params.format_list,
  499. field_size,
  500. right_justify,
  501. suffix );
  502. } else if (field[0] == 'F') {
  503. format_add_nodes_aiot( params.format_list,
  504. field_size,
  505. right_justify,
  506. suffix );
  507. } else if (field[0] == 'g') {
  508. params.match_flags.groups_flag = true;
  509. format_add_groups( params.format_list,
  510. field_size,
  511. right_justify,
  512. suffix );
  513. } else if (field[0] == 'G') {
  514. params.match_flags.gres_flag = true;
  515. format_add_gres( params.format_list,
  516. field_size,
  517. right_justify,
  518. suffix );
  519. } else if (field[0] == 'h') {
  520. params.match_flags.share_flag = true;
  521. format_add_share( params.format_list,
  522. field_size,
  523. right_justify,
  524. suffix );
  525. } else if (field[0] == 'H') {
  526. params.match_flags.reason_timestamp_flag = true;
  527. format_add_timestamp( params.format_list,
  528. field_size,
  529. right_justify,
  530. suffix );
  531. } else if (field[0] == 'l') {
  532. params.match_flags.max_time_flag = true;
  533. format_add_time( params.format_list,
  534. field_size,
  535. right_justify,
  536. suffix );
  537. } else if (field[0] == 'L') {
  538. params.match_flags.default_time_flag = true;
  539. format_add_default_time( params.format_list,
  540. field_size,
  541. right_justify,
  542. suffix );
  543. } else if (field[0] == 'm') {
  544. params.match_flags.memory_flag = true;
  545. format_add_memory( params.format_list,
  546. field_size,
  547. right_justify,
  548. suffix );
  549. } else if (field[0] == 'M') {
  550. params.match_flags.preempt_mode_flag = true;
  551. format_add_preempt_mode( params.format_list,
  552. field_size,
  553. right_justify,
  554. suffix );
  555. } else if (field[0] == 'n') {
  556. params.match_flags.hostnames_flag = true;
  557. format_add_node_hostnames( params.format_list,
  558. field_size,
  559. right_justify,
  560. suffix );
  561. } else if (field[0] == 'N') {
  562. format_add_node_list( params.format_list,
  563. field_size,
  564. right_justify,
  565. suffix );
  566. } else if (field[0] == 'o') {
  567. params.match_flags.node_addr_flag = true;
  568. format_add_node_address( params.format_list,
  569. field_size,
  570. right_justify,
  571. suffix );
  572. } else if (field[0] == 'O') {
  573. params.match_flags.cpu_load_flag = true;
  574. format_add_cpu_load( params.format_list,
  575. field_size,
  576. right_justify,
  577. suffix );
  578. } else if (field[0] == 'p') {
  579. params.match_flags.priority_flag = true;
  580. format_add_priority( params.format_list,
  581. field_size,
  582. right_justify,
  583. suffix );
  584. } else if (field[0] == 'P') {
  585. params.match_flags.partition_flag = true;
  586. format_add_partition( params.format_list,
  587. field_size,
  588. right_justify,
  589. suffix );
  590. } else if (field[0] == 'r') {
  591. params.match_flags.root_flag = true;
  592. format_add_root( params.format_list,
  593. field_size,
  594. right_justify,
  595. suffix );
  596. } else if (field[0] == 'R') {
  597. params.match_flags.partition_flag = true;
  598. format_add_partition_name( params.format_list,
  599. field_size,
  600. right_justify,
  601. suffix );
  602. } else if (field[0] == 's') {
  603. params.match_flags.job_size_flag = true;
  604. format_add_size( params.format_list,
  605. field_size,
  606. right_justify,
  607. suffix );
  608. } else if (field[0] == 'S') {
  609. format_add_alloc_nodes( params.format_list,
  610. field_size,
  611. right_justify,
  612. suffix );
  613. } else if (field[0] == 't') {
  614. params.match_flags.state_flag = true;
  615. format_add_state_compact( params.format_list,
  616. field_size,
  617. right_justify,
  618. suffix );
  619. } else if (field[0] == 'T') {
  620. params.match_flags.state_flag = true;
  621. format_add_state_long( params.format_list,
  622. field_size,
  623. right_justify,
  624. suffix );
  625. } else if (field[0] == 'u') {
  626. params.match_flags.reason_user_flag = true;
  627. format_add_user( params.format_list,
  628. field_size,
  629. right_justify,
  630. suffix );
  631. } else if (field[0] == 'U') {
  632. params.match_flags.reason_user_flag = true;
  633. format_add_user_long( params.format_list,
  634. field_size,
  635. right_justify,
  636. suffix );
  637. } else if (field[0] == 'w') {
  638. params.match_flags.weight_flag = true;
  639. format_add_weight( params.format_list,
  640. field_size,
  641. right_justify,
  642. suffix );
  643. } else if (field[0] == 'X') {
  644. params.match_flags.sockets_flag = true;
  645. format_add_sockets( params.format_list,
  646. field_size,
  647. right_justify,
  648. suffix );
  649. } else if (field[0] == 'Y') {
  650. params.match_flags.cores_flag = true;
  651. format_add_cores( params.format_list,
  652. field_size,
  653. right_justify,
  654. suffix );
  655. } else if (field[0] == 'Z') {
  656. params.match_flags.threads_flag = true;
  657. format_add_threads( params.format_list,
  658. field_size,
  659. right_justify,
  660. suffix );
  661. } else if (field[0] == 'z') {
  662. params.match_flags.sct_flag = true;
  663. format_add_sct( params.format_list,
  664. field_size,
  665. right_justify,
  666. suffix );
  667. } else {
  668. prefix = xstrdup("%");
  669. xstrcat(prefix, token);
  670. xfree(suffix);
  671. suffix = prefix;
  672. format_add_invalid( params.format_list,
  673. field_size,
  674. right_justify,
  675. suffix );
  676. fprintf(stderr, "Invalid node format specification: %c\n",
  677. field[0] );
  678. }
  679. token = strtok_r( NULL, "%", &tmp_char);
  680. }
  681. xfree( tmp_format );
  682. return SLURM_SUCCESS;
  683. }
  684. /* Take a format specification and copy out it's prefix
  685. * IN/OUT token - input specification, everything before "%" is removed
  686. * RET - everything before "%" in the token
  687. */
  688. static char *
  689. _get_prefix( char *token )
  690. {
  691. char *pos, *prefix;
  692. if (token == NULL)
  693. return NULL;
  694. pos = strchr(token, (int) '%');
  695. if (pos == NULL) /* everything is prefix */
  696. return xstrdup(token);
  697. if (pos == token) /* no prefix */
  698. return NULL;
  699. pos[0] = '\0'; /* some prefix */
  700. prefix = xstrdup(token);
  701. pos[0] = '%';
  702. memmove(token, pos, (strlen(pos)+1));
  703. return prefix;
  704. }
  705. /* Take a format specification and break it into its components
  706. * IN token - input specification without leading "%", eg. ".5u"
  707. * OUT field - the letter code for the data type
  708. * OUT field_size - byte count
  709. * OUT right_justify - true of field to be right justified
  710. * OUT suffix - tring containing everthing after the field specification
  711. */
  712. static void
  713. _parse_token( char *token, char *field, int *field_size, bool *right_justify,
  714. char **suffix)
  715. {
  716. int i = 0;
  717. assert (token != NULL);
  718. if (token[i] == '.') {
  719. *right_justify = true;
  720. i++;
  721. } else
  722. *right_justify = false;
  723. *field_size = 0;
  724. while ((token[i] >= '0') && (token[i] <= '9'))
  725. *field_size = (*field_size * 10) + (token[i++] - '0');
  726. field[0] = token[i++];
  727. *suffix = xstrdup(&token[i]);
  728. }
  729. /* print the parameters specified */
  730. void _print_options( void )
  731. {
  732. printf("-----------------------------\n");
  733. printf("dead = %s\n", params.dead_nodes ? "true" : "false");
  734. printf("exact = %d\n", params.exact_match);
  735. printf("filtering = %s\n", params.filtering ? "true" : "false");
  736. printf("format = %s\n", params.format);
  737. printf("iterate = %d\n", params.iterate );
  738. printf("long = %s\n", params.long_output ? "true" : "false");
  739. printf("no_header = %s\n", params.no_header ? "true" : "false");
  740. printf("node_field = %s\n", params.node_field_flag ?
  741. "true" : "false");
  742. printf("node_format = %s\n", params.node_flag ? "true" : "false");
  743. printf("nodes = %s\n", params.nodes ? params.nodes : "n/a");
  744. printf("part_field = %s\n", params.part_field_flag ?
  745. "true" : "false");
  746. printf("partition = %s\n", params.partition ?
  747. params.partition: "n/a");
  748. printf("responding = %s\n", params.responding_nodes ?
  749. "true" : "false");
  750. printf("states = %s\n", params.states);
  751. printf("sort = %s\n", params.sort);
  752. printf("summarize = %s\n", params.summarize ? "true" : "false");
  753. printf("verbose = %d\n", params.verbose);
  754. printf("-----------------------------\n");
  755. printf("all_flag = %s\n", params.all_flag ? "true" : "false");
  756. printf("avail_flag = %s\n", params.match_flags.avail_flag ?
  757. "true" : "false");
  758. printf("bg_flag = %s\n", params.bg_flag ? "true" : "false");
  759. printf("cpus_flag = %s\n", params.match_flags.cpus_flag ?
  760. "true" : "false");
  761. printf("default_time_flag =%s\n", params.match_flags.default_time_flag ?
  762. "true" : "false");
  763. printf("disk_flag = %s\n", params.match_flags.disk_flag ?
  764. "true" : "false");
  765. printf("features_flag = %s\n", params.match_flags.features_flag ?
  766. "true" : "false");
  767. printf("groups_flag = %s\n", params.match_flags.groups_flag ?
  768. "true" : "false");
  769. printf("gres_flag = %s\n", params.match_flags.gres_flag ?
  770. "true" : "false");
  771. printf("job_size_flag = %s\n", params.match_flags.job_size_flag ?
  772. "true" : "false");
  773. printf("max_time_flag = %s\n", params.match_flags.max_time_flag ?
  774. "true" : "false");
  775. printf("memory_flag = %s\n", params.match_flags.memory_flag ?
  776. "true" : "false");
  777. printf("partition_flag = %s\n", params.match_flags.partition_flag ?
  778. "true" : "false");
  779. printf("priority_flag = %s\n", params.match_flags.priority_flag ?
  780. "true" : "false");
  781. printf("reason_flag = %s\n", params.match_flags.reason_flag ?
  782. "true" : "false");
  783. printf("reason_timestamp_flag = %s\n",
  784. params.match_flags.reason_timestamp_flag ? "true" : "false");
  785. printf("reason_user_flag = %s\n",
  786. params.match_flags.reason_user_flag ? "true" : "false");
  787. printf("reservation_flag = %s\n", params.reservation_flag ?
  788. "true" : "false");
  789. printf("root_flag = %s\n", params.match_flags.root_flag ?
  790. "true" : "false");
  791. printf("share_flag = %s\n", params.match_flags.share_flag ?
  792. "true" : "false");
  793. printf("state_flag = %s\n", params.match_flags.state_flag ?
  794. "true" : "false");
  795. printf("weight_flag = %s\n", params.match_flags.weight_flag ?
  796. "true" : "false");
  797. printf("-----------------------------\n\n");
  798. }
  799. static void _usage( void )
  800. {
  801. printf("\
  802. Usage: sinfo [-abdelNRrsTv] [-i seconds] [-t states] [-p partition] [-n nodes]\n\
  803. [-S fields] [-o format] \n");
  804. }
  805. static void _help( void )
  806. {
  807. printf ("\
  808. Usage: sinfo [OPTIONS]\n\
  809. -a, --all show all partitions (including hidden and those\n\
  810. not accessible)\n\
  811. -b, --bg show bgblocks (on Blue Gene systems)\n\
  812. -d, --dead show only non-responding nodes\n\
  813. -e, --exact group nodes only on exact match of configuration\n\
  814. -h, --noheader no headers on output\n\
  815. --hide do not show hidden or non-accessible partitions\n\
  816. -i, --iterate=seconds specify an iteration period\n\
  817. -l, --long long output - displays more information\n\
  818. -n, --nodes=NODES report on specific node(s)\n\
  819. -N, --Node Node-centric format\n\
  820. -o, --format=format format specification\n\
  821. -p, --partition=PARTITION report on specific partition\n\
  822. -r, --responding report only responding nodes\n\
  823. -R, --list-reasons list reason nodes are down or drained\n\
  824. -s, --summarize report state summary only\n\
  825. -S, --sort=fields comma separated list of fields to sort on\n\
  826. -t, --states=node_state specify the what states of nodes to view\n\
  827. -T, --reservation show only reservation information\n\
  828. -v, --verbose verbosity level\n\
  829. -V, --version output version information and exit\n\
  830. \nHelp options:\n\
  831. --help show this help message\n\
  832. --usage display brief usage message\n");
  833. }