-
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. Examples: mxqset group 123 --closed mxqset group 123 --open mxqset group 123 --blacklist "dontpanic" # replace mxqset group 123 --whitelist "+uselessbox +gula" # add mxqset group 123 --blacklist -dontpanic # remove mxqset group 123 --whitelist "" # clear 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 new options, which take a value.
Showing
1 changed file
with
245 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,245 @@ | ||
#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_blacklist(struct mx_mysql *mysql, long unsigned groupid, char *update_blacklist) { | ||
|
||
struct mx_mysql_stmt *stmt = NULL; | ||
unsigned long long num_rows; | ||
char *group_blacklist = NULL; | ||
struct keywordset *blacklist; | ||
|
||
if (strcmp(update_blacklist, "") !=0 ) { | ||
stmt = mx_mysql_statement_prepare(mysql, | ||
"SELECT group_blacklist 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_blacklist); | ||
if (mx_mysql_statement_fetch(stmt) < 0) | ||
die("%m\n"); | ||
mx_mysql_statement_close(&stmt); | ||
blacklist = keywordset_new(group_blacklist); | ||
free(group_blacklist); | ||
} else { | ||
blacklist = keywordset_new(NULL); | ||
} | ||
keywordset_update(blacklist, update_blacklist); | ||
|
||
group_blacklist = keywordset_get(blacklist); | ||
|
||
stmt = mx_mysql_statement_prepare(mysql, | ||
"UPDATE mxq_group SET group_blacklist = ? WHERE group_id = ?"); | ||
if (!stmt) | ||
die("%m\n"); | ||
mx_mysql_statement_param_bind(stmt, 0, string, &group_blacklist); | ||
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_blacklist); | ||
keywordset_free(blacklist); | ||
} | ||
|
||
static void update_whitelist(struct mx_mysql *mysql, long unsigned groupid, char *update_whitelist) { | ||
|
||
struct mx_mysql_stmt *stmt = NULL; | ||
unsigned long long num_rows; | ||
char *group_whitelist = NULL; | ||
struct keywordset *whitelist; | ||
|
||
if (strcmp(update_whitelist, "") !=0 ) { | ||
stmt = mx_mysql_statement_prepare(mysql, | ||
"SELECT group_whitelist 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_whitelist); | ||
if (mx_mysql_statement_fetch(stmt) < 0) | ||
die("%m\n"); | ||
mx_mysql_statement_close(&stmt); | ||
whitelist = keywordset_new(group_whitelist); | ||
free(group_whitelist); | ||
} else { | ||
whitelist = keywordset_new(NULL); | ||
} | ||
keywordset_update(whitelist, update_whitelist); | ||
|
||
group_whitelist = keywordset_get(whitelist); | ||
|
||
stmt = mx_mysql_statement_prepare(mysql, | ||
"UPDATE mxq_group SET group_whitelist = ? WHERE group_id = ?"); | ||
if (!stmt) | ||
die("%m\n"); | ||
mx_mysql_statement_param_bind(stmt, 0, string, &group_whitelist); | ||
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_whitelist); | ||
keywordset_free(whitelist); | ||
} | ||
|
||
struct opts { | ||
enum OPEN_CLOSED open_closed; | ||
char *update_blacklist; | ||
char *update_whitelist; | ||
}; | ||
|
||
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 13: | ||
opts->update_blacklist = arg; | ||
return 0; | ||
case 15: | ||
opts->update_whitelist = arg; | ||
return 0; | ||
} | ||
return ARGP_ERR_UNKNOWN; | ||
} | ||
|
||
static const struct argp_option options[] = { | ||
{"closed", 10, NULL, 0, NULL}, | ||
{"open", 11, NULL, 0, NULL}, | ||
{"blacklist", 13, "", 0, NULL}, | ||
{"whitelist", 15, "", 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" | ||
" --blacklist=STRING\n" | ||
" --whitelist=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.update_blacklist != NULL) | ||
update_blacklist(mysql, groupid, opts.update_blacklist); | ||
if ( opts.update_whitelist != NULL) | ||
update_whitelist(mysql, groupid, opts.update_whitelist); | ||
|
||
mx_mysql_finish(&mysql); | ||
} |