1 /*-------------------------------------------------------------------------
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"
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
);
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'},
60 const char *newuser
= NULL
;
63 char *username
= NULL
;
64 SimpleStringList roles
= {NULL
, NULL
};
65 enum trivalue prompt_password
= TRI_DEFAULT
;
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
,
79 replication
= TRI_DEFAULT
;
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)
98 host
= pg_strdup(optarg
);
101 port
= pg_strdup(optarg
);
104 username
= pg_strdup(optarg
);
107 simple_string_list_append(&roles
, optarg
);
110 prompt_password
= TRI_NO
;
113 prompt_password
= TRI_YES
;
131 createrole
= TRI_YES
;
149 if (!option_parse_int(optarg
, "-c/--connection-limit",
150 -1, INT_MAX
, &conn_limit
))
157 /* no-op, accepted for backward compatibility */
160 replication
= TRI_YES
;
163 replication
= TRI_NO
;
169 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
174 switch (argc
- optind
)
179 newuser
= argv
[optind
];
182 pg_log_error("too many command-line arguments (first is \"%s\")",
184 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
192 newuser
= simple_prompt("Enter name of role to add: ", true);
196 if (getenv("PGUSER"))
197 newuser
= getenv("PGUSER");
199 newuser
= get_user_name_or_exit(progname
);
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"));
219 if (interactive
&& yesno_prompt("Shall the new role be a superuser?"))
225 if (superuser
== TRI_YES
)
227 /* Not much point in trying to restrict a superuser */
229 createrole
= TRI_YES
;
234 if (interactive
&& yesno_prompt("Shall the new role be allowed to create databases?"))
242 if (interactive
&& yesno_prompt("Shall the new role be allowed to create more new roles?"))
243 createrole
= 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
));
268 char *encrypted_password
;
270 appendPQExpBufferStr(&sql
, " PASSWORD ");
272 encrypted_password
= PQencryptPasswordConn(conn
,
276 if (!encrypted_password
)
278 pg_log_error("password encryption failed: %s",
279 PQerrorMessage(conn
));
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");
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
)
320 appendPQExpBuffer(&sql
, "%s,", fmtId(cell
->val
));
322 appendPQExpBufferStr(&sql
, fmtId(cell
->val
));
325 appendPQExpBufferChar(&sql
, ';');
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
));
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
);