Skip to content

Commit 6ffef6e

Browse files
committed
Recognize channel number at start of command line. More error checking.
1 parent 9cd3059 commit 6ffef6e

File tree

1 file changed

+118
-79
lines changed

1 file changed

+118
-79
lines changed

kissutil.c

+118-79
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
* Default is to connect to localhost:8001.
3535
* See the "usage" functions at the bottom for details.
3636
*
37-
* FIXME: This is a rough prototype that needs more work.
38-
*
3937
*---------------------------------------------------------------*/
4038

4139
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
@@ -49,6 +47,8 @@
4947

5048
#include <stdlib.h>
5149
#include <sys/errno.h>
50+
#include <sys/types.h>
51+
#include <sys/socket.h>
5252

5353
#endif
5454

@@ -58,17 +58,17 @@
5858
#include <ctype.h>
5959
#include <string.h>
6060
#include <getopt.h>
61-
#include <sys/types.h>
6261
#include <dirent.h>
62+
#include <sys/stat.h>
6363

64-
//#include "ax25_pad.h"
65-
64+
#include "ax25_pad.h"
6665
#include "textcolor.h"
6766
#include "serial_port.h"
6867
#include "kiss_frame.h"
6968
#include "sock.h"
7069
#include "dtime_now.h"
7170
#include "audio.h" // for DEFAULT_TXDELAY, etc.
71+
#include "dtime_now.h"
7272

7373

7474
// TODO: define in one place, use everywhere.
@@ -90,16 +90,11 @@ static THREAD_F tnc_listen_serial (void *arg);
9090
static void send_to_kiss_tnc (int chan, int cmd, char *data, int dlen);
9191
static void hex_dump (unsigned char *p, int len);
9292

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.
9795
#define SOCK_SEND(s,data,size) send(s,data,size,0)
9896
#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+
10398

10499
static void usage(void);
105100
static void usage2(void);
@@ -273,8 +268,20 @@ int main (int argc, char *argv[])
273268
* If receive queue directory was specified, make sure that it exists.
274269
*/
275270
if (strlen(receive_output) > 0) {
271+
struct stat s;
276272

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+
}
278285
}
279286

280287
/* If port begins with digit, consider it to be TCP. */
@@ -418,79 +425,104 @@ static int parse_number (char *str, int de_fault)
418425

419426
static void process_input (char *stuff)
420427
{
421-
char *p;
422-
int chan = 0;
428+
char *p;
429+
int chan = 0;
423430

424431
/*
425432
* Remove any end of line character(s).
426433
*/
427-
trim (stuff);
434+
trim (stuff);
428435

429436
/*
430-
* Optional prefix, like "[9]" to specify channel. TODO FIXME
437+
* Optional prefix, like "[9]" or "[99]" to specify channel.
431438
*/
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+
}
433465

434466
/*
435467
* If it starts with upper case letter or digit, assume it is an AX.25 frame in monitor format.
436468
* Lower case is a command (e.g. Persistence or set Hardware).
437469
* Anything else, print explanation of what is expected.
438470
*/
439-
if (isupper(*p) || isdigit(*p)) {
471+
if (isupper(*p) || isdigit(*p)) {
440472

441-
// Parse the "TNC2 monitor format" and convert to AX.25 frame.
473+
// Parse the "TNC2 monitor format" and convert to AX.25 frame.
442474

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");
492519
usage2 ();
493-
}
520+
break;
521+
}
522+
}
523+
else {
524+
usage2 ();
525+
}
494526

495527
} /* end process_input */
496528

@@ -548,15 +580,19 @@ static void send_to_kiss_tnc (int chan, int cmd, char *data, int dlen)
548580
hex_dump (kissed, klen);
549581
}
550582

551-
// FIXME: Should check for non -1 server_sock or serial_fd.
552-
// Might need to delay when not using interactive input.
553-
554583
if (using_tcp) {
555584
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+
}
557589
}
558590
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+
}
560596
}
561597

562598
} /* end send_to_kiss_tnc */
@@ -578,8 +614,6 @@ static void send_to_kiss_tnc (int chan, int cmd, char *data, int dlen)
578614
*
579615
*--------------------------------------------------------------------*/
580616

581-
//#define MAX_HOSTS 30
582-
583617
static THREAD_F tnc_listen_net (void *arg)
584618
{
585619
int err;
@@ -673,6 +707,11 @@ static THREAD_F tnc_listen_serial (void *arg)
673707
if (serial_fd == MYFDERROR) {
674708
text_color_set(DW_COLOR_ERROR);
675709
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
676715
exit (EXIT_FAILURE);
677716
}
678717

@@ -902,7 +941,7 @@ static void usage2 (void)
902941
dw_printf (" s Slot time, 10ms units s 10\n");
903942
dw_printf (" t txTail, 10ms units t 5\n");
904943
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");
906945
dw_printf ("\n");
907946
dw_printf (" Lines may be preceded by the form \"[9]\" to indicate a\n");
908947
dw_printf (" channel other than the default 0.\n");

0 commit comments

Comments
 (0)