2 * (c) 2009-2012 by Art Cancro and citadel.org
3 * This program is released under the terms of the GNU General Public License v3.
9 int cmd_quit(int sock, char *cmdbuf) {
15 * Commands understood by ctdlsh
19 ctdlsh_cmdfunc_t *func;
23 COMMAND commands[] = {
24 { "?", cmd_help, "Display this message" },
25 { "help", cmd_help, "Display this message" },
26 { "date", cmd_datetime, "Print the server's date and time" },
27 { "config", cmd_config, "Configure the Citadel server" },
28 { "export", cmd_export, "Export all Citadel databases" },
29 { "shutdown", cmd_shutdown, "Shut down the Citadel server" },
30 { "time", cmd_datetime, "Print the server's date and time" },
31 { "passwd", cmd_passwd, "Set or change an account password" },
32 { "who", cmd_who, "Display a list of online users" },
33 { "exit", cmd_quit, "Quit using ctdlsh" },
34 { "quit", cmd_quit, "Quit using ctdlsh" },
39 int cmd_help(int sock, char *cmdbuf) {
42 for (i=0; commands[i].func != NULL; ++i) {
43 printf("%-10s %s\n", commands[i].name, commands[i].doc);
48 /* Auto-completer function */
49 char *command_generator(const char *text, int state) {
50 static int list_index;
59 while (name = commands[list_index].name) {
62 if (!strncmp(name, text, len)) {
71 /* Auto-completer function */
72 char **ctdlsh_completion(const char *text, int start, int end) {
73 char **matches = (char **) NULL;
76 matches = rl_completion_matches(text, command_generator);
79 rl_bind_key('\t', rl_abort);
86 void do_main_loop(int server_socket) {
90 char server_reply[1024];
96 /* Do an INFO command and learn the hostname for the prompt */
97 sock_puts(server_socket, "INFO");
98 sock_getln(server_socket, buf, sizeof buf);
101 while(sock_getln(server_socket, buf, sizeof buf), strcmp(buf, "000")) {
103 sprintf(prompt, "\n%s> ", buf);
109 /* Tell libreadline how we will help with auto-completion of commands */
110 rl_attempted_completion_function = ctdlsh_completion;
112 /* Here we go ... main command loop */
113 while ((ret != cmdret_exit) && (cmd = readline(prompt))) {
115 if ((cmd) && (*cmd)) {
118 for (i=0; commands[i].func != NULL; ++i) {
119 if (!strncasecmp(cmd, commands[i].name, strlen(commands[i].name))) {
120 ret = (*commands[i].func) (server_socket, cmd);
132 * If you don't know what main() does by now you probably shouldn't be reading this code.
134 int main(int argc, char **argv)
136 int server_socket = 0;
139 char *ctdldir = CTDLDIR;
141 printf("\nCitadel administration shell (c) 2009-2016 by citadel.org\n"
142 "This is open source software made available to you under the terms\n"
143 "of the GNU General Public License v3. All other rights reserved.\n"
147 while ((c = getopt (argc, argv, "h:")) != -1) {
154 fprintf(stderr, "Option -%c requires an argument\n", optopt);
157 fprintf(stderr, "Unknown option '-%c'\n", optopt);
158 fprintf(stderr, "usage: %s [-h citadel_dir]\n", argv[0]);
164 printf("Trying %s...\n", ctdldir);
165 sprintf(buf, "%s/citadel-admin.socket", ctdldir);
166 server_socket = uds_connectsock(buf);
167 if (server_socket < 0) {
171 sock_getln(server_socket, buf, sizeof buf);
173 do_main_loop(server_socket);
176 sock_puts(server_socket, "QUIT");
177 sock_getln(server_socket, buf, sizeof buf);
179 close(server_socket);