PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/bin/scripts/createuser.c

https://github.com/matheusoliveira/postgres
C | 381 lines | 334 code | 33 blank | 14 comment | 70 complexity | d313fd044e7d8daa6c75156d05c141e3 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*-------------------------------------------------------------------------
  2. *
  3. * createuser
  4. *
  5. * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
  6. * Portions Copyright (c) 1994, Regents of the University of California
  7. *
  8. * src/bin/scripts/createuser.c
  9. *
  10. *-------------------------------------------------------------------------
  11. */
  12. #include "postgres_fe.h"
  13. #include "common.h"
  14. #include "dumputils.h"
  15. static void help(const char *progname);
  16. int
  17. main(int argc, char *argv[])
  18. {
  19. static struct option long_options[] = {
  20. {"host", required_argument, NULL, 'h'},
  21. {"port", required_argument, NULL, 'p'},
  22. {"username", required_argument, NULL, 'U'},
  23. {"role", required_argument, NULL, 'g'},
  24. {"no-password", no_argument, NULL, 'w'},
  25. {"password", no_argument, NULL, 'W'},
  26. {"echo", no_argument, NULL, 'e'},
  27. {"createdb", no_argument, NULL, 'd'},
  28. {"no-createdb", no_argument, NULL, 'D'},
  29. {"superuser", no_argument, NULL, 's'},
  30. {"no-superuser", no_argument, NULL, 'S'},
  31. {"createrole", no_argument, NULL, 'r'},
  32. {"no-createrole", no_argument, NULL, 'R'},
  33. {"inherit", no_argument, NULL, 'i'},
  34. {"no-inherit", no_argument, NULL, 'I'},
  35. {"login", no_argument, NULL, 'l'},
  36. {"no-login", no_argument, NULL, 'L'},
  37. {"replication", no_argument, NULL, 1},
  38. {"no-replication", no_argument, NULL, 2},
  39. {"interactive", no_argument, NULL, 3},
  40. /* adduser is obsolete, undocumented spelling of superuser */
  41. {"adduser", no_argument, NULL, 'a'},
  42. {"no-adduser", no_argument, NULL, 'A'},
  43. {"connection-limit", required_argument, NULL, 'c'},
  44. {"pwprompt", no_argument, NULL, 'P'},
  45. {"encrypted", no_argument, NULL, 'E'},
  46. {"unencrypted", no_argument, NULL, 'N'},
  47. {NULL, 0, NULL, 0}
  48. };
  49. const char *progname;
  50. int optindex;
  51. int c;
  52. const char *newuser = NULL;
  53. char *host = NULL;
  54. char *port = NULL;
  55. char *username = NULL;
  56. SimpleStringList roles = {NULL, NULL};
  57. enum trivalue prompt_password = TRI_DEFAULT;
  58. bool echo = false;
  59. bool interactive = false;
  60. char *conn_limit = NULL;
  61. bool pwprompt = false;
  62. char *newpassword = NULL;
  63. /* Tri-valued variables. */
  64. enum trivalue createdb = TRI_DEFAULT,
  65. superuser = TRI_DEFAULT,
  66. createrole = TRI_DEFAULT,
  67. inherit = TRI_DEFAULT,
  68. login = TRI_DEFAULT,
  69. replication = TRI_DEFAULT,
  70. encrypted = TRI_DEFAULT;
  71. PQExpBufferData sql;
  72. PGconn *conn;
  73. PGresult *result;
  74. progname = get_progname(argv[0]);
  75. set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  76. handle_help_version_opts(argc, argv, "createuser", help);
  77. while ((c = getopt_long(argc, argv, "h:p:U:g:wWedDsSaArRiIlLc:PEN",
  78. long_options, &optindex)) != -1)
  79. {
  80. switch (c)
  81. {
  82. case 'h':
  83. host = pg_strdup(optarg);
  84. break;
  85. case 'p':
  86. port = pg_strdup(optarg);
  87. break;
  88. case 'U':
  89. username = pg_strdup(optarg);
  90. break;
  91. case 'g':
  92. simple_string_list_append(&roles, optarg);
  93. break;
  94. case 'w':
  95. prompt_password = TRI_NO;
  96. break;
  97. case 'W':
  98. prompt_password = TRI_YES;
  99. break;
  100. case 'e':
  101. echo = true;
  102. break;
  103. case 'd':
  104. createdb = TRI_YES;
  105. break;
  106. case 'D':
  107. createdb = TRI_NO;
  108. break;
  109. case 's':
  110. case 'a':
  111. superuser = TRI_YES;
  112. break;
  113. case 'S':
  114. case 'A':
  115. superuser = TRI_NO;
  116. break;
  117. case 'r':
  118. createrole = TRI_YES;
  119. break;
  120. case 'R':
  121. createrole = TRI_NO;
  122. break;
  123. case 'i':
  124. inherit = TRI_YES;
  125. break;
  126. case 'I':
  127. inherit = TRI_NO;
  128. break;
  129. case 'l':
  130. login = TRI_YES;
  131. break;
  132. case 'L':
  133. login = TRI_NO;
  134. break;
  135. case 'c':
  136. conn_limit = pg_strdup(optarg);
  137. break;
  138. case 'P':
  139. pwprompt = true;
  140. break;
  141. case 'E':
  142. encrypted = TRI_YES;
  143. break;
  144. case 'N':
  145. encrypted = TRI_NO;
  146. break;
  147. case 1:
  148. replication = TRI_YES;
  149. break;
  150. case 2:
  151. replication = TRI_NO;
  152. break;
  153. case 3:
  154. interactive = true;
  155. break;
  156. default:
  157. fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  158. exit(1);
  159. }
  160. }
  161. switch (argc - optind)
  162. {
  163. case 0:
  164. break;
  165. case 1:
  166. newuser = argv[optind];
  167. break;
  168. default:
  169. fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
  170. progname, argv[optind + 1]);
  171. fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  172. exit(1);
  173. }
  174. if (newuser == NULL)
  175. {
  176. if (interactive)
  177. newuser = simple_prompt("Enter name of role to add: ", 128, true);
  178. else
  179. {
  180. if (getenv("PGUSER"))
  181. newuser = getenv("PGUSER");
  182. else
  183. newuser = get_user_name_or_exit(progname);
  184. }
  185. }
  186. if (pwprompt)
  187. {
  188. char *pw1,
  189. *pw2;
  190. pw1 = simple_prompt("Enter password for new role: ", 100, false);
  191. pw2 = simple_prompt("Enter it again: ", 100, false);
  192. if (strcmp(pw1, pw2) != 0)
  193. {
  194. fprintf(stderr, _("Passwords didn't match.\n"));
  195. exit(1);
  196. }
  197. newpassword = pw1;
  198. free(pw2);
  199. }
  200. if (superuser == 0)
  201. {
  202. if (interactive && yesno_prompt("Shall the new role be a superuser?"))
  203. superuser = TRI_YES;
  204. else
  205. superuser = TRI_NO;
  206. }
  207. if (superuser == TRI_YES)
  208. {
  209. /* Not much point in trying to restrict a superuser */
  210. createdb = TRI_YES;
  211. createrole = TRI_YES;
  212. }
  213. if (createdb == 0)
  214. {
  215. if (interactive && yesno_prompt("Shall the new role be allowed to create databases?"))
  216. createdb = TRI_YES;
  217. else
  218. createdb = TRI_NO;
  219. }
  220. if (createrole == 0)
  221. {
  222. if (interactive && yesno_prompt("Shall the new role be allowed to create more new roles?"))
  223. createrole = TRI_YES;
  224. else
  225. createrole = TRI_NO;
  226. }
  227. if (inherit == 0)
  228. inherit = TRI_YES;
  229. if (login == 0)
  230. login = TRI_YES;
  231. conn = connectDatabase("postgres", host, port, username, prompt_password,
  232. progname, false);
  233. initPQExpBuffer(&sql);
  234. printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
  235. if (newpassword)
  236. {
  237. if (encrypted == TRI_YES)
  238. appendPQExpBufferStr(&sql, " ENCRYPTED");
  239. if (encrypted == TRI_NO)
  240. appendPQExpBufferStr(&sql, " UNENCRYPTED");
  241. appendPQExpBufferStr(&sql, " PASSWORD ");
  242. if (encrypted != TRI_NO)
  243. {
  244. char *encrypted_password;
  245. encrypted_password = PQencryptPassword(newpassword,
  246. newuser);
  247. if (!encrypted_password)
  248. {
  249. fprintf(stderr, _("Password encryption failed.\n"));
  250. exit(1);
  251. }
  252. appendStringLiteralConn(&sql, encrypted_password, conn);
  253. PQfreemem(encrypted_password);
  254. }
  255. else
  256. appendStringLiteralConn(&sql, newpassword, conn);
  257. }
  258. if (superuser == TRI_YES)
  259. appendPQExpBufferStr(&sql, " SUPERUSER");
  260. if (superuser == TRI_NO)
  261. appendPQExpBufferStr(&sql, " NOSUPERUSER");
  262. if (createdb == TRI_YES)
  263. appendPQExpBufferStr(&sql, " CREATEDB");
  264. if (createdb == TRI_NO)
  265. appendPQExpBufferStr(&sql, " NOCREATEDB");
  266. if (createrole == TRI_YES)
  267. appendPQExpBufferStr(&sql, " CREATEROLE");
  268. if (createrole == TRI_NO)
  269. appendPQExpBufferStr(&sql, " NOCREATEROLE");
  270. if (inherit == TRI_YES)
  271. appendPQExpBufferStr(&sql, " INHERIT");
  272. if (inherit == TRI_NO)
  273. appendPQExpBufferStr(&sql, " NOINHERIT");
  274. if (login == TRI_YES)
  275. appendPQExpBufferStr(&sql, " LOGIN");
  276. if (login == TRI_NO)
  277. appendPQExpBufferStr(&sql, " NOLOGIN");
  278. if (replication == TRI_YES)
  279. appendPQExpBufferStr(&sql, " REPLICATION");
  280. if (replication == TRI_NO)
  281. appendPQExpBufferStr(&sql, " NOREPLICATION");
  282. if (conn_limit != NULL)
  283. appendPQExpBuffer(&sql, " CONNECTION LIMIT %s", conn_limit);
  284. if (roles.head != NULL)
  285. {
  286. SimpleStringListCell *cell;
  287. appendPQExpBufferStr(&sql, " IN ROLE ");
  288. for (cell = roles.head; cell; cell = cell->next)
  289. {
  290. if (cell->next)
  291. appendPQExpBuffer(&sql, "%s,", fmtId(cell->val));
  292. else
  293. appendPQExpBuffer(&sql, "%s", fmtId(cell->val));
  294. }
  295. }
  296. appendPQExpBufferStr(&sql, ";");
  297. if (echo)
  298. printf("%s\n", sql.data);
  299. result = PQexec(conn, sql.data);
  300. if (PQresultStatus(result) != PGRES_COMMAND_OK)
  301. {
  302. fprintf(stderr, _("%s: creation of new role failed: %s"),
  303. progname, PQerrorMessage(conn));
  304. PQfinish(conn);
  305. exit(1);
  306. }
  307. PQclear(result);
  308. PQfinish(conn);
  309. exit(0);
  310. }
  311. static void
  312. help(const char *progname)
  313. {
  314. printf(_("%s creates a new PostgreSQL role.\n\n"), progname);
  315. printf(_("Usage:\n"));
  316. printf(_(" %s [OPTION]... [ROLENAME]\n"), progname);
  317. printf(_("\nOptions:\n"));
  318. printf(_(" -c, --connection-limit=N connection limit for role (default: no limit)\n"));
  319. printf(_(" -d, --createdb role can create new databases\n"));
  320. printf(_(" -D, --no-createdb role cannot create databases (default)\n"));
  321. printf(_(" -e, --echo show the commands being sent to the server\n"));
  322. printf(_(" -E, --encrypted encrypt stored password\n"));
  323. printf(_(" -g, --role=ROLE new role will be a member of this role\n"));
  324. printf(_(" -i, --inherit role inherits privileges of roles it is a\n"
  325. " member of (default)\n"));
  326. printf(_(" -I, --no-inherit role does not inherit privileges\n"));
  327. printf(_(" -l, --login role can login (default)\n"));
  328. printf(_(" -L, --no-login role cannot login\n"));
  329. printf(_(" -N, --unencrypted do not encrypt stored password\n"));
  330. printf(_(" -P, --pwprompt assign a password to new role\n"));
  331. printf(_(" -r, --createrole role can create new roles\n"));
  332. printf(_(" -R, --no-createrole role cannot create roles (default)\n"));
  333. printf(_(" -s, --superuser role will be superuser\n"));
  334. printf(_(" -S, --no-superuser role will not be superuser (default)\n"));
  335. printf(_(" -V, --version output version information, then exit\n"));
  336. printf(_(" --interactive prompt for missing role name and attributes rather\n"
  337. " than using defaults\n"));
  338. printf(_(" --replication role can initiate replication\n"));
  339. printf(_(" --no-replication role cannot initiate replication\n"));
  340. printf(_(" -?, --help show this help, then exit\n"));
  341. printf(_("\nConnection options:\n"));
  342. printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
  343. printf(_(" -p, --port=PORT database server port\n"));
  344. printf(_(" -U, --username=USERNAME user name to connect as (not the one to create)\n"));
  345. printf(_(" -w, --no-password never prompt for password\n"));
  346. printf(_(" -W, --password force password prompt\n"));
  347. printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
  348. }