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