34
34
* Default is to connect to localhost:8001.
35
35
* See the "usage" functions at the bottom for details.
36
36
*
37
- * FIXME: This is a rough prototype that needs more work.
38
- *
39
37
*---------------------------------------------------------------*/
40
38
41
39
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
49
47
50
48
#include <stdlib.h>
51
49
#include <sys/errno.h>
50
+ #include <sys/types.h>
51
+ #include <sys/socket.h>
52
52
53
53
#endif
54
54
58
58
#include <ctype.h>
59
59
#include <string.h>
60
60
#include <getopt.h>
61
- #include <sys/types.h>
62
61
#include <dirent.h>
62
+ #include <sys/stat.h>
63
63
64
- //#include "ax25_pad.h"
65
-
64
+ #include "ax25_pad.h"
66
65
#include "textcolor.h"
67
66
#include "serial_port.h"
68
67
#include "kiss_frame.h"
69
68
#include "sock.h"
70
69
#include "dtime_now.h"
71
70
#include "audio.h" // for DEFAULT_TXDELAY, etc.
71
+ #include "dtime_now.h"
72
72
73
73
74
74
// TODO: define in one place, use everywhere.
@@ -90,16 +90,11 @@ static THREAD_F tnc_listen_serial (void *arg);
90
90
static void send_to_kiss_tnc (int chan , int cmd , char * data , int dlen );
91
91
static void hex_dump (unsigned char * p , int len );
92
92
93
-
94
- // Why didn't I use send/recv for Linux?
95
-
96
- #if __WIN32__
93
+ // Formerly used write/read on Linux, for some forgotten reason,
94
+ // but making them the same seems to make more sense.
97
95
#define SOCK_SEND (s ,data ,size ) send(s,data,size,0)
98
96
#define SOCK_RECV (s ,data ,size ) recv(s,data,size,0)
99
- #else
100
- #define SOCK_SEND (s ,data ,size ) write(s,data,size)
101
- #define SOCK_RECV (s ,data ,size ) read(s,data,size)
102
- #endif
97
+
103
98
104
99
static void usage (void );
105
100
static void usage2 (void );
@@ -273,8 +268,20 @@ int main (int argc, char *argv[])
273
268
* If receive queue directory was specified, make sure that it exists.
274
269
*/
275
270
if (strlen (receive_output ) > 0 ) {
271
+ struct stat s ;
276
272
277
- // TODO
273
+ if (stat (receive_output , & s ) == 0 ) {
274
+ if ( ! S_ISDIR (s .st_mode )) {
275
+ text_color_set (DW_COLOR_ERROR );
276
+ dw_printf ("Receive queue location, %s, is not a directory.\n" , receive_output );
277
+ exit (EXIT_FAILURE );
278
+ }
279
+ }
280
+ else {
281
+ text_color_set (DW_COLOR_ERROR );
282
+ dw_printf ("Receive queue location, %s, does not exist.\n" , receive_output );
283
+ exit (EXIT_FAILURE );
284
+ }
278
285
}
279
286
280
287
/* If port begins with digit, consider it to be TCP. */
@@ -418,79 +425,104 @@ static int parse_number (char *str, int de_fault)
418
425
419
426
static void process_input (char * stuff )
420
427
{
421
- char * p ;
422
- int chan = 0 ;
428
+ char * p ;
429
+ int chan = 0 ;
423
430
424
431
/*
425
432
* Remove any end of line character(s).
426
433
*/
427
- trim (stuff );
434
+ trim (stuff );
428
435
429
436
/*
430
- * Optional prefix, like "[9]" to specify channel. TODO FIXME
437
+ * Optional prefix, like "[9]" or "[99]" to specify channel.
431
438
*/
432
- p = stuff ;
439
+ p = stuff ;
440
+ while (isspace (* p )) p ++ ;
441
+ if (* p == '[' ) {
442
+ p ++ ;
443
+ if (p [1 ] == ']' ) {
444
+ chan = atoi (p );
445
+ p += 2 ;
446
+ }
447
+ else if (p [2 ] == ']' ) {
448
+ chan = atoi (p );
449
+ p += 3 ;
450
+ }
451
+ else {
452
+ text_color_set (DW_COLOR_ERROR );
453
+ dw_printf ("ERROR! One or two digit channel number and ] was expected after [ at beginning of line.\n" );
454
+ usage2 ();
455
+ return ;
456
+ }
457
+ if (chan < 0 || chan > 15 ) {
458
+ text_color_set (DW_COLOR_ERROR );
459
+ dw_printf ("ERROR! KISS channel number must be in range of 0 thru 15.\n" );
460
+ usage2 ();
461
+ return ;
462
+ }
463
+ while (isspace (* p )) p ++ ;
464
+ }
433
465
434
466
/*
435
467
* If it starts with upper case letter or digit, assume it is an AX.25 frame in monitor format.
436
468
* Lower case is a command (e.g. Persistence or set Hardware).
437
469
* Anything else, print explanation of what is expected.
438
470
*/
439
- if (isupper (* p ) || isdigit (* p )) {
471
+ if (isupper (* p ) || isdigit (* p )) {
440
472
441
- // Parse the "TNC2 monitor format" and convert to AX.25 frame.
473
+ // Parse the "TNC2 monitor format" and convert to AX.25 frame.
442
474
443
- unsigned char frame_data [AX25_MAX_PACKET_LEN ];
444
- packet_t pp = ax25_from_text (p , 1 );
445
- if (pp != NULL ) {
446
- int frame_len = ax25_pack (pp , frame_data );
447
- send_to_kiss_tnc (chan , KISS_CMD_DATA_FRAME , (char * )frame_data , frame_len );
448
- ax25_delete (pp );
449
- }
450
- else {
451
- text_color_set (DW_COLOR_ERROR );
452
- dw_printf ("ERROR! Could not convert to AX.25 frame: %s\n" , p );
453
- }
454
- }
455
- else if (islower (* p )) {
456
- char value ;
457
-
458
- switch (* p ) {
459
- case 'd' : // txDelay, 10ms units
460
- value = parse_number (p + 1 , DEFAULT_TXDELAY );
461
- send_to_kiss_tnc (chan , KISS_CMD_TXDELAY , & value , 1 );
462
- break ;
463
- case 'p' : // Persistence
464
- value = parse_number (p + 1 , DEFAULT_PERSIST );
465
- send_to_kiss_tnc (chan , KISS_CMD_PERSISTENCE , & value , 1 );
466
- break ;
467
- case 's' : // Slot time, 10ms units
468
- value = parse_number (p + 1 , DEFAULT_SLOTTIME );
469
- send_to_kiss_tnc (chan , KISS_CMD_SLOTTIME , & value , 1 );
470
- break ;
471
- case 't' : // txTail, 10ms units
472
- value = parse_number (p + 1 , DEFAULT_TXTAIL );
473
- send_to_kiss_tnc (chan , KISS_CMD_TXTAIL , & value , 1 );
474
- break ;
475
- case 'f' : // Full duplex
476
- value = parse_number (p + 1 , 0 );
477
- send_to_kiss_tnc (chan , KISS_CMD_FULLDUPLEX , & value , 1 );
478
- break ;
479
- case 'h' : // set Hardware
480
- p ++ ;
481
- while (* p != '\0' && isspace (* p )) { p ++ ; }
482
- send_to_kiss_tnc (chan , KISS_CMD_SET_HARDWARE , p , strlen (p ));
483
- break ;
484
- default :
485
- text_color_set (DW_COLOR_ERROR );
486
- dw_printf ("Invalid command. Must be one of d p s t f h.\n" );
487
- usage2 ();
488
- break ;
489
- }
490
- }
491
- else {
475
+ unsigned char frame_data [AX25_MAX_PACKET_LEN ];
476
+ packet_t pp = ax25_from_text (p , 1 );
477
+ if (pp != NULL ) {
478
+ int frame_len = ax25_pack (pp , frame_data );
479
+ send_to_kiss_tnc (chan , KISS_CMD_DATA_FRAME , (char * )frame_data , frame_len );
480
+ ax25_delete (pp );
481
+ }
482
+ else {
483
+ text_color_set (DW_COLOR_ERROR );
484
+ dw_printf ("ERROR! Could not convert to AX.25 frame: %s\n" , p );
485
+ }
486
+ }
487
+ else if (islower (* p )) {
488
+ char value ;
489
+
490
+ switch (* p ) {
491
+ case 'd' : // txDelay, 10ms units
492
+ value = parse_number (p + 1 , DEFAULT_TXDELAY );
493
+ send_to_kiss_tnc (chan , KISS_CMD_TXDELAY , & value , 1 );
494
+ break ;
495
+ case 'p' : // Persistence
496
+ value = parse_number (p + 1 , DEFAULT_PERSIST );
497
+ send_to_kiss_tnc (chan , KISS_CMD_PERSISTENCE , & value , 1 );
498
+ break ;
499
+ case 's' : // Slot time, 10ms units
500
+ value = parse_number (p + 1 , DEFAULT_SLOTTIME );
501
+ send_to_kiss_tnc (chan , KISS_CMD_SLOTTIME , & value , 1 );
502
+ break ;
503
+ case 't' : // txTail, 10ms units
504
+ value = parse_number (p + 1 , DEFAULT_TXTAIL );
505
+ send_to_kiss_tnc (chan , KISS_CMD_TXTAIL , & value , 1 );
506
+ break ;
507
+ case 'f' : // Full duplex
508
+ value = parse_number (p + 1 , 0 );
509
+ send_to_kiss_tnc (chan , KISS_CMD_FULLDUPLEX , & value , 1 );
510
+ break ;
511
+ case 'h' : // set Hardware
512
+ p ++ ;
513
+ while (* p != '\0' && isspace (* p )) { p ++ ; }
514
+ send_to_kiss_tnc (chan , KISS_CMD_SET_HARDWARE , p , strlen (p ));
515
+ break ;
516
+ default :
517
+ text_color_set (DW_COLOR_ERROR );
518
+ dw_printf ("Invalid command. Must be one of d p s t f h.\n" );
492
519
usage2 ();
493
- }
520
+ break ;
521
+ }
522
+ }
523
+ else {
524
+ usage2 ();
525
+ }
494
526
495
527
} /* end process_input */
496
528
@@ -548,15 +580,19 @@ static void send_to_kiss_tnc (int chan, int cmd, char *data, int dlen)
548
580
hex_dump (kissed , klen );
549
581
}
550
582
551
- // FIXME: Should check for non -1 server_sock or serial_fd.
552
- // Might need to delay when not using interactive input.
553
-
554
583
if (using_tcp ) {
555
584
int rc = SOCK_SEND (server_sock , (char * )kissed , klen );
556
- (void )rc ;
585
+ if (rc != klen ) {
586
+ text_color_set (DW_COLOR_ERROR );
587
+ dw_printf ("ERROR writing KISS frame to socket.\n" );
588
+ }
557
589
}
558
590
else {
559
- serial_port_write (serial_fd , (char * )kissed , klen );
591
+ int rc = serial_port_write (serial_fd , (char * )kissed , klen );
592
+ if (rc != klen ) {
593
+ text_color_set (DW_COLOR_ERROR );
594
+ dw_printf ("ERROR writing KISS frame to serial port.\n" );
595
+ }
560
596
}
561
597
562
598
} /* end send_to_kiss_tnc */
@@ -578,8 +614,6 @@ static void send_to_kiss_tnc (int chan, int cmd, char *data, int dlen)
578
614
*
579
615
*--------------------------------------------------------------------*/
580
616
581
- //#define MAX_HOSTS 30
582
-
583
617
static THREAD_F tnc_listen_net (void * arg )
584
618
{
585
619
int err ;
@@ -673,6 +707,11 @@ static THREAD_F tnc_listen_serial (void *arg)
673
707
if (serial_fd == MYFDERROR ) {
674
708
text_color_set (DW_COLOR_ERROR );
675
709
dw_printf ("Unable to connect to KISS TNC serial port %s.\n" , port );
710
+ #if __WIN32__
711
+ #else
712
+ // More detail such as "permission denied" or "no such device"
713
+ dw_printf ("%s\n" , strerror (errno ));
714
+ #endif
676
715
exit (EXIT_FAILURE );
677
716
}
678
717
@@ -902,7 +941,7 @@ static void usage2 (void)
902
941
dw_printf (" s Slot time, 10ms units s 10\n" );
903
942
dw_printf (" t txTail, 10ms units t 5\n" );
904
943
dw_printf (" f Full duplex f 0\n" );
905
- dw_printf (" h set Hardware h T.B.D. \n" );
944
+ dw_printf (" h set Hardware h TNC: \n" );
906
945
dw_printf ("\n" );
907
946
dw_printf (" Lines may be preceded by the form \"[9]\" to indicate a\n" );
908
947
dw_printf (" channel other than the default 0.\n" );
0 commit comments