Consistently use "superuser" instead of "super user"
[pgsql.git] / src / bin / scripts / createuser.c
blob35b5ccaa5b3b15f9ba1a6e0d8e2a6b476aa7264d
1 /*-------------------------------------------------------------------------
3 * createuser
5 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * src/bin/scripts/createuser.c
10 *-------------------------------------------------------------------------
13 #include "postgres_fe.h"
15 #include <limits.h>
17 #include "common.h"
18 #include "common/logging.h"
19 #include "common/string.h"
20 #include "fe_utils/option_utils.h"
21 #include "fe_utils/simple_list.h"
22 #include "fe_utils/string_utils.h"
25 static void help(const char *progname);
27 int
28 main(int argc, char *argv[])
30 static struct option long_options[] = {
31 {"host", required_argument, NULL, 'h'},
32 {"port", required_argument, NULL, 'p'},
33 {"username", required_argument, NULL, 'U'},
34 {"role", required_argument, NULL, 'g'},
35 {"no-password", no_argument, NULL, 'w'},
36 {"password", no_argument, NULL, 'W'},
37 {"echo", no_argument, NULL, 'e'},
38 {"createdb", no_argument, NULL, 'd'},
39 {"no-createdb", no_argument, NULL, 'D'},
40 {"superuser", no_argument, NULL, 's'},
41 {"no-superuser", no_argument, NULL, 'S'},
42 {"createrole", no_argument, NULL, 'r'},
43 {"no-createrole", no_argument, NULL, 'R'},
44 {"inherit", no_argument, NULL, 'i'},
45 {"no-inherit", no_argument, NULL, 'I'},
46 {"login", no_argument, NULL, 'l'},
47 {"no-login", no_argument, NULL, 'L'},
48 {"replication", no_argument, NULL, 1},
49 {"no-replication", no_argument, NULL, 2},
50 {"interactive", no_argument, NULL, 3},
51 {"connection-limit", required_argument, NULL, 'c'},
52 {"pwprompt", no_argument, NULL, 'P'},
53 {"encrypted", no_argument, NULL, 'E'},
54 {NULL, 0, NULL, 0}
57 const char *progname;
58 int optindex;
59 int c;
60 const char *newuser = NULL;
61 char *host = NULL;
62 char *port = NULL;
63 char *username = NULL;
64 SimpleStringList roles = {NULL, NULL};
65 enum trivalue prompt_password = TRI_DEFAULT;
66 ConnParams cparams;
67 bool echo = false;
68 bool interactive = false;
69 int conn_limit = -2; /* less than minimum valid value */
70 bool pwprompt = false;
71 char *newpassword = NULL;
73 /* Tri-valued variables. */
74 enum trivalue createdb = TRI_DEFAULT,
75 superuser = TRI_DEFAULT,
76 createrole = TRI_DEFAULT,
77 inherit = TRI_DEFAULT,
78 login = TRI_DEFAULT,
79 replication = TRI_DEFAULT;
81 PQExpBufferData sql;
83 PGconn *conn;
84 PGresult *result;
86 pg_logging_init(argv[0]);
87 progname = get_progname(argv[0]);
88 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
90 handle_help_version_opts(argc, argv, "createuser", help);
92 while ((c = getopt_long(argc, argv, "h:p:U:g:wWedDsSrRiIlLc:PE",
93 long_options, &optindex)) != -1)
95 switch (c)
97 case 'h':
98 host = pg_strdup(optarg);
99 break;
100 case 'p':
101 port = pg_strdup(optarg);
102 break;
103 case 'U':
104 username = pg_strdup(optarg);
105 break;
106 case 'g':
107 simple_string_list_append(&roles, optarg);
108 break;
109 case 'w':
110 prompt_password = TRI_NO;
111 break;
112 case 'W':
113 prompt_password = TRI_YES;
114 break;
115 case 'e':
116 echo = true;
117 break;
118 case 'd':
119 createdb = TRI_YES;
120 break;
121 case 'D':
122 createdb = TRI_NO;
123 break;
124 case 's':
125 superuser = TRI_YES;
126 break;
127 case 'S':
128 superuser = TRI_NO;
129 break;
130 case 'r':
131 createrole = TRI_YES;
132 break;
133 case 'R':
134 createrole = TRI_NO;
135 break;
136 case 'i':
137 inherit = TRI_YES;
138 break;
139 case 'I':
140 inherit = TRI_NO;
141 break;
142 case 'l':
143 login = TRI_YES;
144 break;
145 case 'L':
146 login = TRI_NO;
147 break;
148 case 'c':
149 if (!option_parse_int(optarg, "-c/--connection-limit",
150 -1, INT_MAX, &conn_limit))
151 exit(1);
152 break;
153 case 'P':
154 pwprompt = true;
155 break;
156 case 'E':
157 /* no-op, accepted for backward compatibility */
158 break;
159 case 1:
160 replication = TRI_YES;
161 break;
162 case 2:
163 replication = TRI_NO;
164 break;
165 case 3:
166 interactive = true;
167 break;
168 default:
169 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
170 exit(1);
174 switch (argc - optind)
176 case 0:
177 break;
178 case 1:
179 newuser = argv[optind];
180 break;
181 default:
182 pg_log_error("too many command-line arguments (first is \"%s\")",
183 argv[optind + 1]);
184 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
185 exit(1);
188 if (newuser == NULL)
190 if (interactive)
192 newuser = simple_prompt("Enter name of role to add: ", true);
194 else
196 if (getenv("PGUSER"))
197 newuser = getenv("PGUSER");
198 else
199 newuser = get_user_name_or_exit(progname);
203 if (pwprompt)
205 char *pw2;
207 newpassword = simple_prompt("Enter password for new role: ", false);
208 pw2 = simple_prompt("Enter it again: ", false);
209 if (strcmp(newpassword, pw2) != 0)
211 fprintf(stderr, _("Passwords didn't match.\n"));
212 exit(1);
214 free(pw2);
217 if (superuser == 0)
219 if (interactive && yesno_prompt("Shall the new role be a superuser?"))
220 superuser = TRI_YES;
221 else
222 superuser = TRI_NO;
225 if (superuser == TRI_YES)
227 /* Not much point in trying to restrict a superuser */
228 createdb = TRI_YES;
229 createrole = TRI_YES;
232 if (createdb == 0)
234 if (interactive && yesno_prompt("Shall the new role be allowed to create databases?"))
235 createdb = TRI_YES;
236 else
237 createdb = TRI_NO;
240 if (createrole == 0)
242 if (interactive && yesno_prompt("Shall the new role be allowed to create more new roles?"))
243 createrole = TRI_YES;
244 else
245 createrole = TRI_NO;
248 if (inherit == 0)
249 inherit = TRI_YES;
251 if (login == 0)
252 login = TRI_YES;
254 cparams.dbname = NULL; /* this program lacks any dbname option... */
255 cparams.pghost = host;
256 cparams.pgport = port;
257 cparams.pguser = username;
258 cparams.prompt_password = prompt_password;
259 cparams.override_dbname = NULL;
261 conn = connectMaintenanceDatabase(&cparams, progname, echo);
263 initPQExpBuffer(&sql);
265 printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
266 if (newpassword)
268 char *encrypted_password;
270 appendPQExpBufferStr(&sql, " PASSWORD ");
272 encrypted_password = PQencryptPasswordConn(conn,
273 newpassword,
274 newuser,
275 NULL);
276 if (!encrypted_password)
278 pg_log_error("password encryption failed: %s",
279 PQerrorMessage(conn));
280 exit(1);
282 appendStringLiteralConn(&sql, encrypted_password, conn);
283 PQfreemem(encrypted_password);
285 if (superuser == TRI_YES)
286 appendPQExpBufferStr(&sql, " SUPERUSER");
287 if (superuser == TRI_NO)
288 appendPQExpBufferStr(&sql, " NOSUPERUSER");
289 if (createdb == TRI_YES)
290 appendPQExpBufferStr(&sql, " CREATEDB");
291 if (createdb == TRI_NO)
292 appendPQExpBufferStr(&sql, " NOCREATEDB");
293 if (createrole == TRI_YES)
294 appendPQExpBufferStr(&sql, " CREATEROLE");
295 if (createrole == TRI_NO)
296 appendPQExpBufferStr(&sql, " NOCREATEROLE");
297 if (inherit == TRI_YES)
298 appendPQExpBufferStr(&sql, " INHERIT");
299 if (inherit == TRI_NO)
300 appendPQExpBufferStr(&sql, " NOINHERIT");
301 if (login == TRI_YES)
302 appendPQExpBufferStr(&sql, " LOGIN");
303 if (login == TRI_NO)
304 appendPQExpBufferStr(&sql, " NOLOGIN");
305 if (replication == TRI_YES)
306 appendPQExpBufferStr(&sql, " REPLICATION");
307 if (replication == TRI_NO)
308 appendPQExpBufferStr(&sql, " NOREPLICATION");
309 if (conn_limit >= -1)
310 appendPQExpBuffer(&sql, " CONNECTION LIMIT %d", conn_limit);
311 if (roles.head != NULL)
313 SimpleStringListCell *cell;
315 appendPQExpBufferStr(&sql, " IN ROLE ");
317 for (cell = roles.head; cell; cell = cell->next)
319 if (cell->next)
320 appendPQExpBuffer(&sql, "%s,", fmtId(cell->val));
321 else
322 appendPQExpBufferStr(&sql, fmtId(cell->val));
325 appendPQExpBufferChar(&sql, ';');
327 if (echo)
328 printf("%s\n", sql.data);
329 result = PQexec(conn, sql.data);
331 if (PQresultStatus(result) != PGRES_COMMAND_OK)
333 pg_log_error("creation of new role failed: %s", PQerrorMessage(conn));
334 PQfinish(conn);
335 exit(1);
338 PQclear(result);
339 PQfinish(conn);
340 exit(0);
344 static void
345 help(const char *progname)
347 printf(_("%s creates a new PostgreSQL role.\n\n"), progname);
348 printf(_("Usage:\n"));
349 printf(_(" %s [OPTION]... [ROLENAME]\n"), progname);
350 printf(_("\nOptions:\n"));
351 printf(_(" -c, --connection-limit=N connection limit for role (default: no limit)\n"));
352 printf(_(" -d, --createdb role can create new databases\n"));
353 printf(_(" -D, --no-createdb role cannot create databases (default)\n"));
354 printf(_(" -e, --echo show the commands being sent to the server\n"));
355 printf(_(" -g, --role=ROLE new role will be a member of this role\n"));
356 printf(_(" -i, --inherit role inherits privileges of roles it is a\n"
357 " member of (default)\n"));
358 printf(_(" -I, --no-inherit role does not inherit privileges\n"));
359 printf(_(" -l, --login role can login (default)\n"));
360 printf(_(" -L, --no-login role cannot login\n"));
361 printf(_(" -P, --pwprompt assign a password to new role\n"));
362 printf(_(" -r, --createrole role can create new roles\n"));
363 printf(_(" -R, --no-createrole role cannot create roles (default)\n"));
364 printf(_(" -s, --superuser role will be superuser\n"));
365 printf(_(" -S, --no-superuser role will not be superuser (default)\n"));
366 printf(_(" -V, --version output version information, then exit\n"));
367 printf(_(" --interactive prompt for missing role name and attributes rather\n"
368 " than using defaults\n"));
369 printf(_(" --replication role can initiate replication\n"));
370 printf(_(" --no-replication role cannot initiate replication\n"));
371 printf(_(" -?, --help show this help, then exit\n"));
372 printf(_("\nConnection options:\n"));
373 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
374 printf(_(" -p, --port=PORT database server port\n"));
375 printf(_(" -U, --username=USERNAME user name to connect as (not the one to create)\n"));
376 printf(_(" -w, --no-password never prompt for password\n"));
377 printf(_(" -W, --password force password prompt\n"));
378 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
379 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);