1 /* $Id: command.c,v 1.2 2006-12-20 22:19:35 adam Exp $ */
4 #include <sys/socket.h>
13 #include <yaz/yaz-util.h>
14 #include <yaz/comstack.h>
22 extern IOCHAN channel_list;
24 struct command_session {
31 struct session *psession;
34 void command_destroy(struct command_session *s);
35 void command_prompt(struct command_session *s);
36 void command_puts(struct command_session *s, const char *buf);
38 static int cmd_quit(struct command_session *s, char **argv, int argc)
40 IOCHAN i = s->channel;
41 close(iochan_getfd(i));
48 static int cmd_load(struct command_session *s, char **argv, int argc)
51 command_puts(s, "Usage: load filename\n");
53 if (load_targets(s->psession, argv[1]) < 0)
54 command_puts(s, "Failed to open file\n");
59 static int cmd_search(struct command_session *s, char **argv, int argc)
63 command_puts(s, "Usage: search word\n");
66 search(s->psession, argv[1]);
70 static int cmd_hitsbytarget(struct command_session *s, char **argv, int argc)
75 struct hitsbytarget *ht = hitsbytarget(s->psession, &count);
76 for (i = 0; i < count; i++)
80 sprintf(buf, "%s: %d (%d records, diag=%d, state=%s conn=%d)\n", ht[i].id, ht[i].hits,
81 ht[i].records, ht[i].diagnostic, ht[i].state, ht[i].connected);
87 static int cmd_show(struct command_session *s, char **argv, int argc)
93 NMEM nmem_show = nmem_create();
98 recs = show(s->psession, 0, &num, &merged, &total, nmem_show);
100 for (i = 0; i < num; i++)
103 struct record *cnode;
104 struct record *r = recs[i];
106 command_puts(s, r->merge_key);
107 for (rc = 1, cnode = r->next_cluster; cnode; cnode = cnode->next_cluster, rc++)
112 sprintf(buf, " (%d records)", rc);
113 command_puts(s, buf);
115 command_puts(s, "\n");
117 nmem_destroy(nmem_show);
121 static int cmd_stat(struct command_session *s, char **argv, int argc)
124 struct statistics stat;
126 statistics(s->psession, &stat);
127 sprintf(buf, "Number of connections: %d\n", stat.num_clients);
128 command_puts(s, buf);
129 if (stat.num_no_connection)
131 sprintf(buf, "#No_connection: %d\n", stat.num_no_connection);
132 command_puts(s, buf);
134 if (stat.num_connecting)
136 sprintf(buf, "#Connecting: %d\n", stat.num_connecting);
137 command_puts(s, buf);
139 if (stat.num_initializing)
141 sprintf(buf, "#Initializing: %d\n", stat.num_initializing);
142 command_puts(s, buf);
144 if (stat.num_searching)
146 sprintf(buf, "#Searching: %d\n", stat.num_searching);
147 command_puts(s, buf);
149 if (stat.num_presenting)
151 sprintf(buf, "#Ppresenting: %d\n", stat.num_presenting);
152 command_puts(s, buf);
156 sprintf(buf, "#Idle: %d\n", stat.num_idle);
157 command_puts(s, buf);
161 sprintf(buf, "#Failed: %d\n", stat.num_failed);
162 command_puts(s, buf);
166 sprintf(buf, "#Error: %d\n", stat.num_error);
167 command_puts(s, buf);
174 int (*fun)(struct command_session *s, char *argv[], int argc);
180 {"find", cmd_search},
181 {"ht", cmd_hitsbytarget},
187 void command_command(struct command_session *s, char *command)
203 while (*p && !isspace(*p))
210 for (i = 0; cmd_array[i].cmd; i++)
212 if (!strcmp(cmd_array[i].cmd, argv[0])) {
213 res = (cmd_array[i].fun)(s, argv, argc);
219 command_puts(s, "Unknown command.\n");
232 static void command_io(IOCHAN i, int event)
236 struct command_session *s;
238 s = iochan_getdata(i);
244 res = read(iochan_getfd(i), buf, 1024);
247 yaz_log(YLOG_WARN|YLOG_ERRNO, "read command");
248 close(iochan_getfd(i));
253 if (!index(buf, '\n')) {
254 yaz_log(YLOG_WARN|YLOG_ERRNO, "Did not receive complete command");
255 close(iochan_getfd(i));
261 command_command(s, buf);
264 if (!s->outbuflen || s->outbufwrit < 0)
266 yaz_log(YLOG_WARN, "Called with outevent but no data");
267 iochan_clearflag(i, EVENT_OUTPUT);
271 res = write(iochan_getfd(i), s->outbuf + s->outbufwrit, s->outbuflen -
274 yaz_log(YLOG_WARN|YLOG_ERRNO, "write command");
275 close(iochan_getfd(i));
281 s->outbufwrit += res;
282 if (s->outbufwrit >= s->outbuflen)
284 s->outbuflen = s->outbufwrit = 0;
285 iochan_clearflag(i, EVENT_OUTPUT);
291 yaz_log(YLOG_WARN, "Bad voodoo on socket");
295 void command_puts(struct command_session *s, const char *buf)
297 int len = strlen(buf);
298 memcpy(s->outbuf + s->outbuflen, buf, len);
300 iochan_setflag(s->channel, EVENT_OUTPUT);
303 void command_prompt(struct command_session *s)
305 command_puts(s, "Pazpar2> ");
309 /* Accept a new command connection */
310 static void command_accept(IOCHAN i, int event)
312 struct sockaddr_in addr;
313 int fd = iochan_getfd(i);
317 struct command_session *ses;
321 if ((s = accept(fd, (struct sockaddr *) &addr, &len)) < 0)
323 yaz_log(YLOG_WARN|YLOG_ERRNO, "accept");
326 if ((flags = fcntl(s, F_GETFL, 0)) < 0)
327 yaz_log(YLOG_FATAL|YLOG_ERRNO, "fcntl");
328 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
329 yaz_log(YLOG_FATAL|YLOG_ERRNO, "fcntl2");
331 yaz_log(YLOG_LOG, "New command connection");
332 c = iochan_create(s, command_io, EVENT_INPUT | EVENT_EXCEPT);
334 ses = xmalloc(sizeof(*ses));
335 ses->outbuf = xmalloc(50000);
339 ses->psession = new_session();
340 iochan_setdata(c, ses);
342 command_puts(ses, "Welcome to pazpar2\n\n");
345 c->next = channel_list;
349 void command_destroy(struct command_session *s) {
354 /* Create a command-channel listener */
355 void command_init(int port)
360 struct sockaddr_in myaddr;
363 yaz_log(YLOG_LOG, "Command port is %d", port);
364 if (!(p = getprotobyname("tcp"))) {
367 if ((l = socket(PF_INET, SOCK_STREAM, p->p_proto)) < 0)
368 yaz_log(YLOG_FATAL|YLOG_ERRNO, "socket");
369 if (setsockopt(l, SOL_SOCKET, SO_REUSEADDR, (char*)
370 &one, sizeof(one)) < 0)
373 bzero(&myaddr, sizeof myaddr);
374 myaddr.sin_family = AF_INET;
375 myaddr.sin_addr.s_addr = INADDR_ANY;
376 myaddr.sin_port = htons(port);
377 if (bind(l, (struct sockaddr *) &myaddr, sizeof myaddr) < 0)
378 yaz_log(YLOG_FATAL|YLOG_ERRNO, "bind");
379 if (listen(l, SOMAXCONN) < 0)
380 yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen");
382 c = iochan_create(l, command_accept, EVENT_INPUT | EVENT_EXCEPT);
383 //iochan_setdata(c, &l);
384 c->next = channel_list;
391 * indent-tabs-mode: nil
393 * vim: shiftwidth=4 tabstop=8 expandtab