PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sshare/sshare.c

https://github.com/cfenoy/slurm
C | 429 lines | 348 code | 38 blank | 43 comment | 65 complexity | 53fec1fe630992f4d587c1ac46a18424 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * sshare.c - tool for listing the shares of association in
  3. * relationship to the cluster running on.
  4. *****************************************************************************
  5. * Copyright (C) 2008 Lawrence Livermore National Security.
  6. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  7. * Written by Danny Auble <da@llnl.gov>
  8. * CODE-OCEC-09-009. All rights reserved.
  9. *
  10. * This file is part of SLURM, a resource management program.
  11. * For details, see <http://www.schedmd.com/slurmdocs/>.
  12. * Please also read the included file: DISCLAIMER.
  13. *
  14. * SLURM is free software; you can redistribute it and/or modify it under
  15. * the terms of the GNU General Public License as published by the Free
  16. * Software Foundation; either version 2 of the License, or (at your option)
  17. * any later version.
  18. *
  19. * In addition, as a special exception, the copyright holders give permission
  20. * to link the code of portions of this program with the OpenSSL library under
  21. * certain conditions as described in each individual source file, and
  22. * distribute linked combinations including the two. You must obey the GNU
  23. * General Public License in all respects for all of the code used other than
  24. * OpenSSL. If you modify file(s) with this exception, you may extend this
  25. * exception to your version of the file(s), but you are not obligated to do
  26. * so. If you do not wish to do so, delete this exception statement from your
  27. * version. If you delete this exception statement from all source files in
  28. * the program, then also delete it here.
  29. *
  30. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  31. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  32. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  33. * details.
  34. *
  35. * You should have received a copy of the GNU General Public License along
  36. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  37. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  38. \*****************************************************************************/
  39. #include "src/sshare/sshare.h"
  40. #include "src/common/proc_args.h"
  41. #include <grp.h>
  42. #define BUFFER_SIZE 4096
  43. #define OPT_LONG_HELP 0x100
  44. #define OPT_LONG_USAGE 0x101
  45. int exit_code; /* sshare's exit code, =1 on any error at any time */
  46. int quiet_flag; /* quiet=1, verbose=-1, normal=0 */
  47. int long_flag; /* exceeds 80 character limit with more info */
  48. int verbosity; /* count of -v options */
  49. uint32_t my_uid = 0;
  50. List clusters = NULL;
  51. static int _get_info(shares_request_msg_t *shares_req,
  52. shares_response_msg_t **shares_resp);
  53. static int _addto_name_char_list(List char_list, char *names, bool gid);
  54. static char * _convert_to_name(int id, bool gid);
  55. static void _print_version( void );
  56. static void _usage ();
  57. int
  58. main (int argc, char *argv[])
  59. {
  60. int error_code = SLURM_SUCCESS, opt_char;
  61. log_options_t opts = LOG_OPTS_STDERR_ONLY;
  62. shares_request_msg_t req_msg;
  63. shares_response_msg_t *resp_msg = NULL;
  64. char *temp = NULL;
  65. int option_index;
  66. bool all_users = 0;
  67. static struct option long_options[] = {
  68. {"accounts", 1, 0, 'A'},
  69. {"all", 0, 0, 'a'},
  70. {"long", 0, 0, 'l'},
  71. {"cluster", 1, 0, 'M'},
  72. {"clusters", 1, 0, 'M'},
  73. {"noheader", 0, 0, 'h'},
  74. {"parsable", 0, 0, 'p'},
  75. {"parsable2",0, 0, 'P'},
  76. {"users", 1, 0, 'u'},
  77. {"verbose", 0, 0, 'v'},
  78. {"version", 0, 0, 'V'},
  79. {"help", 0, 0, OPT_LONG_HELP},
  80. {"usage", 0, 0, OPT_LONG_USAGE},
  81. {NULL, 0, 0, 0}
  82. };
  83. exit_code = 0;
  84. long_flag = 0;
  85. quiet_flag = 0;
  86. verbosity = 0;
  87. memset(&req_msg, 0, sizeof(shares_request_msg_t));
  88. log_init("sshare", opts, SYSLOG_FACILITY_DAEMON, NULL);
  89. while((opt_char = getopt_long(argc, argv, "aA:hlM:npPqu:t:vV",
  90. long_options, &option_index)) != -1) {
  91. switch (opt_char) {
  92. case (int)'?':
  93. fprintf(stderr, "Try \"sshare --help\" "
  94. "for more information\n");
  95. exit(1);
  96. break;
  97. case 'a':
  98. all_users = 1;
  99. break;
  100. case 'A':
  101. if(!req_msg.acct_list)
  102. req_msg.acct_list =
  103. list_create(slurm_destroy_char);
  104. slurm_addto_char_list(req_msg.acct_list, optarg);
  105. break;
  106. case 'h':
  107. print_fields_have_header = 0;
  108. break;
  109. exit(exit_code);
  110. break;
  111. case 'l':
  112. long_flag = 1;
  113. break;
  114. case 'M':
  115. if(clusters)
  116. list_destroy(clusters);
  117. if(!(clusters =
  118. slurmdb_get_info_cluster(optarg))) {
  119. error("'%s' can't be reached now, "
  120. "or it is an invalid entry for "
  121. "--cluster. Use 'sacctmgr --list "
  122. "cluster' to see available clusters.",
  123. optarg);
  124. exit(1);
  125. }
  126. working_cluster_rec = list_peek(clusters);
  127. break;
  128. case 'n':
  129. print_fields_have_header = 0;
  130. break;
  131. case 'p':
  132. print_fields_parsable_print =
  133. PRINT_FIELDS_PARSABLE_ENDING;
  134. break;
  135. case 'P':
  136. print_fields_parsable_print =
  137. PRINT_FIELDS_PARSABLE_NO_ENDING;
  138. break;
  139. case 'u':
  140. if(!strcmp(optarg, "-1")) {
  141. all_users = 1;
  142. break;
  143. }
  144. all_users = 0;
  145. if(!req_msg.user_list)
  146. req_msg.user_list =
  147. list_create(slurm_destroy_char);
  148. _addto_name_char_list(req_msg.user_list, optarg, 0);
  149. break;
  150. case 'v':
  151. quiet_flag = -1;
  152. verbosity++;
  153. break;
  154. case 'V':
  155. _print_version();
  156. exit(exit_code);
  157. break;
  158. case OPT_LONG_HELP:
  159. case OPT_LONG_USAGE:
  160. _usage();
  161. exit(0);
  162. default:
  163. exit_code = 1;
  164. fprintf(stderr, "getopt error, returned %c\n",
  165. opt_char);
  166. exit(exit_code);
  167. }
  168. }
  169. if (verbosity) {
  170. opts.stderr_level += verbosity;
  171. opts.prefix_level = 1;
  172. log_alter(opts, 0, NULL);
  173. }
  174. if(all_users) {
  175. if(req_msg.user_list
  176. && list_count(req_msg.user_list)) {
  177. list_destroy(req_msg.user_list);
  178. req_msg.user_list = NULL;
  179. }
  180. if(verbosity)
  181. fprintf(stderr, "Users requested:\n\t: all\n");
  182. } else if (verbosity && req_msg.user_list
  183. && list_count(req_msg.user_list)) {
  184. fprintf(stderr, "Users requested:\n");
  185. ListIterator itr = list_iterator_create(req_msg.user_list);
  186. while((temp = list_next(itr)))
  187. fprintf(stderr, "\t: %s\n", temp);
  188. list_iterator_destroy(itr);
  189. } else if(!req_msg.user_list || !list_count(req_msg.user_list)) {
  190. struct passwd *pwd = getpwuid(getuid());
  191. if(!req_msg.user_list)
  192. req_msg.user_list = list_create(slurm_destroy_char);
  193. temp = xstrdup(pwd->pw_name);
  194. list_append(req_msg.user_list, temp);
  195. if(verbosity) {
  196. fprintf(stderr, "Users requested:\n");
  197. fprintf(stderr, "\t: %s\n", temp);
  198. }
  199. }
  200. if(req_msg.acct_list && list_count(req_msg.acct_list)) {
  201. fprintf(stderr, "Accounts requested:\n");
  202. ListIterator itr = list_iterator_create(req_msg.acct_list);
  203. while((temp = list_next(itr)))
  204. fprintf(stderr, "\t: %s\n", temp);
  205. list_iterator_destroy(itr);
  206. } else {
  207. if(req_msg.acct_list
  208. && list_count(req_msg.acct_list)) {
  209. list_destroy(req_msg.acct_list);
  210. req_msg.acct_list = NULL;
  211. }
  212. if(verbosity)
  213. fprintf(stderr, "Accounts requested:\n\t: all\n");
  214. }
  215. error_code = _get_info(&req_msg, &resp_msg);
  216. if(req_msg.acct_list)
  217. list_destroy(req_msg.acct_list);
  218. if(req_msg.user_list)
  219. list_destroy(req_msg.user_list);
  220. if (error_code) {
  221. slurm_perror("Couldn't get shares from controller");
  222. exit(error_code);
  223. }
  224. /* do stuff with it */
  225. process(resp_msg);
  226. slurm_free_shares_response_msg(resp_msg);
  227. exit(exit_code);
  228. }
  229. static int _get_info(shares_request_msg_t *shares_req,
  230. shares_response_msg_t **shares_resp)
  231. {
  232. int rc;
  233. slurm_msg_t req_msg;
  234. slurm_msg_t resp_msg;
  235. slurm_msg_t_init(&req_msg);
  236. slurm_msg_t_init(&resp_msg);
  237. req_msg.msg_type = REQUEST_SHARE_INFO;
  238. req_msg.data = shares_req;
  239. if (slurm_send_recv_controller_msg(&req_msg, &resp_msg) < 0)
  240. return SLURM_ERROR;
  241. switch (resp_msg.msg_type) {
  242. case RESPONSE_SHARE_INFO:
  243. *shares_resp = (shares_response_msg_t *) resp_msg.data;
  244. break;
  245. case RESPONSE_SLURM_RC:
  246. rc = ((return_code_msg_t *) resp_msg.data)->return_code;
  247. slurm_free_return_code_msg(resp_msg.data);
  248. if (rc)
  249. slurm_seterrno_ret(rc);
  250. *shares_resp = NULL;
  251. break;
  252. default:
  253. slurm_seterrno_ret(SLURM_UNEXPECTED_MSG_ERROR);
  254. break;
  255. }
  256. return SLURM_PROTOCOL_SUCCESS;
  257. }
  258. /* returns number of objects added to list */
  259. static int _addto_name_char_list(List char_list, char *names, bool gid)
  260. {
  261. int i=0, start=0;
  262. char *name = NULL, *tmp_char = NULL;
  263. ListIterator itr = NULL;
  264. char quote_c = '\0';
  265. int quote = 0;
  266. int count = 0;
  267. if(!char_list) {
  268. error("No list was given to fill in");
  269. return 0;
  270. }
  271. itr = list_iterator_create(char_list);
  272. if(names) {
  273. if (names[i] == '\"' || names[i] == '\'') {
  274. quote_c = names[i];
  275. quote = 1;
  276. i++;
  277. }
  278. start = i;
  279. while(names[i]) {
  280. //info("got %d - %d = %d", i, start, i-start);
  281. if(quote && names[i] == quote_c)
  282. break;
  283. else if (names[i] == '\"' || names[i] == '\'')
  284. names[i] = '`';
  285. else if(names[i] == ',') {
  286. if((i-start) > 0) {
  287. name = xmalloc((i-start+1));
  288. memcpy(name, names+start, (i-start));
  289. //info("got %s %d", name, i-start);
  290. if (isdigit((int) *name)) {
  291. int id = atoi(name);
  292. xfree(name);
  293. name = _convert_to_name(
  294. id, gid);
  295. }
  296. while((tmp_char = list_next(itr))) {
  297. if(!strcasecmp(tmp_char, name))
  298. break;
  299. }
  300. if(!tmp_char) {
  301. list_append(char_list, name);
  302. count++;
  303. } else
  304. xfree(name);
  305. list_iterator_reset(itr);
  306. }
  307. i++;
  308. start = i;
  309. if(!names[i]) {
  310. info("There is a problem with "
  311. "your request. It appears you "
  312. "have spaces inside your list.");
  313. break;
  314. }
  315. }
  316. i++;
  317. }
  318. if((i-start) > 0) {
  319. name = xmalloc((i-start)+1);
  320. memcpy(name, names+start, (i-start));
  321. if (isdigit((int) *name)) {
  322. int id = atoi(name);
  323. xfree(name);
  324. name = _convert_to_name(id, gid);
  325. }
  326. while((tmp_char = list_next(itr))) {
  327. if(!strcasecmp(tmp_char, name))
  328. break;
  329. }
  330. if(!tmp_char) {
  331. list_append(char_list, name);
  332. count++;
  333. } else
  334. xfree(name);
  335. }
  336. }
  337. list_iterator_destroy(itr);
  338. return count;
  339. }
  340. static char *_convert_to_name(int id, bool gid)
  341. {
  342. char *name = NULL;
  343. if(gid) {
  344. struct group *grp;
  345. if (!(grp=getgrgid(id))) {
  346. fprintf(stderr, "Invalid group id: %s\n", name);
  347. exit(1);
  348. }
  349. name = xstrdup(grp->gr_name);
  350. } else {
  351. struct passwd *pwd;
  352. if (!(pwd=getpwuid(id))) {
  353. fprintf(stderr, "Invalid user id: %s\n", name);
  354. exit(1);
  355. }
  356. name = xstrdup(pwd->pw_name);
  357. }
  358. return name;
  359. }
  360. static void _print_version(void)
  361. {
  362. print_slurm_version();
  363. if (quiet_flag == -1) {
  364. long version = slurm_api_version();
  365. printf("slurm_api_version: %ld, %ld.%ld.%ld\n", version,
  366. SLURM_VERSION_MAJOR(version),
  367. SLURM_VERSION_MINOR(version),
  368. SLURM_VERSION_MICRO(version));
  369. }
  370. }
  371. /* _usage - show the valid sshare options */
  372. void _usage () {
  373. printf ("\
  374. Usage: sshare [OPTION] \n\
  375. Valid OPTIONs are: \n\
  376. -a or --all list all users \n\
  377. -A or --accounts= display specific accounts (comma separated list)\n\
  378. -h or --noheader omit header from output \n\
  379. -M or --cluster=name cluster to issue commands to. Default is \n\
  380. current cluster. cluster with no name will \n\
  381. reset to default. \n\
  382. -l or --long include normalized usage in output \n\
  383. -p or --parsable '|' delimited output with a trailing '|' \n\
  384. -P or --parsable2 '|' delimited output without a trailing '|' \n\
  385. -u or --users= display specific users (comma separated list) \n\
  386. -v or --verbose display more information \n\
  387. -V or --version display tool version number \n\
  388. --help display this usage description \n\
  389. --usage display this usage description \n\
  390. \n\n");
  391. }