4 * Command-line utility to transmit a server command.
11 #include <sys/types.h>
18 #if TIME_WITH_SYS_TIME
19 # include <sys/time.h>
23 # include <sys/time.h>
32 #include <libcitadel.h>
34 #include "citadel_ipc.h"
38 #define LOCKFILE "/tmp/LCK.sendcommand"
40 static CtdlIPC
*ipc
= NULL
;
43 * make sure only one copy of sendcommand runs at a time, using lock files
45 int set_lockfile(void)
50 if ((lfp
= fopen(LOCKFILE
, "r")) != NULL
) {
51 fscanf(lfp
, "%d", &onppid
);
53 if (!kill(onppid
, 0) || errno
== EPERM
)
56 lfp
= fopen(LOCKFILE
, "w");
57 fprintf(lfp
, "%ld\n", (long) getpid());
62 void remove_lockfile(void)
68 * Why both cleanup() and nq_cleanup() ? Notice the alarm() call in
69 * cleanup() . If for some reason sendcommand hangs waiting for the server
70 * to clean up, the alarm clock goes off and the program exits anyway.
71 * The cleanup() routine makes a check to ensure it's not reentering, in
72 * case the ipc module looped it somehow.
74 void nq_cleanup(int e
)
77 fprintf(stderr
, "\nWatch dog time out.\n");
83 * send binary to server
85 void serv_write(CtdlIPC
*ipc
, const char *buf
, unsigned int nbytes
)
87 unsigned int bytes_written
= 0;
90 #if defined(HAVE_OPENSSL)
92 serv_write_ssl(ipc, buf, nbytes);
97 while (bytes_written
< nbytes
) {
98 retval
= write(ipc
->sock
, &buf
[bytes_written
],
99 nbytes
- bytes_written
);
101 connection_died(ipc
, 0);
104 bytes_written
+= retval
;
111 static int nested
= 0;
114 signal(SIGALRM
, nq_cleanup
);
115 serv_write(ipc
, "\n", 1);
122 * This is implemented as a function rather than as a macro because the
123 * client-side IPC modules expect logoff() to be defined. They call logoff()
124 * when a problem connecting or staying connected to the server occurs.
132 * Connect sendcommand to the Citadel server running on this computer.
134 void np_attach_to_server(char *host
, char *port
)
137 char hostbuf
[256], portbuf
[256];
139 {"sendcommand", NULL
};
142 fprintf(stderr
, "Attaching to server...\n");
143 strcpy(hostbuf
, host
);
144 strcpy(portbuf
, port
);
145 ipc
= CtdlIPC_new(1, args
, hostbuf
, portbuf
);
147 fprintf(stderr
, "Can't connect: %s\n", strerror(errno
));
150 CtdlIPC_chat_recv(ipc
, buf
);
151 fprintf(stderr
, "%s\n", &buf
[4]);
152 snprintf(buf
, sizeof buf
, "IPGM %d", config
.c_ipgm_secret
);
153 r
= CtdlIPCInternalProgram(ipc
, config
.c_ipgm_secret
, buf
);
154 fprintf(stderr
, "%s\n", buf
);
161 void sendcommand_die(void) {
170 int main(int argc
, char **argv
)
179 char relhome
[PATH_MAX
]="";
180 char ctdldir
[PATH_MAX
]=CTDLDIR
;
184 int server_shutting_down
= 0;
186 strcpy(ctdl_home_directory
, DEFAULT_PORT
);
190 * Change directories if specified
192 for (a
= 1; a
< argc
; ++a
) {
193 if (!strncmp(argv
[a
], "-h", 2)) {
194 relh
=argv
[a
][2]!='/';
195 if (!relh
) safestrncpy(ctdl_home_directory
, &argv
[a
][2],
196 sizeof ctdl_home_directory
);
198 safestrncpy(relhome
, &argv
[a
][2],
201 } else if (!strncmp(argv
[a
], "-w", 2)) {
202 watchdog
= atoi(&argv
[a
][2]);
206 if (!IsEmptyStr(cmd
))
208 strcat(cmd
, argv
[a
]);
212 calc_dirs_n_files(relh
, home
, relhome
, ctdldir
, 0);
215 signal(SIGINT
, cleanup
);
216 signal(SIGQUIT
, cleanup
);
217 signal(SIGHUP
, cleanup
);
218 signal(SIGTERM
, cleanup
);
220 fprintf(stderr
, "sendcommand: started (pid=%d) "
223 ctdl_home_directory
);
227 signal(SIGALRM
, nq_cleanup
); /* Set up a watchdog type timer in case we hang */
229 np_attach_to_server(UDS
, ctdl_home_directory
);
231 setIPCDeathHook(sendcommand_die
);
233 fprintf(stderr
, "%s\n", cmd
);
234 CtdlIPC_chat_send(ipc
, cmd
);
235 CtdlIPC_chat_recv(ipc
, buf
);
236 fprintf(stderr
, "%s\n", buf
);
241 if (!strncasecmp(&buf
[1], "31", 2)) {
242 server_shutting_down
= 1;
246 while (CtdlIPC_chat_recv(ipc
, buf
), strcmp(buf
, "000")) {
248 alarm(watchdog
); /* Kick the watchdog timer */
250 } else if (buf
[0] == '4') {
252 if (fgets(buf
, sizeof buf
, stdin
) == NULL
)
254 if (!IsEmptyStr(buf
))
255 if (buf
[strlen(buf
) - 1] == '\n')
256 buf
[strlen(buf
) - 1] = 0;
257 if (!IsEmptyStr(buf
))
258 if (buf
[strlen(buf
) - 1] == '\r')
259 buf
[strlen(buf
) - 1] = 0;
260 if (strcmp(buf
, "000"))
261 CtdlIPC_chat_send(ipc
, buf
);
264 FD_SET(ipc
->sock
, &read_fd
);
265 ret
= select(ipc
->sock
+1, &read_fd
, NULL
, NULL
, &tv
);
268 printf("select failed: %d", err
);
271 if (!(errno
== EINTR
|| errno
== EAGAIN
))
272 printf("select failed: %d", err
);
281 n
= read(ipc
->sock
, rbuf
, SIZ
);
284 fprintf (stderr
, rbuf
);
288 alarm(watchdog
); /* Kick the watchdog timer */
289 } while (strcmp(buf
, "000"));
290 CtdlIPC_chat_send(ipc
, "\n");
291 CtdlIPC_chat_send(ipc
, "000");
293 alarm(0); /* Shutdown the watchdog timer */
294 fprintf(stderr
, "sendcommand: processing ended.\n");
296 /* Clean up and log off ... unless the server indicated that the command
297 * we sent is shutting it down, in which case we want to just cut the
298 * connection and exit.
300 if (server_shutting_down
) {
312 void stty_ctdl(int cmd
) {