1
2
3
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
85
86
87
88
89
90
91
92
93
100
101
102
103
104
105
107
108
109
110
111
112
113
114
120
121
122
123
124
125
126
127
128
134
135
136
137
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
231
232
233
234
235
236
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
265
266
267
273
274
275
277
278
279
280
281
282
283
284
285
286
287
293
294
295
296
297
298
299
300
301
302
303
304
311
312
313
314
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
440
441
442
443
444
445
446
447
448
468
469
470
471
477
478
479
480
481
482
483
484
485
486
487
488
509
510
511
516
517
518
519
520
521
522
524
525
529
530
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
574
575
576
577
578
579
580
581
582
583
584
585
586
587
593
594
595
596
597
598
599
600
601
602
612
613
614
615
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
638
639
640
650
651
652
653
660
661
662
663
664
669
670
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
694
695
696
697
698
699
700
701
702
703
704
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
731
732
733
734
738
739
740
741
742
743
744
751
752
756
757
758
759
760
761
762
763
764
765
766
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
803
804
805
812
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
865
866
/* ... */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "server.h"
#include <helper/time_support.h>
#include <target/target.h>
#include <target/target_request.h>
#include <target/openrisc/jsp_server.h>
#include "openocd.h"
#include "tcl_server.h"
#include "telnet_server.h"
#include "ipdbg.h"
#include <signal.h>
10 includes
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifndef _WIN32
#include <netinet/tcp.h>
#endif
static struct service *services;
enum shutdown_reason {
CONTINUE_MAIN_LOOP,
SHUTDOWN_REQUESTED,
SHUTDOWN_WITH_ERROR_CODE,
SHUTDOWN_WITH_SIGNAL_CODE
...};
static enum shutdown_reason shutdown_openocd = CONTINUE_MAIN_LOOP;
static int last_signal;
static int polling_period = 100;
static char *bindto_name;
static int add_connection(struct service *service, struct command_context *cmd_ctx)
{
socklen_t address_size;
struct connection *c, **p;
int retval;
int flag = 1;
c = malloc(sizeof(struct connection));
c->fd = -1;
c->fd_out = -1;
memset(&c->sin, 0, sizeof(c->sin));
c->cmd_ctx = copy_command_context(cmd_ctx);
c->service = service;
c->input_pending = false;
c->priv = NULL;
c->next = NULL;
if (service->type == CONNECTION_TCP) {
address_size = sizeof(c->sin);
c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
c->fd_out = c->fd;
/* ... */
setsockopt(c->fd,
IPPROTO_TCP,
TCP_NODELAY,
(char *)&flag,
sizeof(int));
LOG_INFO("accepting '%s' connection on tcp/%s", service->name, service->port);
retval = service->new_connection(c);
if (retval != ERROR_OK) {
close_socket(c->fd);
LOG_ERROR("attempted '%s' connection rejected", service->name);
command_done(c->cmd_ctx);
free(c);
return retval;
}if (retval != ERROR_OK) { ... }
}if (service->type == CONNECTION_TCP) { ... } else if (service->type == CONNECTION_STDINOUT) {
c->fd = service->fd;
c->fd_out = fileno(stdout);
#ifdef _WIN32
SetConsoleCtrlHandler(NULL, TRUE);/* ... */
#endif
service->fd = -1;
LOG_INFO("accepting '%s' connection from pipe", service->name);
retval = service->new_connection(c);
if (retval != ERROR_OK) {
LOG_ERROR("attempted '%s' connection rejected", service->name);
command_done(c->cmd_ctx);
free(c);
return retval;
}if (retval != ERROR_OK) { ... }
}else if (service->type == CONNECTION_STDINOUT) { ... } else if (service->type == CONNECTION_PIPE) {
c->fd = service->fd;
service->fd = -1;
char *out_file = alloc_printf("%so", service->port);
c->fd_out = open(out_file, O_WRONLY);
free(out_file);
if (c->fd_out == -1) {
LOG_ERROR("could not open %s", service->port);
command_done(c->cmd_ctx);
free(c);
return ERROR_FAIL;
}if (c->fd_out == -1) { ... }
LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
retval = service->new_connection(c);
if (retval != ERROR_OK) {
LOG_ERROR("attempted '%s' connection rejected", service->name);
command_done(c->cmd_ctx);
free(c);
return retval;
}if (retval != ERROR_OK) { ... }
}else if (service->type == CONNECTION_PIPE) { ... }
for (p = &service->connections; *p; p = &(*p)->next)
;
*p = c;
if (service->max_connections != CONNECTION_LIMIT_UNLIMITED)
service->max_connections--;
return ERROR_OK;
}{ ... }
static int remove_connection(struct service *service, struct connection *connection)
{
struct connection **p = &service->connections;
struct connection *c;
while ((c = *p)) {
if (c->fd == connection->fd) {
service->connection_closed(c);
if (service->type == CONNECTION_TCP)
close_socket(c->fd);
else if (service->type == CONNECTION_PIPE) {
c->service->fd = c->fd;
}else if (service->type == CONNECTION_PIPE) { ... }
command_done(c->cmd_ctx);
*p = c->next;
free(c);
if (service->max_connections != CONNECTION_LIMIT_UNLIMITED)
service->max_connections++;
break;
}if (c->fd == connection->fd) { ... }
p = &(*p)->next;
}while ((c = *p)) { ... }
return ERROR_OK;
}{ ... }
static void free_service(struct service *c)
{
free(c->name);
free(c->port);
free(c);
}{ ... }
int add_service(const struct service_driver *driver, const char *port,
int max_connections, void *priv)
{
struct service *c, **p;
struct hostent *hp;
int so_reuseaddr_option = 1;
c = malloc(sizeof(struct service));
c->name = strdup(driver->name);
c->port = strdup(port);
c->max_connections = 1;
c->fd = -1;
c->connections = NULL;
c->new_connection_during_keep_alive = driver->new_connection_during_keep_alive_handler;
c->new_connection = driver->new_connection_handler;
c->input = driver->input_handler;
c->connection_closed = driver->connection_closed_handler;
c->keep_client_alive = driver->keep_client_alive_handler;
c->priv = priv;
c->next = NULL;
long portnumber;
if (strcmp(c->port, "pipe") == 0)
c->type = CONNECTION_STDINOUT;
else {
char *end;
portnumber = strtol(c->port, &end, 0);
if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) {
c->portnumber = portnumber;
c->type = CONNECTION_TCP;
}if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) { ... } else
c->type = CONNECTION_PIPE;
}else { ... }
if (c->type == CONNECTION_TCP) {
c->max_connections = max_connections;
c->fd = socket(AF_INET, SOCK_STREAM, 0);
if (c->fd == -1) {
LOG_ERROR("error creating socket: %s", strerror(errno));
free_service(c);
return ERROR_FAIL;
}if (c->fd == -1) { ... }
setsockopt(c->fd,
SOL_SOCKET,
SO_REUSEADDR,
(void *)&so_reuseaddr_option,
sizeof(int));
socket_nonblock(c->fd);
memset(&c->sin, 0, sizeof(c->sin));
c->sin.sin_family = AF_INET;
if (!bindto_name)
c->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
else {
hp = gethostbyname(bindto_name);
if (!hp) {
LOG_ERROR("couldn't resolve bindto address: %s", bindto_name);
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}if (!hp) { ... }
memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length);
}else { ... }
c->sin.sin_port = htons(c->portnumber);
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) {
LOG_ERROR("couldn't bind %s to socket on port %d: %s", c->name, c->portnumber, strerror(errno));
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { ... }
#ifndef _WIN32
int segsize = 65536;
setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int));/* ... */
#endif
int window_size = 128 * 1024;
setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF,
(char *)&window_size, sizeof(window_size));
setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF,
(char *)&window_size, sizeof(window_size));
if (listen(c->fd, 1) == -1) {
LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}if (listen(c->fd, 1) == -1) { ... }
struct sockaddr_in addr_in;
addr_in.sin_port = 0;
socklen_t addr_in_size = sizeof(addr_in);
if (getsockname(c->fd, (struct sockaddr *)&addr_in, &addr_in_size) == 0)
LOG_INFO("Listening on port %hu for %s connections",
ntohs(addr_in.sin_port), c->name);
}if (c->type == CONNECTION_TCP) { ... } else if (c->type == CONNECTION_STDINOUT) {
c->fd = fileno(stdin);
#ifdef _WIN32
if (_setmode(_fileno(stdout), _O_BINARY) < 0)
LOG_WARNING("cannot change stdout mode to binary");
if (_setmode(_fileno(stdin), _O_BINARY) < 0)
LOG_WARNING("cannot change stdin mode to binary");
if (_setmode(_fileno(stderr), _O_BINARY) < 0)
LOG_WARNING("cannot change stderr mode to binary");/* ... */
#else
socket_nonblock(c->fd);
#endif
}else if (c->type == CONNECTION_STDINOUT) { ... } else if (c->type == CONNECTION_PIPE) {
#ifdef _WIN32
/* ... */
LOG_ERROR("Named pipes currently not supported under this os");
free_service(c);
return ERROR_FAIL;/* ... */
#else
c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
if (c->fd == -1) {
LOG_ERROR("could not open %s", c->port);
free_service(c);
return ERROR_FAIL;
}if (c->fd == -1) { ... }
/* ... */#endif
}else if (c->type == CONNECTION_PIPE) { ... }
for (p = &services; *p; p = &(*p)->next)
;
*p = c;
return ERROR_OK;
}{ ... }
static void remove_connections(struct service *service)
{
struct connection *connection;
connection = service->connections;
while (connection) {
struct connection *tmp;
tmp = connection->next;
remove_connection(service, connection);
connection = tmp;
}while (connection) { ... }
}{ ... }
int remove_service(const char *name, const char *port)
{
struct service *tmp;
struct service *prev;
prev = services;
for (tmp = services; tmp; prev = tmp, tmp = tmp->next) {
if (!strcmp(tmp->name, name) && !strcmp(tmp->port, port)) {
remove_connections(tmp);
if (tmp == services)
services = tmp->next;
else
prev->next = tmp->next;
if (tmp->type != CONNECTION_STDINOUT)
close_socket(tmp->fd);
free(tmp->priv);
free_service(tmp);
return ERROR_OK;
}if (!strcmp(tmp->name, name) && !strcmp(tmp->port, port)) { ... }
}for (tmp = services; tmp; prev = tmp, tmp = tmp->next) { ... }
return ERROR_OK;
}{ ... }
static int remove_services(void)
{
struct service *c = services;
while (c) {
struct service *next = c->next;
remove_connections(c);
free(c->name);
if (c->type == CONNECTION_PIPE) {
if (c->fd != -1)
close(c->fd);
}if (c->type == CONNECTION_PIPE) { ... }
free(c->port);
free(c->priv);
free(c);
c = next;
}while (c) { ... }
services = NULL;
return ERROR_OK;
}{ ... }
void server_keep_clients_alive(void)
{
for (struct service *s = services; s; s = s->next)
if (s->keep_client_alive)
for (struct connection *c = s->connections; c; c = c->next)
s->keep_client_alive(c);
}{ ... }
int server_loop(struct command_context *command_context)
{
struct service *service;
bool poll_ok = true;
fd_set read_fds;
int fd_max;
int retval;
int64_t next_event = timeval_ms() + polling_period;
#ifndef _WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");/* ... */
#endif
while (shutdown_openocd == CONTINUE_MAIN_LOOP) {
fd_max = 0;
FD_ZERO(&read_fds);
for (service = services; service; service = service->next) {
if (service->fd != -1) {
FD_SET(service->fd, &read_fds);
if (service->fd > fd_max)
fd_max = service->fd;
}if (service->fd != -1) { ... }
if (service->connections) {
struct connection *c;
for (c = service->connections; c; c = c->next) {
FD_SET(c->fd, &read_fds);
if (c->fd > fd_max)
fd_max = c->fd;
}for (c = service->connections; c; c = c->next) { ... }
}if (service->connections) { ... }
}for (service = services; service; service = service->next) { ... }
struct timeval tv;
tv.tv_sec = 0;
if (poll_ok) {
/* ... */
tv.tv_usec = 0;
retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
}if (poll_ok) { ... } else {
int timeout_ms = next_event - timeval_ms();
if (timeout_ms < 0)
timeout_ms = 0;
else if (timeout_ms > polling_period)
timeout_ms = polling_period;
tv.tv_usec = timeout_ms * 1000;
retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
}else { ... }
if (retval == -1) {
#ifdef _WIN32
errno = WSAGetLastError();
if (errno == WSAEINTR)
FD_ZERO(&read_fds);
else {
LOG_ERROR("error during select: %s", strerror(errno));
return ERROR_FAIL;
}else { ... }
/* ... */#else
if (errno == EINTR)
FD_ZERO(&read_fds);
else {
LOG_ERROR("error during select: %s", strerror(errno));
return ERROR_FAIL;
}else { ... }
/* ... */#endif
}if (retval == -1) { ... }
if (retval == 0) {
/* ... */
target_call_timer_callbacks();
next_event = target_timer_next_event();
process_jim_events(command_context);
FD_ZERO(&read_fds);
/* ... */
poll_ok = false;
}if (retval == 0) { ... } else {
poll_ok = true;
}else { ... }
/* ... */
poll_ok = poll_ok || target_got_message();
for (service = services; service; service = service->next) {
if ((service->fd != -1)
&& (FD_ISSET(service->fd, &read_fds))) {
if (service->max_connections != 0)
add_connection(service, command_context);
else {
if (service->type == CONNECTION_TCP) {
struct sockaddr_in sin;
socklen_t address_size = sizeof(sin);
int tmp_fd;
tmp_fd = accept(service->fd,
(struct sockaddr *)&service->sin,
&address_size);
close_socket(tmp_fd);
}if (service->type == CONNECTION_TCP) { ... }
LOG_INFO(
"rejected '%s' connection, no more connections allowed",
service->name);
}else { ... }
}if ((service->fd != -1) && (FD_ISSET(service->fd, &read_fds))) { ... }
if (service->connections) {
struct connection *c;
for (c = service->connections; c; ) {
if ((c->fd >= 0 && FD_ISSET(c->fd, &read_fds)) || c->input_pending) {
retval = service->input(c);
if (retval != ERROR_OK) {
struct connection *next = c->next;
if (service->type == CONNECTION_PIPE ||
service->type == CONNECTION_STDINOUT) {
/* ... */
shutdown_openocd = SHUTDOWN_REQUESTED;
}if (service->type == CONNECTION_PIPE || service->type == CONNECTION_STDINOUT) { ... }
remove_connection(service, c);
LOG_INFO("dropped '%s' connection (error %d)",
service->name, retval);
c = next;
continue;
}if (retval != ERROR_OK) { ... }
}if ((c->fd >= 0 && FD_ISSET(c->fd, &read_fds)) || c->input_pending) { ... }
c = c->next;
}for (c = service->connections; c;) { ... }
}if (service->connections) { ... }
}for (service = services; service; service = service->next) { ... }
#ifdef _WIN32
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE;
}while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { ... }
/* ... */#endif
}while (shutdown_openocd == CONTINUE_MAIN_LOOP) { ... }
if (shutdown_openocd == SHUTDOWN_WITH_SIGNAL_CODE)
command_run_line(command_context, "shutdown");
return shutdown_openocd == SHUTDOWN_WITH_ERROR_CODE ? ERROR_FAIL : ERROR_OK;
}{ ... }
static void sig_handler(int sig)
{
if (shutdown_openocd == CONTINUE_MAIN_LOOP) {
shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE;
last_signal = sig;
LOG_DEBUG("Terminating on Signal %d", sig);
}if (shutdown_openocd == CONTINUE_MAIN_LOOP) { ... } else
LOG_DEBUG("Ignored extra Signal %d", sig);
}{ ... }
#ifdef _WIN32
BOOL WINAPI control_handler(DWORD ctrl_type)
{
shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE;
return TRUE;
}{ ... }
/* ... */#else
static void sigkey_handler(int sig)
{
if (tcgetpgrp(STDIN_FILENO) > 0)
sig_handler(sig);
else
LOG_DEBUG("Ignored Signal %d", sig);
}sigkey_handler (int sig) { ... }
/* ... */#endif
int server_host_os_entry(void)
{
/* ... */
#ifdef _WIN32
WORD version_requested;
WSADATA wsadata;
version_requested = MAKEWORD(2, 2);
if (WSAStartup(version_requested, &wsadata) != 0) {
LOG_ERROR("Failed to Open Winsock");
return ERROR_FAIL;
}if (WSAStartup(version_requested, &wsadata) != 0) { ... }
/* ... */#endif
return ERROR_OK;
}{ ... }
int server_host_os_close(void)
{
#ifdef _WIN32
WSACleanup();
#endif
return ERROR_OK;
}{ ... }
int server_preinit(void)
{
#ifdef _WIN32
SetConsoleCtrlHandler(control_handler, TRUE);
signal(SIGBREAK, sig_handler);
signal(SIGINT, sig_handler);/* ... */
#else
signal(SIGHUP, sig_handler);
signal(SIGPIPE, sig_handler);
signal(SIGQUIT, sigkey_handler);
signal(SIGINT, sigkey_handler);/* ... */
#endif
signal(SIGTERM, sig_handler);
signal(SIGABRT, sig_handler);
return ERROR_OK;
}{ ... }
int server_init(struct command_context *cmd_ctx)
{
int ret = tcl_init();
if (ret != ERROR_OK)
return ret;
ret = telnet_init("Open On-Chip Debugger");
if (ret != ERROR_OK) {
remove_services();
return ret;
}if (ret != ERROR_OK) { ... }
return ERROR_OK;
}{ ... }
int server_quit(void)
{
remove_services();
target_quit();
#ifdef _WIN32
SetConsoleCtrlHandler(control_handler, FALSE);
return ERROR_OK;/* ... */
#endif
return last_signal;
}{ ... }
void server_free(void)
{
tcl_service_free();
telnet_service_free();
jsp_service_free();
ipdbg_server_free();
free(bindto_name);
}{ ... }
void exit_on_signal(int sig)
{
#ifndef _WIN32
signal(sig, SIG_DFL);
kill(getpid(), sig);/* ... */
#endif
}{ ... }
int connection_write(struct connection *connection, const void *data, int len)
{
if (len == 0) {
return 0;
}if (len == 0) { ... }
if (connection->service->type == CONNECTION_TCP)
return write_socket(connection->fd_out, data, len);
else
return write(connection->fd_out, data, len);
}{ ... }
int connection_read(struct connection *connection, void *data, int len)
{
if (connection->service->type == CONNECTION_TCP)
return read_socket(connection->fd, data, len);
else
return read(connection->fd, data, len);
}{ ... }
bool openocd_is_shutdown_pending(void)
{
return shutdown_openocd != CONTINUE_MAIN_LOOP;
}{ ... }
COMMAND_HANDLER(handle_shutdown_command)
{
LOG_USER("shutdown command invoked");
shutdown_openocd = SHUTDOWN_REQUESTED;
command_run_line(CMD_CTX, "_run_pre_shutdown_commands");
if (CMD_ARGC == 1) {
if (!strcmp(CMD_ARGV[0], "error")) {
shutdown_openocd = SHUTDOWN_WITH_ERROR_CODE;
return ERROR_FAIL;
}if (!strcmp(CMD_ARGV[0], "error")) { ... }
}if (CMD_ARGC == 1) { ... }
return ERROR_COMMAND_CLOSE_CONNECTION;
}{ ... }
COMMAND_HANDLER(handle_poll_period_command)
{
if (CMD_ARGC == 0)
LOG_WARNING("You need to set a period value");
else
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], polling_period);
LOG_INFO("set servers polling period to %ums", polling_period);
return ERROR_OK;
}{ ... }
COMMAND_HANDLER(handle_bindto_command)
{
switch (CMD_ARGC) {
case 0:
command_print(CMD, "bindto name: %s", bindto_name);
break;case 0:
case 1:
free(bindto_name);
bindto_name = strdup(CMD_ARGV[0]);
break;case 1:
default:
return ERROR_COMMAND_SYNTAX_ERROR;default
}switch (CMD_ARGC) { ... }
return ERROR_OK;
}{ ... }
static const struct command_registration server_command_handlers[] = {
{
.name = "shutdown",
.handler = &handle_shutdown_command,
.mode = COMMAND_ANY,
.usage = "",
.help = "shut the server down",
...},
{
.name = "poll_period",
.handler = &handle_poll_period_command,
.mode = COMMAND_ANY,
.usage = "",
.help = "set the servers polling period",
...},
{
.name = "bindto",
.handler = &handle_bindto_command,
.mode = COMMAND_CONFIG,
.usage = "[name]",
.help = "Specify address by name on which to listen for "
"incoming TCP/IP connections",
...},
COMMAND_REGISTRATION_DONE
...};
int server_register_commands(struct command_context *cmd_ctx)
{
int retval = telnet_register_commands(cmd_ctx);
if (retval != ERROR_OK)
return retval;
retval = tcl_register_commands(cmd_ctx);
if (retval != ERROR_OK)
return retval;
retval = jsp_register_commands(cmd_ctx);
if (retval != ERROR_OK)
return retval;
return register_commands(cmd_ctx, NULL, server_command_handlers);
}{ ... }
COMMAND_HELPER(server_port_command, unsigned short *out)
{
switch (CMD_ARGC) {
case 0:
command_print(CMD, "%d", *out);
break;case 0:
case 1:
{
uint16_t port;
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
*out = port;
break;
...}case 1:
default:
return ERROR_COMMAND_SYNTAX_ERROR;default
}switch (CMD_ARGC) { ... }
return ERROR_OK;
}{ ... }
COMMAND_HELPER(server_pipe_command, char **out)
{
switch (CMD_ARGC) {
case 0:
command_print(CMD, "%s", *out);
break;case 0:
case 1:
{
if (CMD_CTX->mode == COMMAND_EXEC) {
LOG_WARNING("unable to change server port after init");
return ERROR_COMMAND_ARGUMENT_INVALID;
}if (CMD_CTX->mode == COMMAND_EXEC) { ... }
free(*out);
*out = strdup(CMD_ARGV[0]);
break;
...}case 1:
default:
return ERROR_COMMAND_SYNTAX_ERROR;default
}switch (CMD_ARGC) { ... }
return ERROR_OK;
}{ ... }