2 * (c) 2009-2011 by Art Cancro and citadel.org
3 * This program is released under the terms of the GNU General Public License v3.
11 int cmd_quit(int sock, char *cmdbuf) {
17 * Commands understood by ctdlsh
21 ctdlsh_cmdfunc_t *func;
25 COMMAND commands[] = {
26 { "?", cmd_help, "Display this message" },
27 { "help", cmd_help, "Display this message" },
28 { "quit", cmd_quit, "Quit using ctdlsh" },
29 { "exit", cmd_quit, "Quit using ctdlsh" },
30 { "date", cmd_datetime, "Print the server's date and time" },
31 { "time", cmd_datetime, "Print the server's date and time" },
32 { "passwd", cmd_passwd, "Set or change an account password" },
33 { "shutdown", cmd_shutdown, "Shut down the Citadel server" },
38 int cmd_help(int sock, char *cmdbuf) {
41 for (i=0; commands[i].func != NULL; ++i) {
42 printf("%-10s %s\n", commands[i].name, commands[i].doc);
51 int discover_ipgm_secret(char *dirname) {
53 struct partial_config ccc;
54 char configfile[1024];
56 sprintf(configfile, "%s/citadel.config", dirname);
57 fd = open(configfile, O_RDONLY);
59 fprintf(stderr, "%s: %s\n", configfile, strerror(errno));
63 if (read(fd, &ccc, sizeof(struct partial_config)) != sizeof(struct partial_config)) {
64 fprintf(stderr, "%s: %s\n", configfile, strerror(errno));
68 fprintf(stderr, "%s: %s\n", configfile, strerror(errno));
71 return(ccc.c_ipgm_secret);
75 /* Auto-completer function */
76 char *command_generator(const char *text, int state) {
77 static int list_index;
86 while (name = commands[list_index].name) {
89 if (!strncmp(name, text, len)) {
98 /* Auto-completer function */
99 char **ctdlsh_completion(const char *text, int start, int end) {
100 char **matches = (char **) NULL;
103 matches = rl_completion_matches(text, command_generator);
106 rl_bind_key('\t', rl_abort);
114 void do_main_loop(int server_socket) {
118 char server_reply[1024];
122 strcpy(prompt, "> ");
124 /* Do an INFO command and learn the hostname for the prompt */
125 sock_puts(server_socket, "INFO");
126 sock_getln(server_socket, buf, sizeof buf);
129 while(sock_getln(server_socket, buf, sizeof buf), strcmp(buf, "000")) {
131 sprintf(prompt, "\n%s> ", buf);
137 /* Tell libreadline how we will help with auto-completion of commands */
138 rl_attempted_completion_function = ctdlsh_completion;
140 /* Here we go ... main command loop */
141 while ((ret != cmdret_exit) && (cmd = readline(prompt))) {
143 if ((cmd) && (*cmd)) {
146 for (i=0; commands[i].func != NULL; ++i) {
147 if (!strncasecmp(cmd, commands[i].name, strlen(commands[i].name))) {
148 ret = (*commands[i].func) (server_socket, cmd);
158 int main(int argc, char **argv)
160 int server_socket = 0;
162 int ipgm_secret = (-1);
164 char *ctdldir = CTDLDIR;
166 printf("\nCitadel administration shell v" PACKAGE_VERSION "\n");
167 printf("(c) 2009-2011 citadel.org GPLv3\n");
170 while ((c = getopt (argc, argv, "h:")) != -1) {
177 fprintf(stderr, "Option -%c requires an argument\n", optopt);
180 fprintf(stderr, "Unknown option '-%c'\n", optopt);
181 fprintf(stderr, "usage: %s [-h citadel_dir]\n", argv[0]);
187 ipgm_secret = discover_ipgm_secret(ctdldir);
188 if (ipgm_secret < 0) {
192 printf("Trying %s...\n", ctdldir);
193 sprintf(buf, "%s/citadel.socket", ctdldir);
194 server_socket = uds_connectsock(buf);
195 if (server_socket < 0) {
199 sock_getln(server_socket, buf, sizeof buf);
202 sock_printf(server_socket, "IPGM %d\n", ipgm_secret);
203 sock_getln(server_socket, buf, sizeof buf);
207 do_main_loop(server_socket);
210 sock_puts(server_socket, "QUIT");
211 sock_getln(server_socket, buf, sizeof buf);
213 close(server_socket);