Integrated the DKIM signer into serv_smtpclient, but disabled it
[citadel.git] / ctdlsh / main.c
1 /*
2  * (c) 2009-2020 by Art Cancro and citadel.org
3  * This program is open source.  It runs great on the Linux operating system.
4  * It's released under the General Public License (GPL) version 3.
5  */
6
7 #include "ctdlsh.h"
8
9
10 /*
11  * Commands understood by ctdlsh
12  */
13 typedef struct {
14         char *name;
15         ctdlsh_cmdfunc_t *func;
16         char *doc;
17 } COMMAND;
18
19 COMMAND commands[] = {
20         { "?", cmd_help, "Display this message" },
21         { "help", cmd_help, "Display this message" },
22         { "date", cmd_datetime, "Print the server's date and time" },
23         { "config", cmd_config, "Configure the Citadel server" },
24         { "export", cmd_export, "Export all Citadel databases" },
25         { "shutdown", cmd_shutdown, "Shut down the Citadel server" },
26         { "time", cmd_datetime, "Print the server's date and time" },
27         { "passwd", cmd_passwd, "Set or change an account password" },
28         { "who", cmd_who, "Display a list of online users" },
29         { "mailq", cmd_mailq, "Show the outbound email queue" },
30         { NULL, NULL, NULL }
31 };
32
33
34
35 int cmd_help(int sock, char *cmdbuf)
36 {
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 int do_one_command(int server_socket, char *cmd)
46 {
47         int i;
48         int ret;
49         for (i = 0; commands[i].func != NULL; ++i) {
50                 if (!strncasecmp(cmd, commands[i].name, strlen(commands[i].name))) {
51                         ret = (*commands[i].func) (server_socket, cmd);
52                 }
53         }
54         return ret;
55 }
56
57 char *command_name_generator(const char *text, int state)
58 {
59         static int list_index, len;
60         char *name;
61
62         if (!state) {
63                 list_index = 0;
64                 len = strlen(text);
65         }
66
67         while (name = commands[list_index++].name) {
68                 if (strncmp(name, text, len) == 0) {
69                         return strdup(name);
70                 }
71         }
72
73         return NULL;
74 }
75
76
77 char **command_name_completion(const char *text, int start, int end)
78 {
79         rl_attempted_completion_over = 1;
80         return rl_completion_matches(text, command_name_generator);
81 }
82
83
84 void do_main_loop(int server_socket)
85 {
86         char *cmd = NULL;
87         char prompt[1024];
88         char buf[1024];
89         char server_reply[1024];
90         int i;
91         int ret = (-1);
92
93         strcpy(prompt, "> ");
94
95         /* Do an INFO command and learn the hostname for the prompt */
96         sock_puts(server_socket, "INFO");
97         sock_getln(server_socket, buf, sizeof buf);
98         if (buf[0] == '1') {
99                 i = 0;
100                 while (sock_getln(server_socket, buf, sizeof buf),
101                        strcmp(buf, "000")) {
102                         if (i == 1) {
103                                 sprintf(prompt, "\n%s> ", buf);
104                         }
105                         ++i;
106                 }
107         }
108
109         /* Here we go ... main command loop */
110         rl_attempted_completion_function = command_name_completion;
111         while ((cmd = readline(prompt)), cmd) {
112                 if (*cmd) {
113                         add_history(cmd);
114                         ret = do_one_command(server_socket, cmd);
115                 }
116                 free(cmd);
117         }
118 }
119
120
121 /*
122  * If you don't know what main() does by now you probably shouldn't be reading this code.
123  */
124 int main(int argc, char **argv)
125 {
126         int server_socket = 0;
127         char buf[1024];
128         int i;
129         char *ctdldir = CTDLDIR;
130         char cmd[1024] = { 0 };
131         int exitcode = 0;
132
133         for (i = 1; i < argc; ++i) {
134                 if (!strcmp(argv[i], "-h")) {
135                         ctdldir = argv[++i];
136                 } else {
137                         if (strlen(cmd) > 0) {
138                                 strcat(cmd, " ");
139                         }
140                         strcat(cmd, argv[i]);
141                 }
142         }
143
144         int is_interactive = ((strlen(cmd) == 0) ? 1 : 0);
145
146         if (is_interactive) {
147                 printf
148                     ("\nCitadel administration shell (c) 2009-2020 by citadel.org\n"
149                      "This is open source software made available to you under the terms\n"
150                      "of the GNU General Public License v3.  All other rights reserved.\n");
151                 printf("Connecting to Citadel server in %s...\n", ctdldir);
152         }
153
154         sprintf(buf, "%s/citadel-admin.socket", ctdldir);
155         server_socket = uds_connectsock(buf);
156         if (server_socket < 0) {
157                 exit(1);
158         }
159
160         sock_getln(server_socket, buf, sizeof buf);
161         if (buf[0] == '2') {
162                 if (is_interactive) {
163                         printf("Connected: %s\n", buf);
164                         do_main_loop(server_socket);
165                 } else {
166                         exitcode = do_one_command(server_socket, cmd);
167                 }
168         }
169
170         sock_puts(server_socket, "QUIT");
171         sock_getln(server_socket, buf, sizeof buf);
172         if (is_interactive) {
173                 printf("%s\n", buf);
174         }
175         close(server_socket);
176         exit(exitcode);
177 }