-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a new command which can be used to modify an existing group: mxqset group 123 --closed mxqset group 123 --open mxqset group 123 --disabled-servers=dontpanic mxqset group 123 --update-disabled-servers="sigusr sigusr2 -dontpanic" mxqset group 123 --disabled-servers= The flags open and closed can be set from mxqadmin as well (`mxqadmin --close=123`) , but the synopsis, in which the options take the groupid as a value is difficult to expand to options, which take a value by themself.
- Loading branch information
Showing
1 changed file
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
#define _GNU_SOURCE | ||
#include <argp.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <assert.h> | ||
#include <sysexits.h> | ||
#include "mx_mysql.h" | ||
#include "mxq.h" | ||
#include "mxq_group.h" | ||
#include "keywordset.h" | ||
#include "stdarg.h" | ||
|
||
static __attribute__ ((noreturn)) void die(char *msg, ...) { | ||
va_list ap; | ||
|
||
va_start(ap, msg); | ||
fprintf(stderr, "%s: ",program_invocation_short_name); | ||
vfprintf(stderr, msg, ap); | ||
va_end(ap); | ||
exit(1); | ||
} | ||
|
||
static void verify_group_permission(struct mx_mysql *mysql , long unsigned groupid, uid_t client_uid) { | ||
struct mx_mysql_stmt *stmt = NULL; | ||
unsigned long long num_rows; | ||
unsigned uid; | ||
|
||
stmt = mx_mysql_statement_prepare(mysql,"SELECT user_uid FROM mxq_group WHERE group_id = ? LIMIT 1"); | ||
if (!stmt) | ||
die("%m\n"); | ||
mx_mysql_statement_param_bind(stmt, 0, uint64, &(groupid)); | ||
if (mx_mysql_statement_execute(stmt, &num_rows) < 0) | ||
die("%m\n"); | ||
if (num_rows < 1) | ||
die("no such group %ld\n", groupid); | ||
mx_mysql_statement_result_bind(stmt, 0, uint32, &uid); | ||
if (mx_mysql_statement_fetch(stmt) < 0) | ||
die("%m\n"); | ||
if ( client_uid != 0 && client_uid != uid ) | ||
die("no permission to access this group\n"); | ||
mx_mysql_statement_close(&stmt); | ||
} | ||
|
||
enum OPEN_CLOSED { | ||
OPEN_CLOSED_UNSET = 0, | ||
OPEN_CLOSED_CLOSED, | ||
OPEN_CLOSED_OPEN, | ||
}; | ||
|
||
static void update_closed_flag(struct mx_mysql *mysql, long unsigned groupid, enum OPEN_CLOSED open_closed) { | ||
|
||
struct mx_mysql_stmt *stmt = NULL; | ||
unsigned long long num_rows; | ||
|
||
uint64_t mask = ~MXQ_GROUP_FLAG_CLOSED; | ||
uint64_t value = open_closed == OPEN_CLOSED_CLOSED ? MXQ_GROUP_FLAG_CLOSED : 0; | ||
|
||
stmt = mx_mysql_statement_prepare(mysql, | ||
"UPDATE mxq_group SET group_flags = ( group_flags & ?) | ? WHERE group_id = ?"); | ||
if (!stmt) | ||
die("%m\n"); | ||
mx_mysql_statement_param_bind(stmt, 0, uint64, &(mask)); | ||
mx_mysql_statement_param_bind(stmt, 1, uint64, &(value)); | ||
mx_mysql_statement_param_bind(stmt, 2, uint64, &(groupid)); | ||
if (mx_mysql_statement_execute(stmt, &num_rows) < 0) | ||
die("%m\n"); | ||
if (num_rows < 1) | ||
die("no such group %ld\n", groupid); | ||
mx_mysql_statement_close(&stmt); | ||
} | ||
|
||
static void update_disabled_server(struct mx_mysql *mysql, long unsigned groupid, char *set_disabled_server, char *update_disabled_server) { | ||
|
||
struct mx_mysql_stmt *stmt = NULL; | ||
unsigned long long num_rows; | ||
char *group_disabled_servers = NULL; | ||
struct keywordset *disabled_server; | ||
|
||
if (set_disabled_server) | ||
disabled_server = keywordset_new(set_disabled_server); | ||
else { | ||
stmt = mx_mysql_statement_prepare(mysql, | ||
"SELECT group_disabled_servers FROM mxq_group WHERE group_id = ? LIMIT 1"); | ||
if (!stmt) | ||
die("%m\n"); | ||
mx_mysql_statement_param_bind(stmt, 0, uint64, &groupid); | ||
if (mx_mysql_statement_execute(stmt, &num_rows) < 0) | ||
die("%m\n"); | ||
if (num_rows < 1) | ||
die("no such group %ld\n", groupid); | ||
mx_mysql_statement_result_bind(stmt, 0, string, &group_disabled_servers); | ||
if (mx_mysql_statement_fetch(stmt) < 0) | ||
die("%m\n"); | ||
mx_mysql_statement_close(&stmt); | ||
disabled_server = keywordset_new(group_disabled_servers); | ||
free(group_disabled_servers); | ||
} | ||
|
||
if (update_disabled_server != NULL) | ||
keywordset_update(disabled_server, update_disabled_server); | ||
|
||
group_disabled_servers = keywordset_get(disabled_server); | ||
|
||
stmt = mx_mysql_statement_prepare(mysql, | ||
"UPDATE mxq_group SET group_disabled_servers = ? WHERE group_id = ?"); | ||
if (!stmt) | ||
die("%m\n"); | ||
mx_mysql_statement_param_bind(stmt, 0, string, &group_disabled_servers); | ||
mx_mysql_statement_param_bind(stmt, 1, uint64, &groupid); | ||
if (mx_mysql_statement_execute(stmt, &num_rows) < 0) | ||
die("%m\n"); | ||
if (num_rows < 1) | ||
die("no such group %ld\n", groupid); | ||
mx_mysql_statement_close(&stmt); | ||
free(group_disabled_servers); | ||
keywordset_free(disabled_server); | ||
} | ||
|
||
struct opts { | ||
enum OPEN_CLOSED open_closed; | ||
char *set_disabled_server; | ||
char *update_disabled_server; | ||
}; | ||
|
||
static error_t parser (int key, char *arg, struct argp_state *state) { | ||
struct opts *opts = state->input; | ||
switch (key) { | ||
case 10: | ||
opts->open_closed = OPEN_CLOSED_CLOSED; | ||
return 0; | ||
case 11: | ||
opts->open_closed = OPEN_CLOSED_OPEN; | ||
return 0; | ||
case 12: | ||
opts->set_disabled_server = arg; | ||
return 0; | ||
case 13: | ||
opts->update_disabled_server = arg; | ||
return 0; | ||
} | ||
return ARGP_ERR_UNKNOWN; | ||
} | ||
|
||
static const struct argp_option options[] = { | ||
{"closed", 10, NULL, 0, NULL}, | ||
{"open", 11, NULL, 0, NULL}, | ||
{"disabled-servers", 12, "", 0, NULL}, | ||
{"update-disabled-servers", 13, "", 0, NULL}, | ||
{0} | ||
}; | ||
|
||
static const struct argp argp = { options, parser, NULL, NULL }; | ||
|
||
static __attribute__ ((noreturn)) void exit_usage(char *argv0) { | ||
fprintf(stderr, | ||
"usage: %s group GID [group-options]\n" | ||
"\n" | ||
"group options:\n" | ||
"\n" | ||
" --open\n" | ||
" --closed\n" | ||
" --disabled-servers=STRING\n" | ||
" --update-disabled-servers=STRING\n" | ||
,program_invocation_short_name); | ||
exit(EX_USAGE); | ||
} | ||
|
||
int main(int argc, char **argv) { | ||
|
||
char *argv0=argv[0]; | ||
struct mx_mysql *mysql = NULL; | ||
int groupid; | ||
uid_t uid = getuid(); | ||
|
||
if (argc<3 || strcmp(argv[1],"group") != 0) | ||
exit_usage(argv0); | ||
groupid=atoi(argv[2]); | ||
|
||
int sts; | ||
struct opts opts={0}; | ||
|
||
sts=argp_parse (&argp, argc-3, &argv[3], ARGP_PARSE_ARGV0|ARGP_SILENT, NULL, &opts); | ||
if (sts) | ||
exit_usage(argv0); | ||
|
||
assert(mx_mysql_initialize(&mysql) == 0); | ||
mx_mysql_option_set_default_file(mysql, MXQ_MYSQL_DEFAULT_FILE); | ||
mx_mysql_option_set_default_group(mysql, MXQ_MYSQL_DEFAULT_GROUP); | ||
assert(mx_mysql_connect_forever(&mysql) == 0); | ||
|
||
verify_group_permission(mysql, groupid, uid); | ||
|
||
if ( opts.open_closed != OPEN_CLOSED_UNSET) | ||
update_closed_flag(mysql, groupid, opts.open_closed); | ||
if ( opts.set_disabled_server != NULL || opts.update_disabled_server != NULL) | ||
update_disabled_server(mysql, groupid, opts.set_disabled_server, opts.update_disabled_server); | ||
|
||
mx_mysql_finish(&mysql); | ||
} |