Initial mysql-admtools import
This commit is contained in:
427
mysql-dbadm.c
Normal file
427
mysql-dbadm.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* @(#) $Header: /home/nalle/cvsroot/mysql-admutils/mysql-dbadm.c,v 1.3 1998/07/06 12:33:07 ljosa Exp $
|
||||
*
|
||||
* mysql-dbadm.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mysql.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include "mysql-admutils.h"
|
||||
|
||||
char *
|
||||
strchr_whitespace(const char *s)
|
||||
{
|
||||
char *sp, *tab;
|
||||
sp = strchr(s, ' ');
|
||||
tab = strchr(s, '\t');
|
||||
if (sp == NULL)
|
||||
return tab;
|
||||
if (tab == NULL)
|
||||
return sp;
|
||||
return sp < tab ? sp : tab; /* if both are found, return the first one */
|
||||
}
|
||||
|
||||
char *
|
||||
strtok_whitespace(char *s)
|
||||
{
|
||||
static char *cp;
|
||||
char *r;
|
||||
|
||||
r = s ? s : cp;
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
cp = strchr_whitespace(r);
|
||||
if (cp == NULL)
|
||||
return r;
|
||||
while ((*cp == ' ') || (*cp == '\t'))
|
||||
{
|
||||
*cp++ = '\0';
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
valid_priv(const char *s)
|
||||
{
|
||||
#define ACCEPT(x) if (strcmp(s, x) == 0) return 1
|
||||
ACCEPT("Y");
|
||||
ACCEPT("N");
|
||||
ACCEPT("y");
|
||||
ACCEPT("n");
|
||||
#undef ACCEPT
|
||||
return 0; /* not a valid priv */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
usage()
|
||||
{
|
||||
printf("Usage: %s COMMAND [DATABASE]...\n", program_name);
|
||||
printf("Create, drop og edit permission for the DATABASE(s),\n");
|
||||
printf("as determined by the COMMAND. Valid COMMANDs:\n");
|
||||
printf("\n");
|
||||
printf(" create create the DATABASE(s).\n");
|
||||
printf(" drop delete the DATABASE(s).\n");
|
||||
printf(" show give information about the DATABASE(s), or, if\n");
|
||||
printf(" none are given, all the ones you own.\n");
|
||||
printf(" editperm change permissions for the DATABASE(s). Your\n");
|
||||
printf(" favorite editor will be started, allowing you\n");
|
||||
printf(" to make changes to the permission table.\n");
|
||||
printf("\n");
|
||||
printf("Report bugs to ljosa@initio.no\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
create(MYSQL *pmysql, char *db)
|
||||
{
|
||||
char query[1024];
|
||||
sprintf(query, "create database `%s`", db);
|
||||
if (mysql_query(pmysql, query))
|
||||
return dberror(pmysql, "Cannot create database '%s'.", db);
|
||||
|
||||
fprintf(stderr, "Database '%s' created.\n", db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
drop(MYSQL *pmysql, char *db)
|
||||
{
|
||||
char query[1024];
|
||||
|
||||
sprintf(query, "delete from db where db = '%s'", db);
|
||||
if (mysql_query(pmysql, query))
|
||||
dberror(pmysql, "Failed to delete permissions for database '%s'.", db);
|
||||
|
||||
sprintf(query, "drop database `%s`", db);
|
||||
if (mysql_query(pmysql, query))
|
||||
return dberror(pmysql, "Cannot drop database '%s'.", db);
|
||||
|
||||
fprintf(stderr, "Database '%s' dropped.\n", db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* return a list of the user's databases */
|
||||
char **
|
||||
list(MYSQL *pmysql)
|
||||
{
|
||||
char *wild;
|
||||
MYSQL_RES *res;
|
||||
int rows;
|
||||
MYSQL_ROW row;
|
||||
char **dblist;
|
||||
int i;
|
||||
char **t;
|
||||
struct passwd *p;
|
||||
|
||||
p = getpwuid(getuid());
|
||||
if (!p)
|
||||
{
|
||||
dberror(NULL, "Failed to lookup your UNIX username.");
|
||||
exit(1);
|
||||
}
|
||||
wild = malloc(strlen(p->pw_name) + 3);
|
||||
sprintf(wild, "%s_%%", p->pw_name);
|
||||
|
||||
res = mysql_list_dbs(pmysql, wild);
|
||||
rows = mysql_num_rows(res);
|
||||
dblist = malloc((rows + 2) * sizeof(char *)); /* one for the username
|
||||
(might not be used)*/
|
||||
if (!dblist)
|
||||
{
|
||||
dberror(NULL, "Out of memory.\n");
|
||||
free(wild);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < rows; i++)
|
||||
if (row = mysql_fetch_row(res))
|
||||
{
|
||||
dblist[i] = strdup(row[0]);
|
||||
}
|
||||
|
||||
res = mysql_list_dbs(pmysql, p->pw_name);
|
||||
rows = mysql_num_rows(res);
|
||||
if (rows == 1)
|
||||
dblist[i++] = strdup(p->pw_name);
|
||||
|
||||
dblist[i] = NULL;
|
||||
|
||||
return dblist;
|
||||
}
|
||||
|
||||
|
||||
writeperm(FILE *f, MYSQL *pmysql, const char *db)
|
||||
{
|
||||
char query[1024];
|
||||
MYSQL_RES *res;
|
||||
int rows, i;
|
||||
MYSQL_ROW row;
|
||||
|
||||
sprintf(query, "select user,select_priv,insert_priv,update_priv,"
|
||||
"delete_priv,create_priv,alter_priv,drop_priv from db where db='%s'", db);
|
||||
|
||||
if (mysql_query(pmysql, query))
|
||||
return dberror(pmysql, "Query for permissions failed.");
|
||||
res = mysql_store_result(pmysql);
|
||||
rows = mysql_num_rows(res);
|
||||
fprintf(f, "# User "
|
||||
"Select Insert Update Delete Create Alter Drop\n");
|
||||
fprintf(f, "# ---------------- "
|
||||
"------ ------ ------ ------ ------ ------ ------\n");
|
||||
if (rows == 0)
|
||||
fprintf(f, "# (no permissions currently granted to any users)\n");
|
||||
else
|
||||
for (i = 0; i < rows; i++)
|
||||
{
|
||||
row = mysql_fetch_row(res);
|
||||
fprintf(f, " %-16s %-7s %-7s %-7s %-7s %-7s %-7s %s\n",
|
||||
row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* show information about the database */
|
||||
int
|
||||
show(MYSQL *pmysql, const char *db)
|
||||
{
|
||||
printf("Database '%s':\n", db);
|
||||
|
||||
writeperm(stdout, pmysql, db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_GRANTS 1024
|
||||
|
||||
|
||||
int
|
||||
editperm(MYSQL *pmysql, const char *db)
|
||||
{
|
||||
char fn[] = "/tmp/mysql-dbadm.tmp.XXXXXX";
|
||||
FILE *f;
|
||||
char *editor;
|
||||
char cmd[1024]; /* shell command for editing the file */
|
||||
char line[1024]; /* buffer to hold one line */
|
||||
char *cp; /* used to interate through a line */
|
||||
char *user, *select_priv, *insert_priv, *update_priv, *delete_priv,
|
||||
*create_priv, *alter_priv, *drop_priv;
|
||||
char query[1024]; /* used to build a query */
|
||||
char *queries[MAX_GRANTS]; /* insert queries */
|
||||
int lines; /* number of grant lines processed */
|
||||
int i; /* iterate through lines[] */
|
||||
|
||||
mktemp(fn);
|
||||
if (strcmp(fn, "") == 0)
|
||||
return dberror(NULL, "Cannot create a unique temporary file name.");
|
||||
|
||||
f = fopen(fn, "w");
|
||||
if (f == NULL)
|
||||
return dberror(NULL, "Failed to open temporary file %s.", fn);
|
||||
writeperm(f, pmysql, db);
|
||||
fclose(f);
|
||||
|
||||
editor = getenv("EDITOR");
|
||||
if (!editor)
|
||||
editor = "pico"; /* OK since editor won't be freed */
|
||||
strcpy(cmd, editor);
|
||||
strcat(cmd, " ");
|
||||
strcat(cmd, fn);
|
||||
if (system(cmd) == -1)
|
||||
{
|
||||
dberror(NULL, "Failed to execute '%s'\n", cmd);
|
||||
perror("system");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse */
|
||||
f = fopen(fn, "r");
|
||||
lines = 0;
|
||||
while (fgets(line, sizeof(line), f))
|
||||
{
|
||||
cp = strchr(line, '\n');
|
||||
if (cp)
|
||||
*cp = '\0';
|
||||
|
||||
cp = line;
|
||||
while (*cp && ((*cp == ' ') || (*cp == '\t'))) cp++;
|
||||
if (*cp == '\0') continue;
|
||||
if (*cp == '#') continue;
|
||||
if (*cp == '\n') continue;
|
||||
|
||||
#define STRTOK_WHITESPACE(res, start) \
|
||||
{ if (!(res = strtok_whitespace(start))) continue; }
|
||||
|
||||
STRTOK_WHITESPACE(user, cp);
|
||||
if (strlen(user) < 1)
|
||||
return dberror(NULL, "Invalid user '%s' in grant line %d.", user,
|
||||
lines + 1);
|
||||
if (strcmp(user, "%") == 0)
|
||||
*user = '\0'; /* ugly, but it works... */
|
||||
|
||||
#define CHECK_PRIV(PRIV) \
|
||||
if (!valid_priv(PRIV)) return dberror(NULL, "Invalid value '%s' " \
|
||||
"in grant line %d.", PRIV, lines + 1)
|
||||
|
||||
STRTOK_WHITESPACE(select_priv, NULL);
|
||||
CHECK_PRIV(select_priv);
|
||||
STRTOK_WHITESPACE(insert_priv, NULL);
|
||||
CHECK_PRIV(insert_priv);
|
||||
STRTOK_WHITESPACE(update_priv, NULL);
|
||||
CHECK_PRIV(update_priv);
|
||||
STRTOK_WHITESPACE(delete_priv, NULL);
|
||||
CHECK_PRIV(delete_priv);
|
||||
STRTOK_WHITESPACE(create_priv, NULL);
|
||||
CHECK_PRIV(create_priv);
|
||||
STRTOK_WHITESPACE(alter_priv, NULL);
|
||||
CHECK_PRIV(alter_priv);
|
||||
STRTOK_WHITESPACE(drop_priv, NULL);
|
||||
CHECK_PRIV(drop_priv);
|
||||
|
||||
#undef STRTOK_WHITESPACE
|
||||
#undef CHECK_PRIV
|
||||
|
||||
sprintf(query, "insert into db(Host, Db, User, Select_priv, Insert_priv, "
|
||||
"Update_priv, Delete_priv, Create_priv, Alter_priv, Drop_priv) "
|
||||
"values ('%%', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
|
||||
db, user, select_priv, insert_priv, update_priv, delete_priv,
|
||||
create_priv, alter_priv, drop_priv);
|
||||
queries[lines] = strdup(query);
|
||||
lines++;
|
||||
if (lines >= MAX_GRANTS)
|
||||
{
|
||||
dberror(NULL, "Warning: Maximum of %d grants reached.\n",
|
||||
MAX_GRANTS);
|
||||
continue;
|
||||
}
|
||||
} /* while fgets ... */
|
||||
|
||||
unlink(fn);
|
||||
fclose(f);
|
||||
|
||||
/* now that we have checked the input for errors, we can safely
|
||||
delete the old grants from the database and insert the new ones. */
|
||||
|
||||
sprintf(query, "delete from db where db='%s'", db);
|
||||
if (mysql_query(pmysql, query))
|
||||
dberror(pmysql, "Failed to delete old grants for '%s'.", db);
|
||||
|
||||
for (i = 0; i < lines; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
puts(queries[i]);
|
||||
putchar('\n');
|
||||
#endif DEBUG
|
||||
if (mysql_query(pmysql, queries[i]))
|
||||
dberror(pmysql, "Failed to insert grant line %d.", i + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
enum { c_create, c_drop, c_editperm, c_show } command;
|
||||
MYSQL mysql;
|
||||
mysql_init(&mysql);
|
||||
char **dblist, **p;
|
||||
|
||||
program_name = argv[0];
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "--help") == 0)
|
||||
return usage();
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "--version") == 0)
|
||||
return version();
|
||||
|
||||
if (argc < 2)
|
||||
return wrong_use(NULL);
|
||||
|
||||
/* check that the supplied command is valid */
|
||||
|
||||
if (strcmp(argv[1], "create") == 0)
|
||||
command = c_create;
|
||||
else if (strcmp(argv[1], "drop") == 0)
|
||||
command = c_drop;
|
||||
else if (strcmp(argv[1], "editperm") == 0)
|
||||
command = c_editperm;
|
||||
else if (strcmp(argv[1], "show") == 0)
|
||||
command = c_show;
|
||||
else
|
||||
return wrong_use("unrecognized command"); /* XXX */
|
||||
|
||||
/* all other than show requires at lease one DATABASE argument. */
|
||||
if ((command != c_show) && (argc < 3))
|
||||
return wrong_use(NULL);
|
||||
|
||||
/* connect to the database server and select the mysql database */
|
||||
if (!mysql_real_connect(&mysql, DB_SERVER, DB_USER, DB_PASSWD, DB_NAME, 0, NULL, 0))
|
||||
return dberror(&mysql, "Cannot connect to database server '%s'.",
|
||||
DB_SERVER);
|
||||
if (mysql_select_db(&mysql, DB_NAME))
|
||||
return dberror(&mysql, "Cannot select database '%s'.", DB_NAME);
|
||||
|
||||
if ((command == c_show) && (argc == 2))
|
||||
{
|
||||
dblist = list(&mysql);
|
||||
p = dblist;
|
||||
while (*p)
|
||||
{
|
||||
show(&mysql, *p);
|
||||
free(*p);
|
||||
p++;
|
||||
}
|
||||
free(dblist);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* for each supplied database name, perform the requested action */
|
||||
for (i = 2; i < argc; i++)
|
||||
{
|
||||
if (! owner(argv[i]))
|
||||
{
|
||||
dberror(NULL, "You are not the owner of '%s'. Skipping.",
|
||||
argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case c_create:
|
||||
create(&mysql, argv[i]);
|
||||
break;
|
||||
case c_drop:
|
||||
drop(&mysql, argv[i]);
|
||||
break;
|
||||
case c_editperm:
|
||||
editperm(&mysql, argv[i]);
|
||||
break;
|
||||
case c_show:
|
||||
show(&mysql, argv[i]);
|
||||
break;
|
||||
default:
|
||||
return dberror(NULL, "This point should never be reached!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mysql_reload(&mysql);
|
||||
mysql_close(&mysql);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user