25eca54b149cb7dae8ec654721ddd4ca043cbfd9
[fw/altos] / ao-tools / ao-dbg / ao-dbg-main.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "ao-dbg.h"
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <poll.h>
31 #include <getopt.h>
32
33 static int s51_port = 0;
34 static char *cpu = "8051";
35 static double freq = 11059200;
36 char *s51_prompt = "> ";
37 struct ccdbg *s51_dbg;
38 int s51_interrupted = 0;
39 int s51_monitor = 0;
40 char *s51_tty = NULL;
41 char *s51_device = NULL;
42
43 static FILE *s51_input;
44 static FILE *s51_output;
45
46 static void
47 usage(void)
48 {
49         fprintf(stderr, "You're doing it wrong.\n");
50         exit(1);
51 }
52
53 void s51_sigint()
54 {
55         s51_interrupted = 1;
56 }
57
58 static const struct option options[] = {
59         { .name = "tty", .has_arg = 1, .val = 'T' },
60         { .name = "device", .has_arg = 1, .val = 'D' },
61         { 0, 0, 0, 0 },
62 };
63
64 int
65 main(int argc, char **argv)
66 {
67         int flags, opt;
68         char *endptr;
69         struct sigvec vec, ovec;
70
71         while ((opt = getopt_long(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:T:", options, NULL)) != -1) {
72                 switch (opt) {
73                 case 't':
74                         cpu = optarg;
75                         break;
76                 case 'X':
77                         freq = strtod(optarg, &endptr);
78                         if (endptr == optarg)
79                                 usage();
80                         if (endptr[0] != '\0') {
81                                 if (!strcmp(endptr, "k"))
82                                         freq *= 1000;
83                                 else if (!strcmp(endptr, "M") )
84                                         freq *= 1000000;
85                                 else
86                                         usage ();
87                         }
88                         break;
89                 case 'c':
90                         break;
91                 case 'r':
92                 case 'Z':
93                         s51_port = strtol(optarg, &endptr, 0);
94                         if (endptr == optarg || strlen(endptr) != 0)
95                                 usage();
96                         break;
97                 case 's':
98                         break;
99                 case 'S':
100                         break;
101                 case 'p':
102                         s51_prompt = optarg;
103                         break;
104                 case 'P':
105                         s51_prompt = NULL;
106                         break;
107                 case 'V':
108                         break;
109                 case 'v':
110                         break;
111                 case 'H':
112                         exit (0);
113                         break;
114                 case 'h':
115                         usage ();
116                         break;
117                 case 'm':
118                         s51_monitor = 1;
119                         break;
120                 case 'T':
121                         s51_tty = optarg;
122                         break;
123                 case 'D':
124                         s51_device = optarg;
125                         break;
126                 }
127         }
128         if (s51_port) {
129                 int l, r, one = 1;
130                 int s;
131                 struct sockaddr_in in;
132
133                 l = socket(AF_INET, SOCK_STREAM, 0);
134                 if (l < 0) {
135                         perror ("socket");
136                         exit(1);
137                 }
138                 r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int));
139                 if (r) {
140                         perror("setsockopt");
141                         exit(1);
142                 }
143                 in.sin_family = AF_INET;
144                 in.sin_port = htons(s51_port);
145                 in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
146                 r = bind(l, (struct sockaddr *) &in, sizeof (in));
147                 if (r) {
148                         perror("bind");
149                         exit(1);
150                 }
151                 r = listen(l, 5);
152                 if (r) {
153                         perror("listen");
154                         exit(1);
155                 }
156                 for (;;) {
157                         struct sockaddr_in client_addr;
158                         socklen_t client_len = sizeof (struct sockaddr_in);
159
160                         s = accept(l, (struct sockaddr *)
161                                    &client_addr, &client_len);
162                         if (s < 0) {
163                                 perror("accept");
164                                 exit(1);
165                         }
166                         s51_input = fdopen(s, "r");
167                         s51_output = fdopen(s, "w");
168                         if (!s51_input || !s51_output) {
169                                 perror("fdopen");
170                                 exit(1);
171                         }
172                         vec.sv_handler = SIG_IGN;
173                         vec.sv_mask = 0;
174                         vec.sv_flags = 0;
175                         sigvec(SIGINT, &vec, &ovec);
176                         command_read();
177                         sigvec(SIGINT, &ovec, NULL);
178                         fclose(s51_input);
179                         fclose(s51_output);
180                 }
181         } else {
182                 s51_input = stdin;
183                 s51_output = stdout;
184                 vec.sv_handler = s51_sigint;
185                 vec.sv_mask = 0;
186                 vec.sv_flags = 0;
187                 sigvec(SIGINT, &vec, &ovec);
188                 command_read();
189         }
190         exit(0);
191 }
192
193 void
194 s51_printf(char *format, ...)
195 {
196         va_list ap;
197
198         va_start(ap, format);
199         vfprintf(s51_output, format, ap);
200         if (s51_monitor)
201                 vfprintf(stdout, format, ap);
202         va_end(ap);
203 }
204
205 void
206 s51_putc(int c)
207 {
208         putc(c, s51_output);
209 }
210
211 #if HAVE_LIBREADLINE
212 #include <readline/readline.h>
213 #include <readline/history.h>
214 #endif
215
216 int
217 s51_read_line(char *line, int len)
218 {
219         int ret;
220 #if HAVE_LIBREADLINE
221         if (s51_output == stdout && s51_input == stdin && s51_prompt) {
222                 char *r;
223
224                 r = readline(s51_prompt);
225                 if (r == NULL)
226                         return 0;
227                 strncpy (line, r, len);
228                 line[len-1] = '\0';
229                 add_history(r);
230                 return 1;
231         } else
232 #endif
233         {
234                 if (s51_prompt)
235                         s51_printf("%s", s51_prompt);
236                 else
237                         s51_putc('\0');
238                 fflush(s51_output);
239                 ret = fgets(line, len, s51_input) != NULL;
240                 if (s51_monitor)
241                         printf("> %s", line);
242                 fflush(stdout);
243         }
244         return ret;
245 }
246
247 int
248 s51_check_input(void)
249 {
250         struct pollfd   input;
251         int r;
252         int c;
253
254         input.fd = fileno(s51_input);
255         input.events = POLLIN;
256         r = poll(&input, 1, 0);
257         if (r > 0) {
258                 char line[256];
259                 (void) s51_read_line(line, sizeof (line));
260                 return 1;
261         }
262         return 0;
263 }