2 * $Id: sendcommand.c 5736 2007-11-10 23:12:19Z dothebart $
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
)
81 * send binary to server
83 void serv_write(CtdlIPC
*ipc
, const char *buf
, unsigned int nbytes
)
85 unsigned int bytes_written
= 0;
88 #if defined(HAVE_OPENSSL)
90 serv_write_ssl(ipc, buf, nbytes);
95 while (bytes_written
< nbytes
) {
96 retval
= write(ipc
->sock
, &buf
[bytes_written
],
97 nbytes
- bytes_written
);
99 connection_died(ipc
, 0);
102 bytes_written
+= retval
;
109 static int nested
= 0;
112 signal(SIGALRM
, nq_cleanup
);
113 serv_write(ipc
, "\n", 1);
120 * This is implemented as a function rather than as a macro because the
121 * client-side IPC modules expect logoff() to be defined. They call logoff()
122 * when a problem connecting or staying connected to the server occurs.
129 static char *args
[] =
133 * Connect sendcommand to the Citadel server running on this computer.
135 void np_attach_to_server(char *host
, char *port
)
138 char hostbuf
[256] = "";
139 char portbuf
[256] = "";
142 fprintf(stderr
, "Attaching to server...\n");
143 strncpy(hostbuf
, host
, 256);
144 strncpy(portbuf
, port
, 256);
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) {
167 * saves filelen bytes from file at pathname
169 int save_buffer(void *file
, size_t filelen
, const char *pathname
)
172 size_t bytes_written
= 0;
175 fp
= fopen(pathname
, "w");
177 fprintf(stderr
, "Cannot open '%s': %s\n", pathname
, strerror(errno
));
181 block
= fwrite((char *)file
+ bytes_written
, 1,
182 filelen
- bytes_written
, fp
);
183 bytes_written
+= block
;
184 } while (errno
== EINTR
&& bytes_written
< filelen
);
187 if (bytes_written
< filelen
) {
188 fprintf(stderr
,"Trouble saving '%s': %s\n", pathname
,
199 int main(int argc
, char **argv
)
204 int MessageToRetrieve
;
205 int MessageFound
= 0;
209 char relhome
[PATH_MAX
]="";
210 char ctdldir
[PATH_MAX
]=CTDLDIR
;
214 int server_shutting_down
= 0;
215 struct ctdlipcroom
*Room
;
216 struct ctdlipcmessage
*mret
;
218 unsigned long *msgarr
;
221 strcpy(ctdl_home_directory
, DEFAULT_PORT
);
224 * Change directories if specified
226 for (a
= 1; a
< argc
&& n
< 5; ++a
) {
227 if (!strncmp(argv
[a
], "-h", 2)) {
228 relh
=argv
[a
][2]!='/';
229 if (!relh
) safestrncpy(ctdl_home_directory
, &argv
[a
][2],
230 sizeof ctdl_home_directory
);
232 safestrncpy(relhome
, &argv
[a
][2],
237 strcpy(cmd
[n
++], argv
[a
]);
241 calc_dirs_n_files(relh
, home
, relhome
, ctdldir
, 0);
244 signal(SIGINT
, cleanup
);
245 signal(SIGQUIT
, cleanup
);
246 signal(SIGHUP
, cleanup
);
247 signal(SIGTERM
, cleanup
);
249 fprintf(stderr
, "getmail: started (pid=%d) "
252 ctdl_home_directory
);
256 // signal(SIGALRM, nq_cleanup); /* Set up a watchdog type timer in case we hang */
258 np_attach_to_server(UDS
, ctdl_run_dir
);
260 setIPCDeathHook(sendcommand_die
);
262 fprintf(stderr
, "GOTO %s\n", cmd
[0]);
263 CtdlIPCGotoRoom(ipc
, cmd
[0], "", &Room
, cret
);
264 fprintf(stderr
, "%s\n", cret
);
266 MessageToRetrieve
= atol(cmd
[1]);
268 r
= CtdlIPCGetMessages(ipc
, 0, 0, NULL
, &msgarr
, buf
);
269 printf("Messages: ");
270 for (i
= 0; msgarr
[i
] > 0 ; i
++)
272 // printf(" %ld ", msgarr[i]);
273 if (msgarr
[i
] == MessageToRetrieve
)
277 printf("Message %d not found in the above list.", MessageToRetrieve
);
280 CtdlIPCGetSingleMessage(ipc
, MessageToRetrieve
,0,4, &mret
, cret
);
281 fprintf(stderr
, "%s\n", cret
);
282 fprintf(stderr
, "%s: %s\n", "path", mret
->path
);
283 fprintf(stderr
, "%s: %s\n", "author", mret
->author
);
284 fprintf(stderr
, "%s: %s\n", "subject", mret
->subject
);
285 fprintf(stderr
, "%s: %s\n", "email", mret
->email
);
286 fprintf(stderr
, "%s: %s\n", "text", mret
->text
);
288 att
= mret
->attachments
;
295 fprintf(stderr
, "Attachment: [%s] %s\n", att
->number
, att
->filename
);
296 r
= CtdlIPCAttachmentDownload(ipc
, MessageToRetrieve
, att
->number
, &attachment
, NULL
, buf
);
297 printf("----\%s\n----\n", buf
);
303 len
= (size_t)extract_long(buf
, 0);
304 CtdlMakeTempFileName(tmp
, sizeof tmp
);
305 strcat(tmp
, att
->filename
);
306 printf("Saving Attachment to %s", tmp
);
307 save_buffer(attachment
, len
, tmp
);
325 CtdlIPC_chat_send(ipc
, cmd
[4]);
326 CtdlIPC_chat_recv(ipc
, buf
);
327 fprintf(stderr
, "%s\n", buf
);
332 if (!strncasecmp(&buf
[1], "31", 2)) {
333 server_shutting_down
= 1;
337 while (CtdlIPC_chat_recv(ipc
, buf
), strcmp(buf
, "000")) {
339 alarm(5); /* Kick the watchdog timer */
341 } else if (buf
[0] == '4') {
343 if (fgets(buf
, sizeof buf
, stdin
) == NULL
)
345 if (!IsEmptyStr(buf
))
346 if (buf
[strlen(buf
) - 1] == '\n')
347 buf
[strlen(buf
) - 1] = 0;
348 if (!IsEmptyStr(buf
))
349 if (buf
[strlen(buf
) - 1] == '\r')
350 buf
[strlen(buf
) - 1] = 0;
351 if (strcmp(buf
, "000"))
352 CtdlIPC_chat_send(ipc
, buf
);
355 FD_SET(ipc
->sock
, &read_fd
);
356 ret
= select(ipc
->sock
+1, &read_fd
, NULL
, NULL
, &tv
);
359 printf("select failed: %d", err
);
362 if (!(errno
== EINTR
|| errno
== EAGAIN
))
363 printf("select failed: %d", err
);
372 n
= read(ipc
->sock
, rbuf
, SIZ
);
375 fprintf (stderr
, rbuf
);
379 alarm(5); /* Kick the watchdog timer */
380 } while (strcmp(buf
, "000"));
381 CtdlIPC_chat_send(ipc
, "\n");
382 CtdlIPC_chat_send(ipc
, "000");
384 alarm(0); /* Shutdown the watchdog timer */
385 fprintf(stderr
, "sendcommand: processing ended.\n");
387 /* Clean up and log off ... unless the server indicated that the command
388 * we sent is shutting it down, in which case we want to just cut the
389 * connection and exit.
391 if (server_shutting_down
) {
404 void stty_ctdl(int cmd
) {