view rvinterf/lowlevel/rvifmain.c @ 988:5a6019ed7e72

pln-ppb-test: implement read-id
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 03 Dec 2023 00:04:18 +0000
parents 21604c3413c1
children
line wrap: on
line source

/*
 * This module contains the main() function for rvinterf
 */

#include <sys/types.h>
#include <sys/errno.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include "../include/pktmux.h"
#include "../include/localsock.h"
#include "client.h"

extern int target_fd, listener;
extern char *extlcd_program;
extern int bootctrl_etmoff_mode;

extern u_char rxpkt[];
extern size_t rxpkt_len;

extern void output_cont_logpref();

struct client *client_head;
int socketpair_fd;

char *logfname;
FILE *logF;
time_t logtime;
int background, no_output, verbose;
int max_fd;

char *socket_pathname = "/tmp/rvinterf_socket";

int wakeup_after_sec = 7;

static char *baudrate = "115200";

static char keepalive_msg[] =
	"Received keepalive query, responding with keepalive answer";
static u_char keepalive_answer[2] = {RVT_KEEPALIVE_HEADER, 'A'};

write_pid_file(pid)
{
	static char pid_filename[] = "/tmp/rvinterf.pid";
	FILE *of;

	of = fopen(pid_filename, "w");
	if (!of) {
		fprintf(stderr, "warning: unable to write %s\n", pid_filename);
		return(-1);
	}
	fprintf(of, "%d\n", pid);
	fclose(of);
	return(0);
}

main(argc, argv)
	char **argv;
{
	extern char *optarg;
	extern int optind;
	int c;
	fd_set fds;
	struct client *cli, **clip;

	while ((c = getopt(argc, argv, "bB:d:l:nP:s:S:vw:X:")) != EOF)
		switch (c) {
		case 'b':
			background++;
			/* FALL THRU */
		case 'n':
			no_output++;
			continue;
		case 'B':
			baudrate = optarg;
			continue;
		case 'd':
			target_fd = atoi(optarg);
			continue;
		case 'l':
			logfname = optarg;
			continue;
		case 'P':
			if (find_bootctrl_entry(optarg) < 0)
				exit(1);	/* error msg already printed */
			continue;
		case 's':
			socket_pathname = optarg;
			continue;
		case 'S':
			socketpair_fd = atoi(optarg);
			continue;
		case 'v':
			verbose++;
			continue;
		case 'w':
			wakeup_after_sec = strtoul(optarg, 0, 0);
			continue;
		case 'X':
			extlcd_program = optarg;
			continue;
		case '?':
		default:
usage:			fprintf(stderr,
				"usage: %s [options] ttyport\n", argv[0]);
			exit(1);
		}
	if (bootctrl_etmoff_mode) {
		fprintf(stderr,
			"error: -Petmoff mode is not valid for rvinterf\n");
		exit(1);
	}
	if (target_fd <= 0) {
		if (argc - optind != 1)
			goto usage;
		open_serial_port(argv[optind]);
		set_fixed_baudrate(baudrate);
	}
	max_fd = target_fd;
	if (extlcd_program)
		open_extlcd_pipe();

	set_serial_nonblock(0);
	setlinebuf(stdout);
	if (logfname) {
		logF = fopen(logfname, "w");
		if (!logF) {
			perror(logfname);
			exit(1);
		}
		setlinebuf(logF);
		fprintf(logF, "*** Log of rvinterf session ***\n");
	}
	if (socketpair_fd)
		create_socketpair_client();
	else
		create_listener_socket();
	if (background) {
		c = fork();
		if (c < 0) {
			perror("fork");
			exit(1);
		}
		if (c) {
			printf("rvinterf forked into background (pid %d)\n", c);
			write_pid_file(c);
			exit(0);
		}
	}
	signal(SIGPIPE, SIG_IGN);
	pwon_if_needed();
	for (;;) {
		FD_ZERO(&fds);
		FD_SET(target_fd, &fds);
		if (listener)
			FD_SET(listener, &fds);
		for (clip = &client_head; cli = *clip; ) {
			if (cli->rx_state == 2) {
				close(cli->fd);
				*clip = cli->next;
				free(cli);
				continue;
			}
			FD_SET(cli->fd, &fds);
			clip = &cli->next;
		}
		if (socketpair_fd && !client_head)
			exit(0);
		c = select(max_fd+1, &fds, 0, 0, 0);
		time(&logtime);
		if (c < 0) {
			if (errno == EINTR)
				continue;
			perror("select");
			exit(1);
		}
		if (FD_ISSET(target_fd, &fds))
			process_serial_rx();
		if (listener && FD_ISSET(listener, &fds))
			handle_listener_select();
		for (cli = client_head; cli; cli = cli->next)
			if (FD_ISSET(cli->fd, &fds))
				handle_client_select(cli);
	}
}

handle_rx_packet()
{
	switch (rxpkt[0]) {
	case RVT_RV_HEADER:
		if (rxpkt_len < 6)
			goto unknown;
		if (!no_output || logF)
			print_rv_trace();
		if (client_head)
			forward_rv_trace();
		return;
	case RVT_L1_HEADER:
		if (!no_output || logF)
			print_l1_trace();
		if (client_head)
			forward_nonrvt_pkt();
		return;
	case RVT_L23_HEADER:
		if (!no_output || logF)
			print_g23_trace();
		if (client_head)
			forward_nonrvt_pkt();
		return;
	case RVT_TM_HEADER:
		if (!no_output || logF)
			print_tm_output_new();
		if (client_head)
			forward_nonrvt_pkt();
		return;
	case RVT_AT_HEADER:
		if (!no_output || logF)
			print_ati_output();
		if (client_head)
			forward_nonrvt_pkt();
		return;
	case RVT_EXTUI_HEADER:
		if (rxpkt_len < 5 || !(rxpkt_len & 1))
			goto unknown;
		if (extlcd_program)
			output_to_extlcd();
		else {
			report_extui_packet();
			if (verbose >= 2)
				packet_hex_dump(rxpkt, (unsigned) rxpkt_len,
						output_cont_logpref);
		}
		return;
	case RVT_TCH_HEADER:
		if (!no_output || logF) {
			if (verbose >= 2)
				print_tch_output_raw();
			else
				tch_inc_count_rx();
		}
		if (client_head)
			forward_nonrvt_pkt();
		return;
	case RVT_KEEPALIVE_HEADER:
		if (rxpkt_len != 2 || rxpkt[1] != 'Q')
			goto unknown;
		output_line(keepalive_msg);
		send_pkt_to_target(keepalive_answer, 2);
		return;
	case '*':
		print_fc_lld_msg();
		return;
	default:
	unknown:
		print_unknown_packet();
	}
}