? GNUmakefile ? config.log ? config.status ? configure.lineno ? src/Makefile.global ? src/backend/postgres ? src/backend/access/common/.deps ? src/backend/access/gist/.deps ? src/backend/access/hash/.deps ? src/backend/access/heap/.deps ? src/backend/access/index/.deps ? src/backend/access/nbtree/.deps ? src/backend/access/rtree/.deps ? src/backend/access/transam/.deps ? src/backend/bootstrap/.deps ? src/backend/catalog/.deps ? src/backend/catalog/pg_location.c ? src/backend/catalog/postgres.bki ? src/backend/catalog/postgres.description ? src/backend/commands/.deps ? src/backend/executor/.deps ? src/backend/lib/.deps ? src/backend/libpq/.deps ? src/backend/main/.deps ? src/backend/nodes/.deps ? src/backend/optimizer/geqo/.deps ? src/backend/optimizer/path/.deps ? src/backend/optimizer/plan/.deps ? src/backend/optimizer/prep/.deps ? src/backend/optimizer/util/.deps ? src/backend/parser/.deps ? src/backend/port/.deps ? src/backend/postmaster/.deps ? src/backend/regex/.deps ? src/backend/rewrite/.deps ? src/backend/storage/buffer/.deps ? src/backend/storage/file/.deps ? src/backend/storage/freespace/.deps ? src/backend/storage/ipc/.deps ? src/backend/storage/large_object/.deps ? src/backend/storage/lmgr/.deps ? src/backend/storage/page/.deps ? src/backend/storage/smgr/.deps ? src/backend/tcop/.deps ? src/backend/utils/.deps ? src/backend/utils/adt/.deps ? src/backend/utils/cache/.deps ? src/backend/utils/error/.deps ? src/backend/utils/fmgr/.deps ? src/backend/utils/hash/.deps ? src/backend/utils/init/.deps ? src/backend/utils/mb/.deps ? src/backend/utils/mb/conversion_procs/conversion_create.sql ? src/backend/utils/mb/conversion_procs/ascii_and_mic/.deps ? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0 ? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/.deps ? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0 ? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/.deps ? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0 ? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/.deps ? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0 ? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/.deps ? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0 ? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/.deps ? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0 ? src/backend/utils/mb/conversion_procs/latin2_and_win1250/.deps ? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0 ? src/backend/utils/mb/conversion_procs/latin_and_mic/.deps ? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_ascii/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_big5/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gbk/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_johab/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_sjis/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_tcvn/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_tcvn/libutf8_and_tcvn.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_uhc/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_win1250/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_win1250/libutf8_and_win1250.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_win1256/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_win1256/libutf8_and_win1256.so.0 ? src/backend/utils/mb/conversion_procs/utf8_and_win874/.deps ? src/backend/utils/mb/conversion_procs/utf8_and_win874/libutf8_and_win874.so.0 ? src/backend/utils/misc/.deps ? src/backend/utils/mmgr/.deps ? src/backend/utils/sort/.deps ? src/backend/utils/time/.deps ? src/bin/initdb/.deps ? src/bin/initdb/initdb ? src/bin/initlocation/initlocation ? src/bin/ipcclean/ipcclean ? src/bin/pg_config/pg_config ? src/bin/pg_controldata/.deps ? src/bin/pg_controldata/pg_controldata ? src/bin/pg_ctl/pg_ctl ? src/bin/pg_dump/.deps ? src/bin/pg_dump/pg_dump ? src/bin/pg_dump/pg_dumpall ? src/bin/pg_dump/pg_restore ? src/bin/pg_encoding/.deps ? src/bin/pg_encoding/pg_encoding ? src/bin/pg_id/.deps ? src/bin/pg_id/pg_id ? src/bin/pg_resetxlog/.deps ? src/bin/pg_resetxlog/pg_resetxlog ? src/bin/psql/.deps ? src/bin/psql/psql ? src/bin/scripts/.deps ? src/bin/scripts/clusterdb ? src/bin/scripts/createdb ? src/bin/scripts/createlang ? src/bin/scripts/createuser ? src/bin/scripts/dropdb ? src/bin/scripts/droplang ? src/bin/scripts/dropuser ? src/bin/scripts/vacuumdb ? src/include/pg_config.h ? src/include/stamp-h ? src/include/catalog/pg_location.h ? src/interfaces/ecpg/compatlib/.deps ? src/interfaces/ecpg/compatlib/libecpg_compat.so.1 ? src/interfaces/ecpg/ecpglib/.deps ? src/interfaces/ecpg/ecpglib/libecpg.so.3 ? src/interfaces/ecpg/ecpglib/libecpg.so.4 ? src/interfaces/ecpg/lib/libecpg.so.3 ? src/interfaces/ecpg/pgtypeslib/.deps ? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.1 ? src/interfaces/ecpg/preproc/.deps ? src/interfaces/ecpg/preproc/ecpg ? src/interfaces/libpq/.deps ? src/interfaces/libpq/libpq.so.3 ? src/pl/plpgsql/src/.deps ? src/pl/plpgsql/src/libplpgsql.so.1 ? src/port/.deps ? src/test/regress/postgres.core Index: doc/src/sgml/ref/alter_user.sgml =================================================================== RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/ref/alter_user.sgml,v retrieving revision 1.32 diff -c -r1.32 alter_user.sgml *** doc/src/sgml/ref/alter_user.sgml 29 Nov 2003 19:51:38 -0000 1.32 --- doc/src/sgml/ref/alter_user.sgml 24 Dec 2003 12:35:16 -0000 *************** *** 27,32 **** --- 27,33 ---- [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password' | CREATEDB | NOCREATEDB | CREATEUSER | NOCREATEUSER + | CATALOG | NOCATALOG | VALID UNTIL 'abstime' ALTER USER name RENAME TO newname *************** *** 132,137 **** --- 133,156 ---- + CATALOG + NOCATALOG + + + This clause determines whether or not a user will be permitted + to manually edit the system catalogs, using the regular SQL DML + statements. + + + + Since any user granted this permission can easily make themselves + a superuser, the owner of any object or cause complete database + destruction, this is a very dangerous privilege to allow. + + + + + abstime *************** *** 233,242 **** ! Give a user the ability to create other users and new databases: ! ALTER USER miriam CREATEUSER CREATEDB; --- 252,262 ---- ! Give a user the ability to create other users and new databases, but ! not the ability to manually edit the system catalogs: ! ALTER USER miriam CREATEUSER CREATEDB NOCATALOG; Index: doc/src/sgml/ref/create_user.sgml =================================================================== RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/ref/create_user.sgml,v retrieving revision 1.32 diff -c -r1.32 create_user.sgml *** doc/src/sgml/ref/create_user.sgml 14 Dec 2003 00:15:03 -0000 1.32 --- doc/src/sgml/ref/create_user.sgml 24 Dec 2003 12:35:17 -0000 *************** *** 28,33 **** --- 28,34 ---- | [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password' | CREATEDB | NOCREATEDB | CREATEUSER | NOCREATEUSER + | CATALOG | NOCATALOG | IN GROUP groupname [, ...] | VALID UNTIL 'abstime' *************** *** 144,149 **** --- 145,169 ---- + + CATALOG + NOCATALOG + + + This clause determines whether or not a user will be permitted + to manually edit the system catalogs, using the regular SQL DML + statements. If this clause is omitted, NOCATALOG + will be assumed. + + + + Since any user granted this permission can easily make themselves + a superuser, the owner of any object or cause complete database + destruction, this is a very dangerous privilege to allow. + + + + groupname Index: src/backend/commands/user.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/commands/user.c,v retrieving revision 1.131 diff -c -r1.131 user.c *** src/backend/commands/user.c 29 Nov 2003 19:51:47 -0000 1.131 --- src/backend/commands/user.c 24 Dec 2003 12:35:25 -0000 *************** *** 500,505 **** --- 500,506 ---- int sysid = 0; /* PgSQL system id (valid if havesysid) */ bool createdb = false; /* Can the user create databases? */ bool createuser = false; /* Can this user create users? */ + bool catalog = false; /* Can this user manually edit the catalogs? */ List *groupElts = NIL; /* The groups the user is a member of */ char *validUntil = NULL; /* The time the login is valid * until */ *************** *** 507,512 **** --- 508,514 ---- DefElem *dsysid = NULL; DefElem *dcreatedb = NULL; DefElem *dcreateuser = NULL; + DefElem *dcatalog = NULL; DefElem *dgroupElts = NULL; DefElem *dvalidUntil = NULL; *************** *** 553,558 **** --- 555,568 ---- errmsg("conflicting or redundant options"))); dcreateuser = defel; } + else if (strcmp(defel->defname, "catalog") == 0) + { + if (dcatalog) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + dcatalog = defel; + } else if (strcmp(defel->defname, "groupElts") == 0) { if (dgroupElts) *************** *** 578,583 **** --- 588,595 ---- createdb = intVal(dcreatedb->arg) != 0; if (dcreateuser) createuser = intVal(dcreateuser->arg) != 0; + if (dcatalog) + catalog = intVal(dcatalog->arg) != 0; if (dsysid) { sysid = intVal(dsysid->arg); *************** *** 603,608 **** --- 615,623 ---- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to create users"))); + /* XXX: Need to check here that the superuser doing the granting + has the catalog priv if they're granting the catalog priv... */ + if (strcmp(stmt->user, "public") == 0) ereport(ERROR, (errcode(ERRCODE_RESERVED_NAME), *************** *** 667,674 **** new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb); AssertState(BoolIsValid(createuser)); new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser); ! /* superuser gets catupd right by default */ ! new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(createuser); if (password) { --- 682,689 ---- new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb); AssertState(BoolIsValid(createuser)); new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser); ! AssertState(BoolIsValid(catalog)); ! new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(catalog); if (password) { *************** *** 753,763 **** --- 768,780 ---- char encrypted_password[MD5_PASSWD_LEN + 1]; int createdb = -1; /* Can the user create databases? */ int createuser = -1; /* Can this user create users? */ + int catalog = -1; /* Can this user manually edit the catalogs? */ char *validUntil = NULL; /* The time the login is valid * until */ DefElem *dpassword = NULL; DefElem *dcreatedb = NULL; DefElem *dcreateuser = NULL; + DefElem *dcatalog = NULL; DefElem *dvalidUntil = NULL; /* Extract options from the statement node tree */ *************** *** 795,800 **** --- 812,825 ---- errmsg("conflicting or redundant options"))); dcreateuser = defel; } + else if (strcmp(defel->defname, "catalog") == 0) + { + if (dcatalog) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + dcatalog = defel; + } else if (strcmp(defel->defname, "validUntil") == 0) { if (dvalidUntil) *************** *** 812,817 **** --- 837,844 ---- createdb = intVal(dcreatedb->arg); if (dcreateuser) createuser = intVal(dcreateuser->arg); + if (dcatalog) + catalog = intVal(dcatalog->arg); if (dvalidUntil) validUntil = strVal(dvalidUntil->arg); if (dpassword) *************** *** 824,835 **** --- 851,866 ---- if (!superuser() && !(createdb < 0 && createuser < 0 && + catalog < 0 && !validUntil && password && strcmp(GetUserNameFromId(GetUserId()), stmt->user) == 0)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); + + /* XXX: Need to check here that the superuser doing the granting + has the catalog priv if they're granting the catalog priv... */ /* * Scan the pg_shadow relation to be certain the user exists. Note we *************** *** 865,884 **** new_record_repl[Anum_pg_shadow_usecreatedb - 1] = 'r'; } ! /* ! * createuser (superuser) and catupd ! * ! * XXX It's rather unclear how to handle catupd. It's probably best to ! * keep it equal to the superuser status, otherwise you could end up ! * with a situation where no existing superuser can alter the ! * catalogs, including pg_shadow! ! */ if (createuser >= 0) { new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser > 0); new_record_repl[Anum_pg_shadow_usesuper - 1] = 'r'; ! ! new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(createuser > 0); new_record_repl[Anum_pg_shadow_usecatupd - 1] = 'r'; } --- 896,912 ---- new_record_repl[Anum_pg_shadow_usecreatedb - 1] = 'r'; } ! /* createuser (superuser) */ if (createuser >= 0) { new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser > 0); new_record_repl[Anum_pg_shadow_usesuper - 1] = 'r'; ! } ! ! /* catupd */ ! if (catalog >= 0) ! { ! new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(catalog > 0); new_record_repl[Anum_pg_shadow_usecatupd - 1] = 'r'; } Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/parser/gram.y,v retrieving revision 2.441 diff -c -r2.441 gram.y *** src/backend/parser/gram.y 1 Dec 2003 22:07:58 -0000 2.441 --- src/backend/parser/gram.y 24 Dec 2003 12:37:00 -0000 *************** *** 334,340 **** BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT BOOLEAN_P BOTH BY ! CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT COMMITTED CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB --- 334,340 ---- BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT BOOLEAN_P BOTH BY ! CACHE CALLED CASCADE CASE CAST CATALOG_P CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT COMMITTED CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB *************** *** 370,376 **** MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE ! NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NULL_P NULLIF NUMERIC --- 370,376 ---- MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE ! NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCATALOG_P NOCREATEDB NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NULL_P NULLIF NUMERIC *************** *** 672,677 **** --- 672,685 ---- { $$ = makeDefElem("createuser", (Node *)makeInteger(FALSE)); } + | CATALOG_P + { + $$ = makeDefElem("catalog", (Node *)makeInteger(TRUE)); + } + | NOCATALOG_P + { + $$ = makeDefElem("catalog", (Node *)makeInteger(FALSE)); + } | IN_P GROUP_P user_list { $$ = makeDefElem("groupElts", (Node *)$3); *************** *** 7348,7353 **** --- 7356,7362 ---- | CACHE | CALLED | CASCADE + | CATALOG_P | CHAIN | CHARACTERISTICS | CHECKPOINT *************** *** 7431,7436 **** --- 7440,7446 ---- | NATIONAL | NEXT | NO + | NOCATALOG_P | NOCREATEDB | NOCREATEUSER | NOTHING Index: src/backend/parser/keywords.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/parser/keywords.c,v retrieving revision 1.144 diff -c -r1.144 keywords.c *** src/backend/parser/keywords.c 29 Nov 2003 19:51:51 -0000 1.144 --- src/backend/parser/keywords.c 24 Dec 2003 12:37:00 -0000 *************** *** 65,70 **** --- 65,71 ---- {"cascade", CASCADE}, {"case", CASE}, {"cast", CAST}, + {"catalog", CATALOG_P}, {"chain", CHAIN}, {"char", CHAR_P}, {"character", CHARACTER}, *************** *** 205,210 **** --- 206,212 ---- {"new", NEW}, {"next", NEXT}, {"no", NO}, + {"nocatalog", NOCATALOG_P}, {"nocreatedb", NOCREATEDB}, {"nocreateuser", NOCREATEUSER}, {"none", NONE}, Index: src/bin/pg_dump/pg_dumpall.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/bin/pg_dump/pg_dumpall.c,v retrieving revision 1.29 diff -c -r1.29 pg_dumpall.c *** src/bin/pg_dump/pg_dumpall.c 29 Nov 2003 19:52:05 -0000 1.29 --- src/bin/pg_dump/pg_dumpall.c 24 Dec 2003 12:37:03 -0000 *************** *** 277,289 **** if (server_version >= 70100) res = executeQuery(conn, "SELECT usename, usesysid, passwd, usecreatedb, " ! "usesuper, valuntil " "FROM pg_shadow " "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0')"); else res = executeQuery(conn, "SELECT usename, usesysid, passwd, usecreatedb, " ! "usesuper, valuntil " "FROM pg_shadow " "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')"); --- 277,289 ---- if (server_version >= 70100) res = executeQuery(conn, "SELECT usename, usesysid, passwd, usecreatedb, " ! "usesuper, valuntil, usecatupd " "FROM pg_shadow " "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0')"); else res = executeQuery(conn, "SELECT usename, usesysid, passwd, usecreatedb, " ! "usesuper, valuntil, usecatupd " "FROM pg_shadow " "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')"); *************** *** 312,317 **** --- 312,322 ---- appendPQExpBuffer(buf, " CREATEUSER"); else appendPQExpBuffer(buf, " NOCREATEUSER"); + + if (strcmp(PQgetvalue(res, i, 6), "t") == 0) + appendPQExpBuffer(buf, " CATALOG"); + else + appendPQExpBuffer(buf, " NOCATALOG"); if (!PQgetisnull(res, i, 5)) appendPQExpBuffer(buf, " VALID UNTIL '%s'", Index: src/bin/scripts/createuser.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/bin/scripts/createuser.c,v retrieving revision 1.7 diff -c -r1.7 createuser.c *** src/bin/scripts/createuser.c 29 Nov 2003 19:52:07 -0000 1.7 --- src/bin/scripts/createuser.c 24 Dec 2003 12:37:03 -0000 *************** *** 32,37 **** --- 32,39 ---- {"no-createdb", no_argument, NULL, 'D'}, {"adduser", no_argument, NULL, 'a'}, {"no-adduser", no_argument, NULL, 'A'}, + {"catalog", no_argument, NULL, 'c'}, + {"no-catalog", no_argument, NULL, 'C'}, {"sysid", required_argument, NULL, 'i'}, {"pwprompt", no_argument, NULL, 'P'}, {"encrypted", no_argument, NULL, 'E'}, *************** *** 52,57 **** --- 54,60 ---- bool quiet = false; int createdb = 0; int adduser = 0; + int catalog = 0; char *sysid = NULL; bool pwprompt = false; int encrypted = 0; /* 0 uses server default */ *************** *** 100,105 **** --- 103,114 ---- case 'D': createdb = -1; break; + case 'c': + catalog = +1; + break; + case 'C': + catalog = -1; + break; case 'i': sysid = optarg; break; *************** *** 184,189 **** --- 193,209 ---- adduser = -1; } + if (catalog == 0) + { + char *reply; + + reply = simple_prompt("Shall the new user be allowed to manually edit the system catalogs? (y/n) ", 1, true); + if (check_yesno_response(reply) == 1) + catalog = +1; + else + catalog = -1; + } + initPQExpBuffer(&sql); printfPQExpBuffer(&sql, "CREATE USER %s", fmtId(newuser)); *************** *** 206,211 **** --- 226,235 ---- appendPQExpBuffer(&sql, " CREATEUSER"); if (adduser == -1) appendPQExpBuffer(&sql, " NOCREATEUSER"); + if (catalog == +1) + appendPQExpBuffer(&sql, " CATALOG"); + if (catalog == -1) + appendPQExpBuffer(&sql, " NOCATALOG"); appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase("template1", host, port, username, password, progname); *************** *** 240,245 **** --- 264,271 ---- printf(_(" -A, --no-adduser user cannot add new users\n")); printf(_(" -d, --createdb user can create new databases\n")); printf(_(" -D, --no-createdb user cannot create databases\n")); + printf(_(" -c, --catalog user can manually edit the system catalogs\n")); + printf(_(" -C, --no-catalog user cannot manually edit the system catalogs\n")); printf(_(" -P, --pwprompt assign a password to new user\n")); printf(_(" -E, --encrypted encrypt stored password\n")); printf(_(" -N, --unencrypted do no encrypt stored password\n"));