Revision d2c392d4

View differences:

client/Makefile
1
source=commands.c util.c client_common.c
1
source=commands.c util.c common.c
2 2
root-rel=../
3 3
dir-name=client
4 4

  
5
clients := $(client) birdcl
6

  
7
source-dep := $(source) $(addsuffix .c,$(clients))
8

  
9
subdir: $(addsuffix .o,$(clients))
10

  
5 11
include ../Rules
client/birdc/Makefile
1
source=client.c
2
root-rel=../../
3
dir-name=client/birdc
4

  
5
include ../../Rules
client/birdc/client.c
1
/*
2
 *	BIRD Client
3
 *
4
 *	(c) 1999--2004 Martin Mares <mj@ucw.cz>
5
 *
6
 *	Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

  
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <fcntl.h>
12
#include <unistd.h>
13
#include <termios.h>
14
#include <errno.h>
15
#include <sys/socket.h>
16
#include <sys/un.h>
17
#include <sys/types.h>
18
#include <readline/readline.h>
19
#include <readline/history.h>
20
#include <curses.h>
21

  
22
#include "nest/bird.h"
23
#include "lib/resource.h"
24
#include "lib/string.h"
25
#include "client/client.h"
26
#include "sysdep/unix/unix.h"
27

  
28
static char *opt_list = "s:vr";
29
static int verbose;
30
static char *init_cmd;
31
static int once;
32
static int restricted;
33

  
34
extern char *server_path;
35
extern int server_fd;
36
extern byte server_read_buf[SERVER_READ_BUF_LEN];
37
extern byte *server_read_pos;
38

  
39
extern int input_initialized;
40
extern int input_hidden_end;
41
extern int cstate;
42
extern int nstate;
43

  
44
extern int num_lines, skip_input, interactive;
45

  
46
/*** Parsing of arguments ***/
47

  
48
static void
49
usage(void)
50
{
51
  fprintf(stderr, "Usage: birdc [-s <control-socket>] [-v] [-r]\n");
52
  exit(1);
53
}
54

  
55
static void
56
parse_args(int argc, char **argv)
57
{
58
  int c;
59

  
60
  while ((c = getopt(argc, argv, opt_list)) >= 0)
61
    switch (c)
62
      {
63
      case 's':
64
	server_path = optarg;
65
	break;
66
      case 'v':
67
	verbose++;
68
	break;
69
      case 'r':
70
	restricted = 1;
71
	break;
72
      default:
73
	usage();
74
      }
75

  
76
  /* If some arguments are not options, we take it as commands */
77
  if (optind < argc)
78
    {
79
      char *tmp;
80
      int i;
81
      int len = 0;
82

  
83
      for (i = optind; i < argc; i++)
84
	len += strlen(argv[i]) + 1;
85

  
86
      tmp = init_cmd = malloc(len);
87
      for (i = optind; i < argc; i++)
88
	{
89
	  strcpy(tmp, argv[i]);
90
	  tmp += strlen(tmp);
91
	  *tmp++ = ' ';
92
	}
93
      tmp[-1] = 0;
94

  
95
      once = 1;
96
    }
97
}
98

  
99
/*** Input ***/
100

  
101
/* HACK: libreadline internals we need to access */
102
extern int _rl_vis_botlin;
103
extern void _rl_move_vert(int);
104
extern Function *rl_last_func;
105

  
106
static void
107
add_history_dedup(char *cmd)
108
{
109
  /* Add history line if it differs from the last one */
110
  HIST_ENTRY *he = history_get(history_length);
111
  if (!he || strcmp(he->line, cmd))
112
    add_history(cmd);
113
}
114

  
115
void got_line(char *cmd_buffer)
116
{
117
  char *cmd;
118

  
119
  if (!cmd_buffer)
120
    {
121
      cleanup();
122
      exit(0);
123
    }
124
  if (cmd_buffer[0])
125
    {
126
      cmd = cmd_expand(cmd_buffer);
127
      if (cmd)
128
       {
129
         add_history_dedup(cmd);
130

  
131
         if (!handle_internal_command(cmd))
132
           submit_server_command(cmd);
133

  
134
         free(cmd);
135
       }
136
      else
137
       add_history_dedup(cmd_buffer);
138
    }
139
  free(cmd_buffer);
140
}
141

  
142
void
143
input_start_list(void)			/* Leave the currently edited line and make space for listing */
144
{
145
  _rl_move_vert(_rl_vis_botlin);
146
#ifdef HAVE_RL_CRLF
147
  rl_crlf();
148
#endif
149
}
150

  
151
void
152
input_stop_list(void)			/* Reprint the currently edited line after listing */
153
{
154
  rl_on_new_line();
155
  rl_redisplay();
156
}
157

  
158
static int
159
input_complete(int arg UNUSED, int key UNUSED)
160
{
161
  static int complete_flag;
162
  char buf[256];
163

  
164
  if (rl_last_func != input_complete)
165
    complete_flag = 0;
166
  switch (cmd_complete(rl_line_buffer, rl_point, buf, complete_flag))
167
    {
168
    case 0:
169
      complete_flag = 1;
170
      break;
171
    case 1:
172
      rl_insert_text(buf);
173
      break;
174
    default:
175
      complete_flag = 1;
176
#ifdef HAVE_RL_DING
177
      rl_ding();
178
#endif
179
    }
180
  return 0;
181
}
182

  
183
static int
184
input_help(int arg, int key UNUSED)
185
{
186
  int i, in_string, in_bracket;
187

  
188
  if (arg != 1)
189
    return rl_insert(arg, '?');
190

  
191
  in_string = in_bracket = 0;
192
  for (i = 0; i < rl_point; i++)
193
    {
194
   
195
      if (rl_line_buffer[i] == '"')
196
	in_string = ! in_string;
197
      else if (! in_string)
198
        {
199
	  if (rl_line_buffer[i] == '[')
200
	    in_bracket++;
201
	  else if (rl_line_buffer[i] == ']')
202
	    in_bracket--;
203
        }
204
    }
205

  
206
  /* `?' inside string or path -> insert */
207
  if (in_string || in_bracket)
208
    return rl_insert(1, '?');
209

  
210
  rl_begin_undo_group();		/* HACK: We want to display `?' at point position */
211
  rl_insert_text("?");
212
  rl_redisplay();
213
  rl_end_undo_group();
214
  input_start_list();
215
  cmd_help(rl_line_buffer, rl_point);
216
  rl_undo_command(1, 0);
217
  input_stop_list();
218
  return 0;
219
}
220

  
221
static void
222
input_init(void)
223
{
224
  rl_readline_name = "birdc";
225
  rl_add_defun("bird-complete", input_complete, '\t');
226
  rl_add_defun("bird-help", input_help, '?');
227
  rl_callback_handler_install("bird> ", got_line);
228
  input_initialized = 1;
229
//  readline library does strange things when stdin is nonblocking.
230
//  if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
231
//    die("fcntl: %m");
232
}
233

  
234
static void
235
input_hide(void)
236
{
237
  input_hidden_end = rl_end;
238
  rl_end = 0;
239
  rl_expand_prompt("");
240
  rl_redisplay();
241
}
242

  
243
static void
244
input_reveal(void)
245
{
246
  /* need this, otherwise some lib seems to eat pending output when
247
     the prompt is displayed */
248
  fflush(stdout);
249
  tcdrain(fileno(stdout));
250

  
251
  rl_end = input_hidden_end;
252
  rl_expand_prompt("bird> ");
253
  rl_forced_update_display();
254
}
255

  
256
void
257
update_state(void)
258
{
259
  if (nstate == cstate)
260
    return;
261

  
262
  if (restricted)
263
    {
264
       submit_server_command("restrict");
265
       restricted = 0;
266
       return;
267
    }
268

  
269
  if (init_cmd)
270
    {
271
      /* First transition - client received hello from BIRD
272
	 and there is waiting initial command */
273
      submit_server_command(init_cmd);
274
      init_cmd = NULL;
275
      return;
276
    }
277

  
278
  if (!init_cmd && once)
279
    {
280
      /* Initial command is finished and we want to exit */
281
      cleanup();
282
      exit(0);
283
    }
284

  
285
  if (nstate == STATE_PROMPT)
286
    {
287
      if (input_initialized)
288
	input_reveal();
289
      else
290
	input_init();
291
    }
292

  
293
  if (nstate != STATE_PROMPT)
294
    input_hide();
295

  
296
  cstate = nstate;
297
}
298

  
299
void
300
more(void)
301
{
302
  printf("--More--\015");
303
  fflush(stdout);
304

  
305
 redo:
306
  switch (getchar())
307
    {
308
    case 32:
309
      num_lines = 2;
310
      break;
311
    case 13:
312
      num_lines--;
313
      break;
314
    case 'q':
315
      skip_input = 1;
316
      break;
317
    default:
318
      goto redo;
319
    }
320

  
321
  printf("        \015");
322
  fflush(stdout);
323
}
324

  
325
void cleanup(void)
326
{
327
  if (input_initialized)
328
    {
329
      input_initialized = 0;
330
      input_hide();
331
      rl_callback_handler_remove();
332
    }
333
}
334

  
335

  
336
/*** Communication with server ***/
337

  
338
static fd_set select_fds;
339

  
340
static void
341
select_loop(void)
342
{
343
  int rv;
344
  while (1)
345
    {
346
      FD_ZERO(&select_fds);
347

  
348
      if (cstate != STATE_CMD_USER)
349
	FD_SET(server_fd, &select_fds);
350
      if (cstate != STATE_CMD_SERVER)
351
	FD_SET(0, &select_fds);
352

  
353
      rv = select(server_fd+1, &select_fds, NULL, NULL, NULL);
354
      if (rv < 0)
355
	{
356
	  if (errno == EINTR)
357
	    continue;
358
	  else
359
	    die("select: %m");
360
	}
361

  
362
      if (FD_ISSET(server_fd, &select_fds))
363
	{
364
	  server_read();
365
	  update_state();
366
	}
367

  
368
      if (FD_ISSET(0, &select_fds))
369
	{
370
	  rl_callback_read_char();
371
	  update_state();
372
	}
373
    }
374
}
375

  
376
#define PRINTF(LEN, PARGS...) do { if (!skip_input) len = printf(PARGS); } while(0)
377

  
378
void server_got_reply(char *x)
379
{
380
  int code;
381
  int len = 0;
382

  
383
  if (*x == '+')                        /* Async reply */
384
    PRINTF(len, ">>> %s\n", x+1);
385
  else if (x[0] == ' ')                 /* Continuation */
386
    PRINTF(len, "%s%s\n", verbose ? "     " : "", x+1);
387
  else if (strlen(x) > 4 &&
388
           sscanf(x, "%d", &code) == 1 && code >= 0 && code < 10000 &&
389
           (x[4] == ' ' || x[4] == '-'))
390
    {
391
      if (code)
392
        PRINTF(len, "%s\n", verbose ? x : x+5);
393
      if (x[4] == ' ')
394
      {
395
        nstate = STATE_PROMPT;
396
        skip_input = 0;
397
        return;
398
      }
399
    }
400
  else
401
    PRINTF(len, "??? <%s>\n", x);
402

  
403
  if (skip_input)
404
    return;
405

  
406
  if (interactive && input_initialized && (len > 0))
407
    {
408
      int lns = LINES ? LINES : 25;
409
      int cls = COLS ? COLS : 80;
410
      num_lines += (len + cls - 1) / cls; /* Divide and round up */
411
      if ((num_lines >= lns)  && (cstate == STATE_CMD_SERVER))
412
        more();
413
    }
414
}
415

  
416
int
417
main(int argc, char **argv)
418
{
419
#ifdef HAVE_LIBDMALLOC
420
  if (!getenv("DMALLOC_OPTIONS"))
421
    dmalloc_debug(0x2f03d00);
422
#endif
423

  
424
  interactive = isatty(0);
425
  parse_args(argc, argv);
426
  cmd_build_tree();
427
  server_connect();
428
  select_loop();
429
  return 0;
430
}
client/birdcl/Makefile
1
source=client.c
2
root-rel=../../
3
dir-name=client/birdcl
4

  
5
include ../../Rules
client/birdcl/client.c
1
/*
2
 *	BIRD Client
3
 *
4
 *	(c) 1999--2004 Martin Mares <mj@ucw.cz>
5
 *      (c) 2013 Tomas Hlavacek <tomas.hlavacek@nic.cz>
6
 *
7
 *	Can be freely distributed and used under the terms of the GNU GPL.
8
 */
9

  
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <fcntl.h>
13
#include <unistd.h>
14
#include <termios.h>
15
#include <errno.h>
16
#include <sys/socket.h>
17
#include <sys/un.h>
18
#include <sys/types.h>
19
#include <sys/ioctl.h>
20
#include <signal.h>
21
#include <ctype.h>
22

  
23
#include "nest/bird.h"
24
#include "lib/resource.h"
25
#include "lib/string.h"
26
#include "client/client.h"
27
#include "sysdep/unix/unix.h"
28

  
29
#define INPUT_BUF_LEN 2048
30

  
31
static char *opt_list = "s:vr";
32
static int verbose;
33
static char *init_cmd;
34
static int once;
35

  
36
extern char *server_path;
37
extern int server_fd;
38

  
39
extern int cstate;
40
extern int num_lines, skip_input, interactive;
41

  
42
static int term_lns=25;
43
static int term_cls=80;
44
struct termios tty_save;
45

  
46
void
47
input_start_list(void)
48
{
49
	/* Empty in non-ncurses version. */
50
}
51

  
52
void
53
input_stop_list(void)
54
{
55
	/* Empty in non-ncurses version. */
56
}
57

  
58
/*** Parsing of arguments ***/
59

  
60
static void
61
usage(void)
62
{
63
  fprintf(stderr, "Usage: birdc [-s <control-socket>] [-v] [-r]\n");
64
  exit(1);
65
}
66

  
67
static void
68
parse_args(int argc, char **argv)
69
{
70
  int c;
71

  
72
  while ((c = getopt(argc, argv, opt_list)) >= 0)
73
    switch (c)
74
      {
75
      case 's':
76
	server_path = optarg;
77
	break;
78
      case 'v':
79
	verbose++;
80
	break;
81
      case 'r':
82
	init_cmd = "restrict";
83
	break;
84
      default:
85
	usage();
86
      }
87

  
88
  /* If some arguments are not options, we take it as commands */
89
  if (optind < argc)
90
    {
91
      char *tmp;
92
      int i;
93
      int len = 0;
94

  
95
      if (init_cmd)
96
	usage();
97

  
98
      for (i = optind; i < argc; i++)
99
	len += strlen(argv[i]) + 1;
100

  
101
      tmp = init_cmd = malloc(len);
102
      for (i = optind; i < argc; i++)
103
	{
104
	  strcpy(tmp, argv[i]);
105
	  tmp += strlen(tmp);
106
	  *tmp++ = ' ';
107
	}
108
      tmp[-1] = 0;
109

  
110
      once = 1;
111
    }
112
}
113

  
114
static void
115
run_init_cmd(void)
116
{
117
  if (init_cmd)
118
    {
119
      /* First transition - client received hello from BIRD
120
         and there is waiting initial command */
121
      submit_server_command(init_cmd);
122
      init_cmd = NULL;
123
      return;
124
    }
125

  
126
  if (!init_cmd && once && (cstate == STATE_PROMPT))
127
    {
128
      /* Initial command is finished and we want to exit */
129
      cleanup();
130
      exit(0);
131
    }
132
}
133

  
134
/*** Input ***/
135

  
136
static void
137
got_line(char *cmd_buffer)
138
{
139
  char *cmd;
140

  
141
  if (!cmd_buffer)
142
    {
143
      cleanup();
144
      exit(0);
145
    }
146
  if (cmd_buffer[0])
147
    {
148
      cmd = cmd_expand(cmd_buffer);
149
      if (cmd)
150
	{
151
	  if (!handle_internal_command(cmd))
152
	    submit_server_command(cmd);
153

  
154
	  free(cmd);
155
	}
156
    }
157
  free(cmd_buffer);
158
}
159

  
160
void
161
cleanup(void)
162
{
163
  /* No ncurses -> restore terminal state. */
164
  if (interactive)
165
    if (tcsetattr (0, TCSANOW, &tty_save) != 0)
166
      {
167
        perror("tcsetattr error");
168
        exit(EXIT_FAILURE);
169
      }
170
}
171

  
172
static void
173
print_prompt(void)
174
{
175
  /* No ncurses -> no status to reveal/hide, print prompt manually. */
176
  printf("bird> ");
177
  fflush(stdout);
178
}
179

  
180

  
181
static int lastnb(char *str)
182
{
183
  int i;
184
  for (i=strlen(str)-1; i>0; i--)
185
    {
186
      if(!isblank(str[i]))
187
        return i;
188
    }
189

  
190
  return 0;
191
}
192

  
193
static void
194
term_read(void)
195
{
196
  char *buf = malloc(INPUT_BUF_LEN);
197

  
198
  if (fgets(buf, INPUT_BUF_LEN, stdin) == NULL) {
199
    free(buf);
200
    exit(0);
201
  }
202

  
203
  if (buf[strlen(buf)-1] != '\n')
204
    {
205
      printf("Input too long.\n");
206
      free(buf);
207
      return;
208
    }
209

  
210
  if (strlen(buf) <= 0)
211
    {
212
      free(buf);
213
      return;
214
    }
215

  
216
  buf[strlen(buf)-1] = '\0';
217

  
218
  if (!interactive)
219
    {
220
      print_prompt();
221
      printf("%s\n",buf);
222
    }
223

  
224
  if (buf[lastnb(buf)] == '?')
225
    {
226
      printf("\n");
227
      cmd_help(buf, strlen(buf));
228
      free(buf);
229
      return;
230
    }
231

  
232
  if (strlen(buf) > 0)
233
    {
234
      got_line(buf); /* buf is free()-ed inside */
235
    }
236
  else
237
    {
238
      free(buf); /* no command, only newline -> no-op */
239
      return;
240
    }
241

  
242
}
243

  
244
/*** Communication with server ***/
245

  
246
void
247
more(void)
248
{
249
  struct termios tty;
250

  
251
  printf("--More--\015");
252
  fflush(stdout);
253

  
254
  if (tcgetattr(0, &tty) != 0)
255
    {
256
      perror("tcgetattr error");
257
      exit(EXIT_FAILURE);
258
    }
259
  tty.c_lflag &= (~ECHO);
260
  tty.c_lflag &= (~ICANON);
261
  if (tcsetattr (0, TCSANOW, &tty) != 0)
262
    {
263
      perror("tcsetattr error");
264
      exit(EXIT_FAILURE);
265
    }
266

  
267
 redo:
268
  switch (getchar())
269
    {
270
    case 32:
271
      num_lines = 2;
272
      break;
273
    case 13:
274
      num_lines--;
275
      break;
276
    case '\n':
277
      num_lines--;
278
      break;
279
    case 'q':
280
      skip_input = 1;
281
      break;
282
    default:
283
      goto redo;
284
    }
285

  
286
  tty.c_lflag |= ECHO;
287
  tty.c_lflag |= ICANON;
288
  if (tcsetattr (0, TCSANOW, &tty) != 0)
289
    {
290
      perror("tcsetattr error");
291
      exit(EXIT_FAILURE);
292
    }
293

  
294
  printf("        \015");
295
  fflush(stdout);
296
}
297

  
298
static void
299
get_term_size(void)
300
{
301
  struct winsize tws;
302
  if (ioctl(0, TIOCGWINSZ, &tws) == 0)
303
    {
304
      term_lns = tws.ws_row;
305
      term_cls = tws.ws_col;
306
    }
307
  else
308
    {
309
       term_lns = 25;
310
       term_cls = 80;
311
    }
312
}
313

  
314
#define PRINTF(LEN, PARGS...) do { if (!skip_input) len = printf(PARGS); } while(0)
315

  
316
void
317
server_got_reply(char *x)
318
{
319
  int code;
320
  int len = 0;
321

  
322
  if (*x == '+')                        /* Async reply */
323
    PRINTF(len, ">>> %s\n", x+1);
324
  else if (x[0] == ' ')                 /* Continuation */
325
    PRINTF(len, "%s%s\n", verbose ? "     " : "", x+1);
326
  else if (strlen(x) > 4 &&
327
           sscanf(x, "%d", &code) == 1 && code >= 0 && code < 10000 &&
328
           (x[4] == ' ' || x[4] == '-'))
329
    {
330
      if (code)
331
        PRINTF(len, "%s\n", verbose ? x : x+5);
332

  
333
      if (x[4] == ' ')
334
      {
335
        cstate = STATE_PROMPT;
336
        skip_input = 0;
337
        return;
338
      }
339
    }
340
  else
341
    PRINTF(len, "??? <%s>\n", x);
342

  
343
  if (skip_input)
344
    return;
345

  
346
  if (interactive && (len > 0))
347
    {
348
      num_lines += (len + term_cls - 1) / term_cls; /* Divide and round up */
349
      if (num_lines >= term_lns)
350
        more();
351
    }
352
}
353

  
354
static fd_set select_fds;
355

  
356
static void
357
select_loop(void)
358
{
359
  int rv;
360

  
361
  while (1)
362
    {
363
      FD_ZERO(&select_fds);
364

  
365
      if (cstate != STATE_CMD_USER)
366
        FD_SET(server_fd, &select_fds);
367

  
368
      if (cstate != STATE_CMD_SERVER)
369
        {
370
          FD_SET(0, &select_fds);
371
          if (interactive)
372
            print_prompt();
373
        }
374

  
375
      rv = select(server_fd+1, &select_fds, NULL, NULL, NULL);
376
      if (rv < 0)
377
	{
378
	  if (errno == EINTR)
379
	    continue;
380
	  else
381
	    die("select: %m");
382
	}
383

  
384
      if (FD_ISSET(server_fd, &select_fds))
385
        {
386
	  server_read();
387
          run_init_cmd();
388
        }
389

  
390
      if (FD_ISSET(0, &select_fds))
391
        term_read();
392
    }
393
}
394

  
395
static void
396
sig_handler(int signal)
397
{
398
  cleanup();
399
  exit(0);
400
}
401

  
402
int
403
main(int argc, char **argv)
404
{
405
  interactive = isatty(fileno(stdin));
406
  if (interactive)
407
    {
408
      if (signal(SIGINT, sig_handler) == SIG_IGN)
409
        signal(SIGINT, SIG_IGN);
410
      if (signal(SIGHUP, sig_handler) == SIG_IGN)
411
        signal(SIGHUP, SIG_IGN);
412
      if (signal(SIGTERM, sig_handler) == SIG_IGN)
413
        signal(SIGTERM, SIG_IGN);
414

  
415
      get_term_size();
416

  
417
      if (tcgetattr(0, &tty_save) != 0)
418
        {
419
          perror("tcgetattr error");
420
          return(EXIT_FAILURE);
421
        }
422
    }
423

  
424
  parse_args(argc, argv);
425
  cmd_build_tree();
426
  server_connect();
427
  select_loop();
428
  return 0;
429
}
client/client.h
20 20
int cmd_complete(char *cmd, int len, char *buf, int again);
21 21
char *cmd_expand(char *cmd);
22 22

  
23
/* client_common.c */
23
/* common.c */
24 24

  
25 25
#define STATE_PROMPT           0
26 26
#define STATE_CMD_SERVER       1
client/client_common.c
1
/*
2
 *	BIRD Client
3
 *
4
 *	(c) 1999--2004 Martin Mares <mj@ucw.cz>
5
 *	(c) 2013 Tomas Hlavacek <tmshlvck@gmail.com>
6
 *
7
 *	Can be freely distributed and used under the terms of the GNU GPL.
8
 */
9

  
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <fcntl.h>
13
#include <unistd.h>
14
#include <errno.h>
15
#include <sys/socket.h>
16
#include <sys/un.h>
17
#include <sys/types.h>
18

  
19
#include "nest/bird.h"
20
#include "lib/resource.h"
21
#include "lib/string.h"
22
#include "client/client.h"
23
#include "sysdep/unix/unix.h"
24

  
25
char *server_path = PATH_CONTROL_SOCKET;
26
int server_fd;
27
byte server_read_buf[SERVER_READ_BUF_LEN];
28
byte *server_read_pos = server_read_buf;
29

  
30
int input_initialized;
31
int input_hidden_end;
32
int cstate = STATE_CMD_SERVER;
33
int nstate = STATE_CMD_SERVER;
34

  
35
int num_lines, skip_input, interactive;
36

  
37

  
38
/*** Input ***/
39

  
40
int
41
handle_internal_command(char *cmd)
42
{
43
  if (!strncmp(cmd, "exit", 4) || !strncmp(cmd, "quit", 4))
44
    {
45
      cleanup();
46
      exit(0);
47
    }
48
  if (!strncmp(cmd, "help", 4))
49
    {
50
      puts("Press `?' for context sensitive help.");
51
      return 1;
52
    }
53
  return 0;
54
}
55

  
56
void
57
submit_server_command(char *cmd)
58
{
59
  server_send(cmd);
60
  nstate = STATE_CMD_SERVER;
61
  num_lines = 2;
62
}
63

  
64
/*** Communication with server ***/
65

  
66
void
67
server_connect(void)
68
{
69
  struct sockaddr_un sa;
70

  
71
  server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
72
  if (server_fd < 0)
73
    die("Cannot create socket: %m");
74

  
75
  if (strlen(server_path) >= sizeof(sa.sun_path))
76
    die("server_connect: path too long");
77

  
78
  bzero(&sa, sizeof(sa));
79
  sa.sun_family = AF_UNIX;
80
  strcpy(sa.sun_path, server_path);
81
  if (connect(server_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) < 0)
82
    die("Unable to connect to server control socket (%s): %m", server_path);
83
  if (fcntl(server_fd, F_SETFL, O_NONBLOCK) < 0)
84
    die("fcntl: %m");
85
}
86

  
87
void
88
server_read(void)
89
{
90
  int c;
91
  byte *start, *p;
92

  
93
 redo:
94
  c = read(server_fd, server_read_pos, server_read_buf + sizeof(server_read_buf) - server_read_pos);
95
  if (!c)
96
    die("Connection closed by server.");
97
  if (c < 0)
98
    {
99
      if (errno == EINTR)
100
	goto redo;
101
      else
102
	die("Server read error: %m");
103
    }
104

  
105
  start = server_read_buf;
106
  p = server_read_pos;
107
  server_read_pos += c;
108
  while (p < server_read_pos)
109
    if (*p++ == '\n')
110
      {
111
	p[-1] = 0;
112
	server_got_reply(start);
113
	start = p;
114
      }
115
  if (start != server_read_buf)
116
    {
117
      int l = server_read_pos - start;
118
      memmove(server_read_buf, start, l);
119
      server_read_pos = server_read_buf + l;
120
    }
121
  else if (server_read_pos == server_read_buf + sizeof(server_read_buf))
122
    {
123
      strcpy(server_read_buf, "?<too-long>");
124
      server_read_pos = server_read_buf + 11;
125
    }
126
}
127

  
128
void
129
wait_for_write(int fd)
130
{
131
  while (1)
132
    {
133
      int rv;
134
      fd_set set;
135
      FD_ZERO(&set);
136
      FD_SET(fd, &set);
137

  
138
      rv = select(fd+1, NULL, &set, NULL, NULL);
139
      if (rv < 0)
140
	{
141
	  if (errno == EINTR)
142
	    continue;
143
	  else
144
	    die("select: %m");
145
	}
146

  
147
      if (FD_ISSET(server_fd, &set))
148
	return;
149
    }
150
}
151

  
152
void
153
server_send(char *cmd)
154
{
155
  int l = strlen(cmd);
156
  byte *z = alloca(l + 1);
157

  
158
  memcpy(z, cmd, l);
159
  z[l++] = '\n';
160
  while (l)
161
    {
162
      int cnt = write(server_fd, z, l);
163

  
164
      if (cnt < 0)
165
	{
166
	  if (errno == EAGAIN)
167
	    wait_for_write(server_fd);
168
	  else if (errno == EINTR)
169
	    continue;
170
	  else
171
	    die("Server write error: %m");
172
	}
173
      else
174
	{
175
	  l -= cnt;
176
	  z += cnt;
177
	}
178
    }
179
}
tools/Makefile.in
3 3

  
4 4
include Rules
5 5

  
6
.PHONY: all daemon birdci birdcl subdir depend clean distclean tags docs userdocs progdocs
6
.PHONY: all daemon birdc birdcl subdir depend clean distclean tags docs userdocs progdocs
7 7

  
8 8
all: sysdep/paths.h .dep-stamp subdir daemon birdcl @CLIENT@
9 9

  
......
17 17

  
18 18
$(bird-dep): sysdep/paths.h .dep-stamp subdir
19 19

  
20
birdc-dep := client/birdc/all.o client/all.o lib/birdlib.a
20
birdc-dep := client/birdc.o client/all.o lib/birdlib.a
21 21

  
22 22
$(birdc-dep): sysdep/paths.h .dep-stamp subdir
23 23

  
24
birdcl-dep := client/birdcl/all.o client/all.o lib/birdlib.a
24
birdcl-dep := client/birdcl.o client/all.o lib/birdlib.a
25 25

  
26 26
$(birdcl-dep): sysdep/paths.h .dep-stamp subdir
27 27

  
28 28

  
29
export client := @CLIENT@
30

  
29 31
depend: sysdep/paths.h .dir-stamp
30 32
	set -e ; for a in $(dynamic-dirs) ; do $(MAKE) -C $$a $@ ; done
31
	set -e ; for a in $(static-dirs) $(birdcl-dirs) $(birdc-dirs) ; do $(MAKE) -C $$a -f $(srcdir_abs)/$$a/Makefile $@ ; done
33
	set -e ; for a in $(static-dirs) $(client-dirs) ; do $(MAKE) -C $$a -f $(srcdir_abs)/$$a/Makefile $@ ; done
32 34

  
33 35
subdir: sysdep/paths.h .dir-stamp .dep-stamp
34 36
	set -e ; for a in $(dynamic-dirs) ; do $(MAKE) -C $$a $@ ; done
35
	set -e ; for a in $(static-dirs) $(birdcl-dirs) $(birdc-dirs) ; do $(MAKE) -C $$a -f $(srcdir_abs)/$$a/Makefile $@ ; done
37
	set -e ; for a in $(static-dirs) $(client-dirs) ; do $(MAKE) -C $$a -f $(srcdir_abs)/$$a/Makefile $@ ; done
36 38

  
37 39
$(exedir)/bird: $(bird-dep)
38 40
	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
......
44 46
	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
45 47

  
46 48
.dir-stamp: sysdep/paths.h
47
	mkdir -p $(static-dirs) $(birdcl-dirs) $(birdc-dirs) $(doc-dirs)
49
	mkdir -p $(static-dirs) $(client-dirs) $(doc-dirs)
48 50
	touch .dir-stamp
49 51

  
50 52
.dep-stamp:
tools/Rules.in
11 11
static-dir-paths := $(addprefix $(srcdir)/,$(static-dirs))
12 12
dynamic-dirs := lib conf
13 13
dynamic-dir-paths := $(dynamic-dirs)
14
birdc-dirs := client client/@CLIENT@
15
birdc-dir-paths := $(birdc-dirs)
16
birdcl-dirs := client client/birdcl
17
birdcl-dir-paths := $(birdcl-dirs)
14
client-dirs := client
15
client-dir-paths := $(client-dirs)
18 16
doc-dirs := doc
19 17
doc-dir-paths := $(doc-dirs)
20 18

  
21
all-dirs:=$(static-dirs) $(dynamic-dirs) $(birdc-dirs) $(doc-dirs)
19
all-dirs:=$(static-dirs) $(dynamic-dirs) $(client-dirs) $(doc-dirs)
22 20
clean-dirs:=$(all-dirs) proto sysdep
23 21

  
24 22
CPPFLAGS=-I$(root-rel) -I$(srcdir) @CPPFLAGS@
......
77 75
%.o: $(src-path)%.c
78 76
	$(CC) $(CFLAGS) -o $@ -c $<
79 77

  
78
ifndef source-dep
79
source-dep := $(source)
80
endif
81

  
80 82
depend:
81
	$(CC) $(CPPFLAGS) -MM $(addprefix $(src-path),$(source)) >depend
83
	$(CC) $(CPPFLAGS) -MM $(addprefix $(src-path),$(source-dep)) >depend
82 84

  
83 85
ifneq ($(wildcard depend),)
84 86
include depend

Also available in: Unified diff