257 lines
4.8 KiB
C
257 lines
4.8 KiB
C
/*
|
|
* Copyright © 2008 Keith Packard <keithp@keithp.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "ao-dbg.h"
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <signal.h>
|
|
#include <stdarg.h>
|
|
#include <poll.h>
|
|
#include <getopt.h>
|
|
|
|
static int s51_port = 0;
|
|
static char *cpu = "8051";
|
|
static double freq = 11059200;
|
|
char *s51_prompt = "> ";
|
|
struct ccdbg *s51_dbg;
|
|
int s51_interrupted = 0;
|
|
int s51_monitor = 0;
|
|
char *s51_tty = NULL;
|
|
char *s51_device = NULL;
|
|
|
|
static FILE *s51_input;
|
|
static FILE *s51_output;
|
|
|
|
static void
|
|
usage(void)
|
|
{
|
|
fprintf(stderr, "You're doing it wrong.\n");
|
|
exit(1);
|
|
}
|
|
|
|
static void
|
|
s51_sigint(int signum)
|
|
{
|
|
s51_interrupted = 1;
|
|
}
|
|
|
|
static const struct option options[] = {
|
|
{ .name = "tty", .has_arg = 1, .val = 'T' },
|
|
{ .name = "device", .has_arg = 1, .val = 'D' },
|
|
{ 0, 0, 0, 0 },
|
|
};
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
char *endptr;
|
|
|
|
while ((opt = getopt_long(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:T:", options, NULL)) != -1) {
|
|
switch (opt) {
|
|
case 't':
|
|
cpu = optarg;
|
|
break;
|
|
case 'X':
|
|
freq = strtod(optarg, &endptr);
|
|
if (endptr == optarg)
|
|
usage();
|
|
if (endptr[0] != '\0') {
|
|
if (!strcmp(endptr, "k"))
|
|
freq *= 1000;
|
|
else if (!strcmp(endptr, "M") )
|
|
freq *= 1000000;
|
|
else
|
|
usage ();
|
|
}
|
|
break;
|
|
case 'c':
|
|
break;
|
|
case 'r':
|
|
case 'Z':
|
|
s51_port = strtol(optarg, &endptr, 0);
|
|
if (endptr == optarg || strlen(endptr) != 0)
|
|
usage();
|
|
break;
|
|
case 's':
|
|
break;
|
|
case 'S':
|
|
break;
|
|
case 'p':
|
|
s51_prompt = optarg;
|
|
break;
|
|
case 'P':
|
|
s51_prompt = NULL;
|
|
break;
|
|
case 'V':
|
|
break;
|
|
case 'v':
|
|
break;
|
|
case 'H':
|
|
exit (0);
|
|
break;
|
|
case 'h':
|
|
usage ();
|
|
break;
|
|
case 'm':
|
|
s51_monitor = 1;
|
|
break;
|
|
case 'T':
|
|
s51_tty = optarg;
|
|
break;
|
|
case 'D':
|
|
s51_device = optarg;
|
|
break;
|
|
}
|
|
}
|
|
if (s51_port) {
|
|
int l, r, one = 1;
|
|
int s;
|
|
struct sockaddr_in in;
|
|
|
|
l = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (l < 0) {
|
|
perror ("socket");
|
|
exit(1);
|
|
}
|
|
r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int));
|
|
if (r) {
|
|
perror("setsockopt");
|
|
exit(1);
|
|
}
|
|
in.sin_family = AF_INET;
|
|
in.sin_port = htons(s51_port);
|
|
in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
r = bind(l, (struct sockaddr *) &in, sizeof (in));
|
|
if (r) {
|
|
perror("bind");
|
|
exit(1);
|
|
}
|
|
r = listen(l, 5);
|
|
if (r) {
|
|
perror("listen");
|
|
exit(1);
|
|
}
|
|
for (;;) {
|
|
struct sockaddr_in client_addr;
|
|
socklen_t client_len = sizeof (struct sockaddr_in);
|
|
|
|
s = accept(l, (struct sockaddr *)
|
|
&client_addr, &client_len);
|
|
if (s < 0) {
|
|
perror("accept");
|
|
exit(1);
|
|
}
|
|
s51_input = fdopen(s, "r");
|
|
s51_output = fdopen(s, "w");
|
|
if (!s51_input || !s51_output) {
|
|
perror("fdopen");
|
|
exit(1);
|
|
}
|
|
signal(SIGINT, SIG_IGN);
|
|
command_read();
|
|
signal(SIGINT, SIG_DFL);
|
|
fclose(s51_input);
|
|
fclose(s51_output);
|
|
}
|
|
} else {
|
|
s51_input = stdin;
|
|
s51_output = stdout;
|
|
signal(SIGINT, s51_sigint);
|
|
command_read();
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
void
|
|
s51_printf(char *format, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
vfprintf(s51_output, format, ap);
|
|
if (s51_monitor)
|
|
vfprintf(stdout, format, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void
|
|
s51_putc(int c)
|
|
{
|
|
putc(c, s51_output);
|
|
}
|
|
|
|
#if HAVE_LIBREADLINE
|
|
#include <readline/readline.h>
|
|
#include <readline/history.h>
|
|
#endif
|
|
|
|
int
|
|
s51_read_line(char *line, int len)
|
|
{
|
|
int ret;
|
|
#if HAVE_LIBREADLINE
|
|
if (s51_output == stdout && s51_input == stdin && s51_prompt) {
|
|
char *r;
|
|
|
|
r = readline(s51_prompt);
|
|
if (r == NULL)
|
|
return 0;
|
|
strncpy (line, r, len);
|
|
line[len-1] = '\0';
|
|
add_history(r);
|
|
return 1;
|
|
} else
|
|
#endif
|
|
{
|
|
if (s51_prompt)
|
|
s51_printf("%s", s51_prompt);
|
|
else
|
|
s51_putc('\0');
|
|
fflush(s51_output);
|
|
ret = fgets(line, len, s51_input) != NULL;
|
|
if (s51_monitor)
|
|
printf("> %s", line);
|
|
fflush(stdout);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
s51_check_input(void)
|
|
{
|
|
struct pollfd input;
|
|
int r;
|
|
|
|
input.fd = fileno(s51_input);
|
|
input.events = POLLIN;
|
|
r = poll(&input, 1, 0);
|
|
if (r > 0) {
|
|
char line[256];
|
|
(void) s51_read_line(line, sizeof (line));
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|