Reworked ctdlsh to use the new admin socket instead of ipgm
[citadel.git] / ctdlsh / src / main.c
1 /*
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.
4  */
5
6 #include "ctdlsh.h"
7
8
9 int cmd_quit(int sock, char *cmdbuf) {
10         return(cmdret_exit);
11 }
12
13
14 /*
15  * Commands understood by ctdlsh
16  */
17 typedef struct {
18         char *name;
19         ctdlsh_cmdfunc_t *func;
20         char *doc;
21 } COMMAND;
22
23 COMMAND commands[] = {
24         {       "?",            cmd_help,       "Display this message"                  },
25         {       "help",         cmd_help,       "Display this message"                  },
26         {       "quit",         cmd_quit,       "Quit using ctdlsh"                     },
27         {       "exit",         cmd_quit,       "Quit using ctdlsh"                     },
28         {       "date",         cmd_datetime,   "Print the server's date and time"      },
29         {       "time",         cmd_datetime,   "Print the server's date and time"      },
30         {       "passwd",       cmd_passwd,     "Set or change an account password"     },
31         {       "shutdown",     cmd_shutdown,   "Shut down the Citadel server"          },
32         {       NULL,           NULL,           NULL                                    }
33 };
34
35
36 int cmd_help(int sock, char *cmdbuf) {
37         int i;
38
39         for (i=0; commands[i].func != NULL; ++i) {
40                 printf("%-10s %s\n", commands[i].name, commands[i].doc);
41         }
42 }
43
44
45 /* Auto-completer function */
46 char *command_generator(const char *text, int state) {
47         static int list_index;
48         static int len;
49         char *name;
50
51         if (!state) {
52                 list_index = 0;
53                 len = strlen(text);
54         }
55
56         while (name = commands[list_index].name) {
57                 ++list_index;
58
59                 if (!strncmp(name, text, len)) {
60                         return(strdup(name));
61                 }
62         }
63
64         return(NULL);
65 }
66
67
68 /* Auto-completer function */
69 char **ctdlsh_completion(const char *text, int start, int end) {
70         char **matches = (char **) NULL;
71
72         if (start == 0) {
73                 matches = rl_completion_matches(text, command_generator);
74         }
75         else {
76                 rl_bind_key('\t', rl_abort);
77         }
78
79         return (matches);
80 }
81
82
83
84 void do_main_loop(int server_socket) {
85         char *cmd = NULL;
86         char prompt[1024];
87         char buf[1024];
88         char server_reply[1024];
89         int i;
90         int ret = (-1);
91
92         strcpy(prompt, "> ");
93
94         /* Do an INFO command and learn the hostname for the prompt */
95         sock_puts(server_socket, "INFO");
96         sock_getln(server_socket, buf, sizeof buf);
97         if (buf[0] == '1') {
98                 i = 0;
99                 while(sock_getln(server_socket, buf, sizeof buf), strcmp(buf, "000")) {
100                         if (i == 1) {
101                                 sprintf(prompt, "\n%s> ", buf);
102                         }
103                         ++i;
104                 }
105         }
106
107         /* Tell libreadline how we will help with auto-completion of commands */
108         rl_attempted_completion_function = ctdlsh_completion;
109
110         /* Here we go ... main command loop */
111         while ((ret != cmdret_exit) && (cmd = readline(prompt))) {
112
113                 if ((cmd) && (*cmd)) {
114                         add_history(cmd);
115
116                         for (i=0; commands[i].func != NULL; ++i) {
117                                 if (!strncasecmp(cmd, commands[i].name, strlen(commands[i].name))) {
118                                         ret = (*commands[i].func) (server_socket, cmd);
119                                 }
120                         }
121
122                 }
123
124                 free(cmd);
125         }
126 }
127
128 int main(int argc, char **argv)
129 {
130         int server_socket = 0;
131         char buf[1024];
132         int c;
133         char *ctdldir = CTDLDIR;
134
135         printf("\nCitadel administration shell v" PACKAGE_VERSION "\n");
136         printf("(c) 2009-2011 citadel.org GPLv3\n");
137
138         opterr = 0;
139         while ((c = getopt (argc, argv, "h:")) != -1) {
140                 switch(c) {
141                 case 'h':
142                         ctdldir = optarg;
143                         break;
144                 case '?':
145                         if (optopt == 'h') {
146                                 fprintf(stderr, "Option -%c requires an argument\n", optopt);
147                         }
148                         else {
149                                 fprintf(stderr, "Unknown option '-%c'\n", optopt);
150                                 fprintf(stderr, "usage: %s [-h citadel_dir]\n", argv[0]);
151                         }
152                         exit(1);
153                 }
154         }
155
156         printf("Trying %s...\n", ctdldir);
157         sprintf(buf, "%s/citadel-admin.socket", ctdldir);
158         server_socket = uds_connectsock(buf);
159         if (server_socket < 0) {
160                 exit(1);
161         }
162
163         sock_getln(server_socket, buf, sizeof buf);
164         if (buf[0] == '2') {
165                 do_main_loop(server_socket);
166         }
167
168         sock_puts(server_socket, "QUIT");
169         sock_getln(server_socket, buf, sizeof buf);
170         printf("%s\n", buf);
171         close(server_socket);
172         exit(0);
173 }