]>
cvs.zerfleddert.de Git - hmcfgusb/blob - hmland.c
   1 /* HM-CFG-LAN emulation for HM-CFG-USB 
   3  * Copyright (c) 2013 Michael Gernoth <michael@gernoth.net> 
   5  * Permission is hereby granted, free of charge, to any person obtaining a copy 
   6  * of this software and associated documentation files (the "Software"), to 
   7  * deal in the Software without restriction, including without limitation the 
   8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
   9  * sell copies of the Software, and to permit persons to whom the Software is 
  10  * furnished to do so, subject to the following conditions: 
  12  * The above copyright notice and this permission notice shall be included in 
  13  * all copies or substantial portions of the Software. 
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
  18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
  20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
  33 #include <sys/types.h> 
  34 #include <sys/socket.h> 
  38 #include <netinet/in.h> 
  39 #include <arpa/inet.h> 
  40 #include <libusb-1.0/libusb.h> 
  45 #define PID_FILE "/var/run/hmland.pid" 
  47 #define DEFAULT_REBOOT_SECONDS  86400 
  51 static int impersonate_hmlanif 
= 0; 
  53 static int verbose 
= 0; 
  54 static int reboot_seconds 
= 0; 
  55 static int reboot_at_hour 
= -1; 
  56 static int reboot_at_minute 
= -1; 
  61         struct queued_rx 
*next
; 
  64 static struct queued_rx 
*qrx 
= NULL
; 
  65 static int wait_for_h 
= 0; 
  67 #define FLAG_LENGTH_BYTE        (1<<0) 
  68 #define FLAG_FORMAT_HEX         (1<<1) 
  69 #define FLAG_COMMA_BEFORE       (1<<2) 
  70 #define FLAG_COMMA_AFTER        (1<<3) 
  71 #define FLAG_NL                 (1<<4) 
  72 #define FLAG_IGNORE_COMMAS      (1<<5) 
  74 #define CHECK_SPACE(x)          if ((*outpos + x) > outend) { fprintf(stderr, "Not enough space!\n"); return 0; } 
  75 #define CHECK_AVAIL(x)          if ((*inpos + x) > inend) { fprintf(stderr, "Not enough input available!\n"); return 0; } 
  77 static void print_timestamp(FILE *f
) 
  83         gettimeofday(&tv
, NULL
); 
  84         tmp 
= localtime(&tv
.tv_sec
); 
  85         memset(ts
, 0, sizeof(ts
)); 
  86         strftime(ts
, sizeof(ts
)-1, "%Y-%m-%d %H:%M:%S", tmp
); 
  87         fprintf(f
, "%s.%06ld: ", ts
, tv
.tv_usec
); 
  90 static int format_part_out(uint8_t **inpos
, int inlen
, uint8_t **outpos
, int outlen
, int len
, int flags
) 
  92         const uint8_t nibble
[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
  93                 'A', 'B', 'C', 'D', 'E', 'F'}; 
  94         uint8_t *buf_out 
= *outpos
; 
  95         uint8_t *outend 
= *outpos 
+ outlen
; 
  96         uint8_t *inend 
= *inpos 
+ inlen
; 
  99         if (flags 
& FLAG_COMMA_BEFORE
) { 
 105         if (flags 
& FLAG_LENGTH_BYTE
) { 
 111         if (flags 
& FLAG_FORMAT_HEX
) { 
 114                 for (i 
= 0; i 
< len
; i
++) { 
 115                         **outpos 
= nibble
[((**inpos
) & 0xf0) >> 4]; 
 117                         **outpos 
= nibble
[((**inpos
) & 0xf)]; 
 118                         *inpos 
+= 1; *outpos 
+= 1; 
 123                 memcpy(*outpos
, *inpos
, len
); 
 128         if (flags 
& FLAG_COMMA_AFTER
) { 
 134         if (flags 
& FLAG_NL
) { 
 142         return *outpos 
- buf_out
; 
 145 static uint8_t ascii_to_nibble(uint8_t a
) 
 149         if ((a 
>= '0') && (a 
<= '9')) { 
 151         } else if ((a 
>= 'A') && (a 
<= 'F')) { 
 153         } else if ((a 
>= 'a') && (a 
<= 'f')) { 
 160 static int parse_part_in(uint8_t **inpos
, int inlen
, uint8_t **outpos
, int outlen
, int flags
) 
 162         uint8_t *buf_out 
= *outpos
; 
 163         uint8_t *outend 
= *outpos 
+ outlen
; 
 164         uint8_t *inend 
= *inpos 
+ inlen
; 
 166         if (flags 
& FLAG_LENGTH_BYTE
) { 
 174                                 if (!(flags 
& FLAG_IGNORE_COMMAS
)) 
 183                 **outpos 
= (len 
/ 2); 
 187         while(*inpos 
< inend
) { 
 188                 if (**inpos 
== ',') { 
 190                         if (!(flags 
& FLAG_IGNORE_COMMAS
)) 
 199                 **outpos 
= ascii_to_nibble(**inpos
) << 4; 
 201                 **outpos 
|= ascii_to_nibble(**inpos
); 
 202                 *inpos 
+= 1; *outpos 
+= 1; 
 205         return *outpos 
- buf_out
; 
 208 static int hmlan_format_out(uint8_t *buf
, int buf_len
, void *data
) 
 213         int fd 
= *((int*)data
); 
 219         memset(out
, 0, sizeof(out
)); 
 223         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, 0); 
 226                         if (impersonate_hmlanif
) { 
 231                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_LENGTH_BYTE
); 
 232                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 233                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_COMMA_BEFORE 
| FLAG_LENGTH_BYTE
); 
 234                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 3, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 235                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 3, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 236                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 237                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_NL
); 
 241                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 3, FLAG_FORMAT_HEX
); 
 242                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 243                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 244                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 245                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 246                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_LENGTH_BYTE 
| FLAG_NL
); 
 250                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX
); 
 251                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 252                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 253                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 254                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 255                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_LENGTH_BYTE 
| FLAG_NL
); 
 259                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX
); 
 260                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 261                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 262                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_NL
); 
 266                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), buf_len
-1, FLAG_FORMAT_HEX 
| FLAG_NL
); 
 267                         hexdump(buf
, buf_len
, "Unknown> "); 
 271         /* Queue packet until first respone to 'K' is received */ 
 272         if (wait_for_h 
&& buf
[0] != 'H') { 
 273                 struct queued_rx 
**rxp 
= &qrx
; 
 276                         rxp 
= &((*rxp
)->next
); 
 278                 *rxp 
= malloc(sizeof(struct queued_rx
)); 
 284                 memset(*rxp
, 0, sizeof(struct queued_rx
)); 
 285                 (*rxp
)->len 
= outpos
-out
; 
 286                 (*rxp
)->rx 
= malloc((*rxp
)->len
); 
 291                 memset((*rxp
)->rx
, 0, (*rxp
)->len
); 
 292                 memcpy((*rxp
)->rx
, out
, (*rxp
)->len
); 
 300                 print_timestamp(stdout
); 
 302                 for (i 
= 0; i 
< outpos
-out
-2; i
++) 
 303                         printf("%c", out
[i
]); 
 307         w 
= write(fd
, out
, outpos
-out
); 
 313         /* Send all queued packets */ 
 315                 struct queued_rx 
*curr_rx 
= qrx
; 
 316                 struct queued_rx 
*last_rx
; 
 322                                 print_timestamp(stdout
); 
 324                                 for (i 
= 0; i 
< curr_rx
->len
-2; i
++) 
 325                                         printf("%c", curr_rx
->rx
[i
]); 
 329                         w 
= write(fd
, curr_rx
->rx
, curr_rx
->len
); 
 334                         curr_rx 
= curr_rx
->next
; 
 348 static int hmlan_parse_in(int fd
, void *data
) 
 350         struct hmcfgusb_dev 
*dev 
= data
; 
 352         uint8_t out
[0x40]; //FIXME!!! 
 359         memset(buf
, 0, sizeof(buf
)); 
 361         r 
= read(fd
, buf
, sizeof(buf
)-1); 
 363                 uint8_t *inend 
= buf 
+ r
; 
 367                 while (inpos 
< inend
) { 
 368                         uint8_t *instart 
= inpos
; 
 370                         if ((*inpos 
== '\r') || (*inpos 
== '\n')) { 
 377                         last 
= inend 
- inpos
; 
 379                         for (i 
= 0; i 
< last
; i
++) { 
 380                                 if ((inpos
[i
] == '\r') || (inpos
[i
] == '\n')) { 
 390                                 print_timestamp(stdout
); 
 392                                 for (i 
= 0; i 
< last
; i
++) 
 393                                         printf("%c", instart
[i
]); 
 397                         memset(out
, 0, sizeof(out
)); 
 398                         *outpos
++ = *inpos
++; 
 402                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 403                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 404                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 405                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 406                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 407                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), FLAG_LENGTH_BYTE
); 
 410                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 411                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 412                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), FLAG_LENGTH_BYTE
); 
 415                                         parse_part_in(&inpos
, (last
-(inpos
-instart
)), &outpos
, (sizeof(out
)-(outpos
-out
)), FLAG_IGNORE_COMMAS
); 
 419                         hmcfgusb_send(dev
, out
, sizeof(out
), 1); 
 422                 if (errno 
!= ECONNRESET
) 
 432 static int comm(int fd_in
, int fd_out
, int master_socket
, int flags
) 
 434         struct hmcfgusb_dev 
*dev
; 
 435         uint8_t out
[0x40]; //FIXME!!! 
 438         hmcfgusb_set_debug(debug
); 
 440         dev 
= hmcfgusb_init(hmlan_format_out
, &fd_out
); 
 442                 fprintf(stderr
, "Can't initialize HM-CFG-USB!\n"); 
 446         if (dev
->bootloader
) { 
 448                         printf("HM-CFG-USB in bootloader mode, restarting in normal mode...\n"); 
 450                 hmcfgusb_leave_bootloader(dev
); 
 457         if ((reboot_at_hour 
!= -1) && (reboot_at_minute 
!= -1)) { 
 462                 tm_s 
= localtime(&tm
); 
 468                 tm_s
->tm_hour 
= reboot_at_hour
; 
 469                 tm_s
->tm_min 
= reboot_at_minute
; 
 473                 reboot_seconds 
= tm 
- dev
->opened_at
; 
 475                 while (reboot_seconds 
<= 0) 
 476                         reboot_seconds 
+= 86400; 
 479         if (verbose 
&& reboot_seconds
) 
 480                 printf("Rebooting in %u seconds\n", reboot_seconds
); 
 483         if (!hmcfgusb_add_pfd(dev
, fd_in
, POLLIN
)) { 
 484                 fprintf(stderr
, "Can't add client to pollfd!\n"); 
 489         if (master_socket 
>= 0) { 
 490                 if (!hmcfgusb_add_pfd(dev
, master_socket
, POLLIN
)) { 
 491                         fprintf(stderr
, "Can't add master_socket to pollfd!\n"); 
 497         memset(out
, 0, sizeof(out
)); 
 500         hmcfgusb_send_null_frame(dev
, 1); 
 501         hmcfgusb_send(dev
, out
, sizeof(out
), 1); 
 506                 fd 
= hmcfgusb_poll(dev
, 1);     /* Wakeup device/bus at least once a second */ 
 508                         if (fd 
== master_socket
) { 
 511                                 client 
= accept(master_socket
, NULL
, 0); 
 513                                         shutdown(client
, SHUT_RDWR
); 
 517                                 if (hmlan_parse_in(fd
, dev
) <= 0) { 
 521                 } else if (fd 
== -1) { 
 523                                 if (errno 
!= ETIMEDOUT
) { 
 524                                         perror("hmcfgusb_poll"); 
 527                                         /* periodically wakeup the device */ 
 528                                         hmcfgusb_send_null_frame(dev
, 1); 
 530                                                 memset(out
, 0, sizeof(out
)); 
 532                                                 hmcfgusb_send(dev
, out
, sizeof(out
), 1); 
 538                 if (reboot_seconds 
&& ((dev
->opened_at 
+ reboot_seconds
) <= time(NULL
))) { 
 540                                 printf("HM-CFG-USB running since %lu seconds, rebooting now...\n", 
 541                                         time(NULL
) - dev
->opened_at
); 
 543                         hmcfgusb_enter_bootloader(dev
); 
 551 void sigterm_handler(int sig
) 
 553         if (unlink(PID_FILE
) == -1) 
 554                 perror("Can't remove PID file"); 
 559 #define FLAG_DAEMON     (1 << 0) 
 560 #define FLAG_PID_FILE   (1 << 1) 
 562 static int socket_server(char *iface
, int port
, int flags
) 
 564         struct sigaction sact
; 
 565         struct sockaddr_in sin
; 
 570         if (flags 
& FLAG_DAEMON
) { 
 571                 FILE *pidfile 
= NULL
; 
 573                 if (flags 
& FLAG_PID_FILE
) { 
 576                         fd 
= open(PID_FILE
, O_CREAT 
| O_EXCL 
| O_WRONLY
, 0644); 
 578                                 if (errno 
== EEXIST
) { 
 580                                         pidfile 
= fopen(PID_FILE
, "r"); 
 582                                                 perror("PID file " PID_FILE 
" already exists, already running?"); 
 586                                         if (fscanf(pidfile
, "%u", &old_pid
) != 1) { 
 588                                                 fprintf(stderr
, "Can't read old PID from " PID_FILE 
", already running?\n"); 
 594                                         fprintf(stderr
, "Already running with PID %u according to " PID_FILE 
"!\n", old_pid
); 
 597                                 perror("Can't create PID file " PID_FILE
); 
 601                         pidfile 
= fdopen(fd
, "w"); 
 603                                 perror("Can't reopen PID file fd"); 
 607                         memset(&sact
, 0, sizeof(sact
)); 
 608                         sact
.sa_handler 
= sigterm_handler
; 
 610                         if (sigaction(SIGTERM
, &sact
, NULL
) == -1) { 
 611                                 perror("sigaction(SIGTERM)"); 
 619                                 fprintf(pidfile
, "%u\n", pid
); 
 623                         printf("Daemon with PID %u started!\n", pid
); 
 625                 } else if (pid 
< 0) { 
 634         memset(&sact
, 0, sizeof(sact
)); 
 635         sact
.sa_handler 
= SIG_IGN
; 
 637         if (sigaction(SIGPIPE
, &sact
, NULL
) == -1) { 
 638                 perror("sigaction(SIGPIPE)"); 
 642         impersonate_hmlanif 
= 1; 
 644         sock 
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
); 
 646                 perror("Can't open socket"); 
 651         if (setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &n
, sizeof(n
)) == -1) { 
 652                 perror("Can't set socket options"); 
 656         memset(&sin
, 0, sizeof(sin
)); 
 657         sin
.sin_family 
= AF_INET
; 
 658         sin
.sin_port 
= htons(port
); 
 660                 sin
.sin_addr
.s_addr 
= htonl(INADDR_ANY
); 
 662                 if (inet_pton(AF_INET
, iface
, &(sin
.sin_addr
.s_addr
)) != 1) { 
 663                         fprintf(stderr
, "Can't convert IP %s, aborting!\n", iface
); 
 668         if (bind(sock
, (struct sockaddr
*)&sin
, sizeof(sin
)) == -1) { 
 669                 perror("Can't bind socket"); 
 673         if (listen(sock
, 1) == -1) { 
 674                 perror("Can't listen on socket"); 
 679                 struct sockaddr_in csin
; 
 682                 in_addr_t client_addr
; 
 684                 memset(&csin
, 0, sizeof(csin
)); 
 685                 csinlen 
= sizeof(csin
); 
 686                 client 
= accept(sock
, (struct sockaddr
*)&csin
, &csinlen
); 
 688                         perror("Couldn't accept client"); 
 692                 /* FIXME: getnameinfo... */ 
 693                 client_addr 
= ntohl(csin
.sin_addr
.s_addr
); 
 696                         print_timestamp(stdout
); 
 697                         printf("Client %d.%d.%d.%d connected!\n", 
 698                                         (client_addr 
& 0xff000000) >> 24, 
 699                                         (client_addr 
& 0x00ff0000) >> 16, 
 700                                         (client_addr 
& 0x0000ff00) >> 8, 
 701                                         (client_addr 
& 0x000000ff)); 
 704                 comm(client
, client
, sock
, flags
); 
 706                 shutdown(client
, SHUT_RDWR
); 
 710                         print_timestamp(stdout
); 
 711                         printf("Connection to %d.%d.%d.%d closed!\n", 
 712                                         (client_addr 
& 0xff000000) >> 24, 
 713                                         (client_addr 
& 0x00ff0000) >> 16, 
 714                                         (client_addr 
& 0x0000ff00) >> 8, 
 715                                         (client_addr 
& 0x000000ff)); 
 723 static int interactive_server(int flags
) 
 725         if (!comm(STDIN_FILENO
, STDOUT_FILENO
, -1, flags
)) 
 731 void hmlan_syntax(char *prog
) 
 733         fprintf(stderr
, "Syntax: %s options\n\n", prog
); 
 734         fprintf(stderr
, "Possible options:\n"); 
 735         fprintf(stderr
, "\t-D\t\tdebug mode\n"); 
 736         fprintf(stderr
, "\t-d\t\tdaemon mode\n"); 
 737         fprintf(stderr
, "\t-h\t\tthis help\n"); 
 738         fprintf(stderr
, "\t-i\t\tinteractive mode (connect HM-CFG-USB to terminal)\n"); 
 739         fprintf(stderr
, "\t-l ip\t\tlisten on given IP address only (for example 127.0.0.1)\n"); 
 740         fprintf(stderr
, "\t-P\t\tcreate PID file " PID_FILE 
" in daemon mode\n"); 
 741         fprintf(stderr
, "\t-p n\t\tlisten on port n (default: 1000)\n"); 
 742         fprintf(stderr
, "\t-r n\t\treboot HM-CFG-USB after n seconds (0: no reboot, default: %u)\n", DEFAULT_REBOOT_SECONDS
); 
 743         fprintf(stderr
, "\t   hh:mm\treboot HM-CFG-USB daily at hh:mm\n"); 
 744         fprintf(stderr
, "\t-v\t\tverbose mode\n"); 
 748 int main(int argc
, char **argv
) 
 757         reboot_seconds 
= DEFAULT_REBOOT_SECONDS
; 
 759         while((opt 
= getopt(argc
, argv
, "DdhiPp:Rr:l:v")) != -1) { 
 766                                 flags 
|= FLAG_DAEMON
; 
 772                                 flags 
|= FLAG_PID_FILE
; 
 775                                 port 
= strtoul(optarg
, &ep
, 10); 
 777                                         fprintf(stderr
, "Can't parse port!\n"); 
 782                                 fprintf(stderr
, "-R is no longer needed (1s wakeup is default)\n"); 
 785                                 reboot_seconds 
= strtoul(optarg
, &ep
, 10); 
 788                                                 reboot_at_hour 
= reboot_seconds
; 
 790                                                 reboot_at_minute 
= strtoul(ep
, &ep
, 10); 
 792                                                         fprintf(stderr
, "Can't parse reboot-time!\n"); 
 798                                                 fprintf(stderr
, "Can't parse reboot-timeout!\n"); 
 813                                 hmlan_syntax(argv
[0]); 
 820                 return interactive_server(flags
); 
 822                 return socket_server(iface
, port
, flags
);