]>
git.ipfire.org Git - thirdparty/bird.git/blob - client/client.c
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
14 #include <sys/socket.h>
17 #include <sys/types.h>
18 #include <readline/readline.h>
19 #include <readline/history.h>
21 #include "nest/bird.h"
22 #include "lib/resource.h"
23 #include "lib/string.h"
24 #include "client/client.h"
25 #include "sysdep/unix/unix.h"
27 static char *opt_list
= "s:v";
30 static char *server_path
= PATH_CONTROL_SOCKET
;
32 static int server_reply
;
33 static byte server_read_buf
[4096];
34 static byte
*server_read_pos
= server_read_buf
;
36 static int input_initialized
;
37 static int input_hidden
;
38 static int input_hidden_end
;
40 /*** Parsing of arguments ***/
45 fprintf(stderr
, "Usage: birdc [-s <control-socket>] [-v]\n");
50 parse_args(int argc
, char **argv
)
54 while ((c
= getopt(argc
, argv
, opt_list
)) >= 0)
72 static void server_send(char *);
73 static void select_loop(int);
75 /* HACK: libreadline internals we need to access */
76 extern int _rl_vis_botlin
;
77 extern void _rl_move_vert(int);
78 extern Function
*rl_last_func
;
81 handle_internal_command(char *cmd
)
83 if (!strncmp(cmd
, "exit", 4) || !strncmp(cmd
, "quit", 4))
88 if (!strncmp(cmd
, "help", 4))
90 puts("Press `?' for context sensitive help.");
97 got_line(char *cmd_buffer
)
108 cmd
= cmd_expand(cmd_buffer
);
112 if (!handle_internal_command(cmd
))
122 add_history(cmd_buffer
);
128 input_start_list(void) /* Leave the currently edited line and make space for listing */
130 _rl_move_vert(_rl_vis_botlin
);
135 input_stop_list(void) /* Reprint the currently edited line after listing */
142 input_complete(int arg
, int key
)
144 static int complete_flag
;
147 if (rl_last_func
!= input_complete
)
149 switch (cmd_complete(rl_line_buffer
, rl_point
, buf
, complete_flag
))
165 input_help(int arg
, int key
)
170 return rl_insert(arg
, '?');
173 if (rl_line_buffer
[i
++] == '"')
176 if (i
>= rl_point
) /* `?' inside quoted string -> insert */
177 return rl_insert(1, '?');
179 while (rl_line_buffer
[i
++] != '"');
181 rl_begin_undo_group(); /* HACK: We want to display `?' at point position */
186 cmd_help(rl_line_buffer
, rl_point
);
187 rl_undo_command(1, 0);
195 rl_readline_name
= "birdc";
196 rl_add_defun("bird-complete", input_complete
, '\t');
197 rl_add_defun("bird-help", input_help
, '?');
198 rl_callback_handler_install("bird> ", got_line
);
199 input_initialized
= 1;
200 if (fcntl(0, F_SETFL
, O_NONBLOCK
) < 0)
211 input_hidden_end
= rl_end
;
213 rl_expand_prompt("");
222 if (input_hidden
<= 0)
224 rl_end
= input_hidden_end
;
225 rl_expand_prompt("bird> ");
226 rl_forced_update_display();
233 if (input_initialized
)
235 input_initialized
= 0;
237 rl_callback_handler_remove();
241 /*** Communication with server ***/
246 struct sockaddr_un sa
;
248 server_fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
250 die("Cannot create socket: %m");
251 bzero(&sa
, sizeof(sa
));
252 sa
.sun_family
= AF_UNIX
;
253 strcpy(sa
.sun_path
, server_path
);
254 if (connect(server_fd
, (struct sockaddr
*) &sa
, SUN_LEN(&sa
)) < 0)
255 die("Unable to connect to server control socket (%s): %m", server_path
);
256 if (fcntl(server_fd
, F_SETFL
, O_NONBLOCK
) < 0)
261 server_got_reply(char *x
)
266 if (*x
== '+') /* Async reply */
267 printf(">>> %s\n", x
+1);
268 else if (x
[0] == ' ') /* Continuation */
269 printf("%s%s\n", verbose
? " " : "", x
+1);
270 else if (strlen(x
) > 4 &&
271 sscanf(x
, "%d", &code
) == 1 && code
>= 0 && code
< 10000 &&
272 (x
[4] == ' ' || x
[4] == '-'))
275 printf("%s\n", verbose
? x
: x
+5);
280 printf("??? <%s>\n", x
);
289 c
= read(server_fd
, server_read_pos
, server_read_buf
+ sizeof(server_read_buf
) - server_read_pos
);
291 die("Connection closed by server.");
293 die("Server read error: %m");
294 start
= server_read_buf
;
296 server_read_pos
+= c
;
297 while (p
< server_read_pos
)
301 server_got_reply(start
);
304 if (start
!= server_read_buf
)
306 int l
= server_read_pos
- start
;
307 memmove(server_read_buf
, start
, l
);
308 server_read_pos
= server_read_buf
+ l
;
310 else if (server_read_pos
== server_read_buf
+ sizeof(server_read_buf
))
312 strcpy(server_read_buf
, "?<too-long>");
313 server_read_pos
= server_read_buf
+ 11;
317 static fd_set select_fds
;
320 select_loop(int mode
)
323 while (mode
|| server_reply
< 0)
325 FD_ZERO(&select_fds
);
326 FD_SET(server_fd
, &select_fds
);
328 FD_SET(0, &select_fds
);
329 select(server_fd
+1, &select_fds
, NULL
, NULL
, NULL
);
330 if (FD_ISSET(server_fd
, &select_fds
))
336 if (FD_ISSET(0, &select_fds
))
337 rl_callback_read_char();
343 server_send(char *cmd
)
346 byte
*z
= alloca(l
+ 1);
352 int cnt
= write(server_fd
, z
, l
);
355 if (errno
== -EAGAIN
)
361 FD_SET(server_fd
, &set
);
362 select(server_fd
+1, NULL
, &set
, NULL
, NULL
);
364 while (!FD_ISSET(server_fd
, &set
));
367 die("Server write error: %m");
378 main(int argc
, char **argv
)
380 #ifdef HAVE_LIBDMALLOC
381 if (!getenv("DMALLOC_OPTIONS"))
382 dmalloc_debug(0x2f03d00);
385 parse_args(argc
, argv
);