2 * Command-line utility to transmit a server command.
4 * Copyright (c) 1987-2012 by the citadel.org team
6 * This program is open source software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include "ctdl_module.h"
19 #include <sys/types.h>
26 #if TIME_WITH_SYS_TIME
27 # include <sys/time.h>
31 # include <sys/time.h>
40 #include <libcitadel.h>
42 #include "citadel_ipc.h"
46 static CtdlIPC *ipc = NULL;
49 * Why both cleanup() and nq_cleanup() ? Notice the alarm() call in
50 * cleanup() . If for some reason sendcommand hangs waiting for the server
51 * to clean up, the alarm clock goes off and the program exits anyway.
52 * The cleanup() routine makes a check to ensure it's not reentering, in
53 * case the ipc module looped it somehow.
55 void nq_cleanup(int e)
58 fprintf(stderr, "\nWatch dog time out.\n");
63 * send binary to server
65 void serv_write(CtdlIPC *ipc, const char *buf, unsigned int nbytes)
67 unsigned int bytes_written = 0;
70 while (bytes_written < nbytes) {
71 retval = write(ipc->sock, &buf[bytes_written],
72 nbytes - bytes_written);
74 connection_died(ipc, 0);
77 bytes_written += retval;
84 static int nested = 0;
87 signal(SIGALRM, nq_cleanup);
90 serv_write(ipc, "\n", 1);
99 * This is implemented as a function rather than as a macro because the
100 * client-side IPC modules expect logoff() to be defined. They call logoff()
101 * when a problem connecting or staying connected to the server occurs.
109 * Connect sendcommand to the Citadel server running on this computer.
111 void np_attach_to_server(char *host, char *port)
114 char hostbuf[256], portbuf[256];
116 {"sendcommand", NULL};
119 fprintf(stderr, "Attaching to server...\n");
120 strcpy(hostbuf, host);
121 strcpy(portbuf, port);
122 ipc = CtdlIPC_new(1, args, hostbuf, portbuf);
124 fprintf(stderr, "Can't connect: %s\n", strerror(errno));
127 CtdlIPC_chat_recv(ipc, buf);
128 fprintf(stderr, "%s\n", &buf[4]);
129 snprintf(buf, sizeof buf, "IPGM %d", config.c_ipgm_secret);
130 r = CtdlIPCInternalProgram(ipc, config.c_ipgm_secret, buf);
131 fprintf(stderr, "%s\n", buf);
138 void sendcommand_die(void) {
144 int main(int argc, char **argv)
153 char relhome[PATH_MAX]="";
154 char ctdldir[PATH_MAX]=CTDLDIR;
158 int server_shutting_down = 0;
160 strcpy(ctdl_home_directory, DEFAULT_PORT);
164 * Change directories if specified
166 for (a = 1; a < argc; ++a) {
167 if (!strncmp(argv[a], "-h", 2)) {
168 relh=argv[a][2]!='/';
169 if (!relh) safestrncpy(ctdl_home_directory, &argv[a][2], sizeof ctdl_home_directory);
171 safestrncpy(relhome, &argv[a][2], sizeof relhome);
174 } else if (!strncmp(argv[a], "-w", 2)) {
175 watchdog = atoi(&argv[a][2]);
179 if (!IsEmptyStr(cmd)) {
182 strcat(cmd, argv[a]);
186 calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
189 signal(SIGINT, cleanup);
190 signal(SIGQUIT, cleanup);
191 signal(SIGHUP, cleanup);
192 signal(SIGTERM, cleanup);
194 fprintf(stderr, "sendcommand: started (pid=%d) "
197 ctdl_home_directory);
201 signal(SIGALRM, nq_cleanup); /* Set up a watchdog type timer in case we hang */
203 np_attach_to_server(UDS, ctdl_home_directory);
205 setIPCDeathHook(sendcommand_die);
207 fprintf(stderr, "%s\n", cmd);
208 CtdlIPC_chat_send(ipc, cmd);
209 CtdlIPC_chat_recv(ipc, buf);
210 fprintf(stderr, "%s\n", buf);
215 if (!strncasecmp(&buf[1], "31", 2)) {
216 server_shutting_down = 1;
220 while (CtdlIPC_chat_recv(ipc, buf), strcmp(buf, "000")) {
222 alarm(watchdog); /* Kick the watchdog timer */
224 } else if (buf[0] == '4') {
226 if (fgets(buf, sizeof buf, stdin) == NULL)
228 if (!IsEmptyStr(buf))
229 if (buf[strlen(buf) - 1] == '\n')
230 buf[strlen(buf) - 1] = 0;
231 if (!IsEmptyStr(buf))
232 if (buf[strlen(buf) - 1] == '\r')
233 buf[strlen(buf) - 1] = 0;
234 if (strcmp(buf, "000"))
235 CtdlIPC_chat_send(ipc, buf);
238 FD_SET(ipc->sock, &read_fd);
239 ret = select(ipc->sock+1, &read_fd, NULL, NULL, &tv);
241 if (!(errno == EINTR || errno == EAGAIN))
242 fprintf(stderr, "select() failed: %s", strerror(errno));
251 n = read(ipc->sock, rbuf, SIZ);
254 fprintf(stderr, "%s", rbuf);
258 alarm(watchdog); /* Kick the watchdog timer */
259 } while (strcmp(buf, "000"));
260 CtdlIPC_chat_send(ipc, "\n");
261 CtdlIPC_chat_send(ipc, "000");
263 alarm(0); /* Shutdown the watchdog timer */
264 fprintf(stderr, "sendcommand: processing ended.\n");
266 /* Clean up and log off ... unless the server indicated that the command
267 * we sent is shutting it down, in which case we want to just cut the
268 * connection and exit.
270 if (server_shutting_down) {
282 void stty_ctdl(int cmd) {