Skip to content

Commit

Permalink
Add command "mxqset"
Browse files Browse the repository at this point in the history
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
donald committed Apr 13, 2020
1 parent 6912c0d commit 0a70658
Showing 1 changed file with 200 additions and 0 deletions.
200 changes: 200 additions & 0 deletions mxqset.c
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);
}

0 comments on commit 0a70658

Please sign in to comment.