Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
mxq
Public
Notifications
You must be signed in to change notification settings
Fork
3
Star
3
Code
Issues
20
Pull requests
3
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
9aee649
helper
manpages
mysql
web
.gitignore
.vimrc
Doxyfile
LICENSE
Makefile
README.md
keywordset.c
keywordset.h
mx_flock.c
mx_flock.h
mx_getopt.c
mx_getopt.h
mx_log.c
mx_log.h
mx_mysql.c
mx_mysql.h
mx_proc.c
mx_proc.h
mx_util.c
mx_util.h
mxq.h
mxq_daemon.c
mxq_daemon.h
mxq_group.c
mxq_group.h
mxq_job.c
mxq_job.h
mxq_log.c
mxq_reaper.c
mxqadmin.c
mxqd.c
mxqd.h
mxqd_control.c
mxqd_control.h
mxqdctl-hostconfig.sh
mxqdump.c
mxqkill.c
mxqps.c
mxqset.c
mxqsub.c
os-release
parser.y
ppidcache.c
ppidcache.h
test_keywordset.c
test_mx_log.c
test_mx_mysql.c
test_mx_util.c
test_mxqd_control.c
test_parser.c
xmalloc.h
Breadcrumbs
mxq
/
mxqadmin.c
Blame
Blame
Latest commit
History
History
399 lines (314 loc) · 10.7 KB
Breadcrumbs
mxq
/
mxqadmin.c
Top
File metadata and controls
Code
Blame
399 lines (314 loc) · 10.7 KB
Raw
#define _GNU_SOURCE #include <stdio.h> #include <stdint.h> #include <errno.h> #include <assert.h> #include <unistd.h> #include <sys/types.h> #include <pwd.h> #include <assert.h> #include <sysexits.h> #include <ctype.h> #include <mysql.h> #include <string.h> #include "mx_log.h" #include "mx_util.h" #include "mx_mysql.h" #include "mx_getopt.h" #include "mxq_group.h" #include "mxq_job.h" #include "mxq.h" #define UINT64_UNSET (uint64_t)(-1) #define UINT64_ALL (uint64_t)(-2) #define UINT64_SPECIAL_MIN (uint64_t)(-2) #define UINT64_HASVALUE(x) ((x) < UINT64_SPECIAL_MIN) enum mode { MODE_UNSET=0, MODE_CLOSE, MODE_REOPEN }; static void print_usage(void) { mxq_print_generic_version(); printf( "\n" "Usage:\n" " %s [options]\n" "\n" "options:\n" "\n" " -c, --close=GROUPID close group <GROUPID>\n" " -o, --reopen=GROUPID reopen group <GROUPID>\n" "\n" " -v, --verbose be more verbose\n" " --debug set debug log level (default: warning log level)\n" "\n" " -V, --version\n" " -h, --help\n" "\n" "Change how to connect to the mysql server:\n" "\n" " -M, --mysql-default-file[=MYSQLCNF] (default: %s)\n" " -S, --mysql-default-group[=MYSQLGROUP] (default: %s)\n" "\n" "Environment:\n" " MXQ_MYSQL_DEFAULT_FILE change default for MYSQLCNF\n" " MXQ_MYSQL_DEFAULT_GROUP change default for MYSQLGROUP\n" "\n", program_invocation_short_name, MXQ_MYSQL_DEFAULT_FILE_STR, MXQ_MYSQL_DEFAULT_GROUP_STR ); } static int update_group_flags_closed(struct mx_mysql *mysql, uint64_t group_id, uint32_t user_uid) { struct mx_mysql_stmt *stmt = NULL; unsigned long long num_rows = 0; int res; uint64_t newflags = 0; newflags |= MXQ_GROUP_FLAG_CLOSED; stmt = mx_mysql_statement_prepare(mysql, "UPDATE mxq_group SET" " group_flags = group_flags | ?" " WHERE group_id = ?" " AND user_uid = ?" ); if (!stmt) { mx_log_err("mx_mysql_statement_prepare(): %s", mx_mysql_error()); return -(errno=EIO); } mx_mysql_statement_param_bind(stmt, 0, uint64, &(newflags)); mx_mysql_statement_param_bind(stmt, 1, uint64, &(group_id)); mx_mysql_statement_param_bind(stmt, 2, uint32, &(user_uid)); res = mx_mysql_statement_execute(stmt, &num_rows); if (res < 0) mx_log_err("mx_mysql_statement_execute(): %s", mx_mysql_error()); mx_mysql_statement_close(&stmt); if (res < 0) return -(errno=-res); assert(num_rows <= 1); return (int)num_rows; } static int update_group_flags_reopen(struct mx_mysql *mysql, uint64_t group_id, uint32_t user_uid) { struct mx_mysql_stmt *stmt = NULL; unsigned long long num_rows = 0; int res; uint64_t newflags = 0; newflags |= MXQ_GROUP_FLAG_CLOSED; stmt = mx_mysql_statement_prepare(mysql, "UPDATE mxq_group SET" " group_flags = group_flags & ~(?)" " WHERE group_id = ?" " AND user_uid = ?" ); if (!stmt) { mx_log_err("mx_mysql_statement_prepare(): %s", mx_mysql_error()); return -(errno=EIO); } mx_mysql_statement_param_bind(stmt, 0, uint64, &(newflags)); mx_mysql_statement_param_bind(stmt, 1, uint64, &(group_id)); mx_mysql_statement_param_bind(stmt, 2, uint32, &(user_uid)); res = mx_mysql_statement_execute(stmt, &num_rows); if (res < 0) mx_log_err("mx_mysql_statement_execute(): %s", mx_mysql_error()); mx_mysql_statement_close(&stmt); if (res < 0) return -(errno=-res); assert(num_rows <= 1); return (int)num_rows; } int _close_group_for_user(struct mx_mysql *mysql, uint64_t group_id, uint64_t user_uid) { int res; res = update_group_flags_closed(mysql, group_id, user_uid); if (res == 0) { mx_log_warning("no group with group_id=%lu found for user with uid=%lu", group_id, user_uid); return -(errno=ENOENT); } if (res < 0) { mx_log_err("closing group failed"); return res; } assert(res == 1); mx_log_notice("closing group %lu succeeded.", group_id); return 0; } int _reopen_group_for_user(struct mx_mysql *mysql, uint64_t group_id, uint64_t user_uid) { int res; res = update_group_flags_reopen(mysql, group_id, user_uid); if (res == 0) { mx_log_warning("no group with group_id=%lu found for user with uid=%lu", group_id, user_uid); return -(errno=ENOENT); } if (res < 0) { mx_log_err("opening group failed"); return res; } assert(res == 1); mx_log_notice("opening group %lu succeeded.", group_id); return 0; } int main(int argc, char *argv[]) { struct mx_mysql *mysql = NULL; uid_t ruid, euid, suid; struct passwd *passwd = NULL; int res; uint64_t arg_group_id; char arg_debug; uint64_t arg_uid; enum mode arg_mode; char *arg_mysql_default_group; char *arg_mysql_default_file; int i; int opt; struct mx_getopt_ctl optctl; struct mx_option opts[] = { MX_OPTION_NO_ARG("help", 'h'), MX_OPTION_NO_ARG("version", 'V'), MX_OPTION_NO_ARG("debug", 5), MX_OPTION_NO_ARG("verbose", 'v'), MX_OPTION_REQUIRED_ARG("user", 'u'), MX_OPTION_REQUIRED_ARG("close", 'c'), MX_OPTION_REQUIRED_ARG("reopen", 'o'), MX_OPTION_OPTIONAL_ARG("mysql-default-file", 'M'), MX_OPTION_OPTIONAL_ARG("mysql-default-group", 'S'), MX_OPTION_END }; arg_mysql_default_group = getenv("MXQ_MYSQL_DEFAULT_GROUP"); if (!arg_mysql_default_group) arg_mysql_default_group = MXQ_MYSQL_DEFAULT_GROUP; arg_mysql_default_file = getenv("MXQ_MYSQL_DEFAULT_FILE"); if (!arg_mysql_default_file) arg_mysql_default_file = MXQ_MYSQL_DEFAULT_FILE; arg_group_id = 0; arg_debug = 0; arg_mode = MODE_UNSET; arg_uid = UINT64_UNSET; mx_log_level_set(MX_LOG_NOTICE); res = getresuid(&ruid, &euid, &suid); assert(res != -1); mx_getopt_init(&optctl, argc-1, &argv[1], opts); optctl.flags = MX_FLAG_STOPONNOOPT; while ((opt=mx_getopt(&optctl, &i)) != MX_GETOPT_END) { if (opt == MX_GETOPT_ERROR) { exit(EX_USAGE); } switch (opt) { case 'V': mxq_print_generic_version(); exit(EX_USAGE); case 'h': print_usage(); exit(EX_USAGE); case 5: arg_debug = 1; mx_log_level_set(MX_LOG_DEBUG); break; case 'v': if (!arg_debug) mx_log_level_set(MX_LOG_INFO); break; case 'M': arg_mysql_default_file = optctl.optarg; break; case 'S': arg_mysql_default_group = optctl.optarg; break; case 'u': passwd = getpwnam(optctl.optarg); if (passwd) { arg_uid = passwd->pw_uid; break; } mx_log_debug("user %s not found. trying numeric uid.", optctl.optarg); if (!isdigit(*optctl.optarg)) { mx_log_err("Invalid argument for --user '%s': User not found.", optctl.optarg); exit(EX_USAGE); } if (mx_strtou64(optctl.optarg, &arg_uid) < 0 || arg_uid >= UINT64_SPECIAL_MIN) { if (arg_uid >= UINT64_SPECIAL_MIN) errno = ERANGE; mx_log_err("Invalid argument for --user '%s': %m", optctl.optarg); exit(EX_USAGE); } errno = 0; passwd = getpwuid(arg_uid); if (!passwd) { if (errno) mx_log_err("Can't load user with uid '%lu': %m", arg_uid); else mx_log_err("Invalid argument for --user '%s': User not found.", optctl.optarg); exit(EX_USAGE); } break; case 'c': if (mx_strtou64(optctl.optarg, &arg_group_id) < 0 || !arg_group_id) { if (!arg_group_id) errno = ERANGE; mx_log_err("Invalid argument for --close '%s': %m", optctl.optarg); exit(EX_CONFIG); } arg_mode = MODE_CLOSE; break; case 'o': if (mx_strtou64(optctl.optarg, &arg_group_id) < 0 || !arg_group_id) { if (!arg_group_id) errno = ERANGE; mx_log_err("Invalid argument for --reopen '%s': %m", optctl.optarg); exit(EX_CONFIG); } arg_mode = MODE_REOPEN; break; } } MX_GETOPT_FINISH(optctl, argc, argv); if (!arg_group_id) { print_usage(); exit(EX_USAGE); } if (arg_uid == UINT64_UNSET) arg_uid = ruid; if (arg_uid != ruid && ruid != 0) { mx_log_err("Nice try, but only root user may kill jobs of other users! Better luck next time."); exit(EX_USAGE); } if (!passwd) { errno = 0; passwd = getpwuid(arg_uid); if (!passwd && errno) { mx_log_err("Can't load user with uid '%lu': %m", arg_uid); exit(EX_IOERR); } if (!passwd) { assert(arg_uid == ruid); mx_log_err("Can't load current user with uid '%lu'.", arg_uid); exit(EX_NOUSER); } } res = mx_mysql_initialize(&mysql); assert(res == 0); mx_mysql_option_set_default_file(mysql, arg_mysql_default_file); mx_mysql_option_set_default_group(mysql, arg_mysql_default_group); res = mx_mysql_connect_forever(&mysql); assert(res == 0); mx_log_info("MySQL: Connection to database established."); if (arg_mode == MODE_CLOSE) { res = _close_group_for_user(mysql, arg_group_id, arg_uid); mx_mysql_finish(&mysql); mx_log_info("MySQL: Connection to database closed."); return (res < 0); } else if (arg_mode == MODE_REOPEN) { res = _reopen_group_for_user(mysql, arg_group_id, arg_uid); mx_mysql_finish(&mysql); mx_log_info("MySQL: Connection to database closed."); return (res < 0); } mx_mysql_finish(&mysql); mx_log_info("MySQL: Connection to database closed."); return 1; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
You can’t perform that action at this time.