1
2 /*
3 * run_test.c - Read a set of Speech Dispatcher commands and try them
4 *
5 * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 *
20 * $Id: run_test.c,v 1.14 2008-02-08 10:01:08 hanke Exp $
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <ctype.h>
37 #include <errno.h>
38 #include <glib.h>
39
40 #define FATAL(msg) { printf(msg"\n"); exit(1); }
41
42 int sockk;
43
44 #ifndef HAVE_STRCASESTR
45 /* Added by Willie Walker - strcasestr is a common but non-standard extension
46 */
strcasestr(const char * a,const char * b)47 char *strcasestr(const char *a, const char *b)
48 {
49 size_t l;
50 char f[3];
51
52 snprintf(f, sizeof(f), "%c%c", tolower(*b), toupper(*b));
53 for (l = strcspn(a, f); l != strlen(a); l += strcspn(a + l + 1, f) + 1)
54 if (strncasecmp(a + l, b, strlen(b)) == 0)
55 return (a + l);
56 return NULL;
57 }
58 #endif /* HAVE_STRCASESTR */
59
send_data(int fd,char * message,int wfr)60 char *send_data(int fd, char *message, int wfr)
61 {
62 char *reply;
63 int bytes;
64
65 /* TODO: 1000?! */
66 reply = (char *)malloc(sizeof(char) * 1000);
67
68 /* write message to the socket */
69 if (!write(fd, message, strlen(message))) {
70 fprintf(stderr, "send_data filed: %s", strerror(errno));
71 }
72
73 /* read reply to the buffer */
74 if (wfr == 1) {
75 bytes = read(fd, reply, 1000);
76 /* print server reply to as a string */
77 reply[bytes] = 0;
78 } else {
79 return "";
80 }
81
82 return reply;
83 }
84
wait_for(int fd,char * event)85 void wait_for(int fd, char *event)
86 {
87 char *reply;
88 int bytes;
89
90 printf(" Waiting for: |%s|\n", event);
91 reply = (char *)malloc(sizeof(char) * 1000);
92 reply[0] = 0;
93 while (0 == strcasestr(reply, event)) {
94 bytes = read(fd, reply, 1000);
95 if (bytes > 0) {
96 reply[bytes] = 0;
97 printf(" < %s\n", reply);
98 fflush(NULL);
99 }
100 }
101 free(reply);
102 printf(" Continuing.\n");
103 fflush(NULL);
104 }
105
106 /*
107 * set_socket_path: establish the pathname that our Unix socket should
108 * have. If the SPEECHD_SOCKET environment variable is set, then that
109 * will be our pathname. Otherwise, the pathname
110 * is $XDG_RUNTIME_DIR/speech-dispatcher/speechd.sock.
111 */
112
set_socket_path(struct sockaddr_un * address)113 void set_socket_path(struct sockaddr_un *address)
114 {
115 size_t path_max = sizeof(address->sun_path);
116 const char *path;
117 char *pathcopy = NULL;
118
119 path = g_getenv("SPEECHD_SOCKET");
120 if (path == NULL || path[0] == '\0') {
121 pathcopy = g_build_filename(g_get_user_runtime_dir(),
122 "speech-dispatcher",
123 "speechd.sock", NULL);
124 path = pathcopy;
125 }
126
127 strncpy(address->sun_path, path, path_max - 1);
128 address->sun_path[path_max - 1] = '\0';
129
130 g_free(pathcopy);
131 }
132
133 /*
134 * init: create and connect our Unix-domain socket.
135 * Returns the file descriptor of the socket on success, or -1 on
136 * failure.
137 */
138
init(void)139 int init(void)
140 {
141 int sockfd;
142 int connect_success;
143 struct sockaddr_un address;
144
145 set_socket_path(&address);
146 address.sun_family = AF_UNIX;
147 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
148 if (sockfd != -1) {
149 connect_success =
150 connect(sockfd, (struct sockaddr *)&address,
151 SUN_LEN(&address));
152 if (connect_success == -1) {
153 close(sockfd);
154 sockfd = -1;
155 }
156 }
157
158 return sockfd;
159 }
160
main(int argc,char * argv[])161 int main(int argc, char *argv[])
162 {
163 char *line;
164 char *command;
165 char *reply;
166 int i;
167 char *ret;
168 FILE *test_file = NULL;
169 int delays = 1;
170 int indent = 0;
171
172 if (argc < 2) {
173 printf("No test script specified!\n");
174 exit(1);
175 }
176
177 if (!strcmp(argv[1], "stdin")) {
178 test_file = stdin;
179 } else {
180 test_file = fopen(argv[1], "r");
181 if (test_file == NULL)
182 FATAL("Test file doesn't exist");
183 }
184
185 if (argc == 3) {
186 if (!strcmp(argv[2], "fast"))
187 delays = 0;
188 else {
189 printf("Unrecognized parameter\n");
190 exit(1);
191 }
192 }
193
194 printf("Start of the test.\n");
195 printf("==================\n\n");
196
197 line = malloc(1024 * sizeof(char));
198 reply = malloc(4096 * sizeof(char));
199
200 sockk = init();
201 if (sockk == -1)
202 FATAL("Can't connect to Speech Dispatcher");
203
204 assert(line != 0);
205
206 while (1) {
207 ret = fgets(line, 1024, test_file);
208 if (ret == NULL)
209 break;
210 if (strlen(line) <= 1) {
211 printf("\n");
212 continue;
213 }
214
215 if (line[0] == '@') {
216 command = (char *)strtok(line, "@\r\n");
217 if (command == NULL)
218 printf("\n");
219 else
220 printf(" %s\n", command);
221 continue;
222 }
223
224 if (line[0] == '!') {
225 command = (char *)strtok(line, "!\r\n");
226 strcat(command, "\r\n");
227 if (command == NULL)
228 continue;
229
230 printf(" >> %s", command);
231 fflush(NULL);
232 reply = send_data(sockk, command, 1);
233 printf(" < %s", reply);
234 fflush(NULL);
235 continue;
236 }
237
238 if (line[0] == '.') {
239 reply = send_data(sockk, "\r\n.\r\n", 1);
240 printf(" < %s", reply);
241 continue;
242 }
243
244 if (line[0] == '+') {
245 command = (char *)strtok(&(line[1]), "+\r\n");
246 wait_for(sockk, command);
247 continue;
248 }
249
250 if (line[0] == '$') {
251 if (delays) {
252 command = (char *)strtok(&(line[1]), "$\r\n");
253 sleep(atoi(command));
254 }
255 continue;
256 }
257
258 if (line[0] == '^') {
259 if (delays) {
260 command = (char *)strtok(&(line[1]), "$\r\n");
261 usleep(atol(command));
262 }
263 continue;
264 }
265
266 if (line[0] == '~') {
267 command = (char *)strtok(line, "~\r\n");
268 indent = atoi(command);
269 continue;
270 }
271
272 if (line[0] == '?') {
273 getc(stdin);
274 continue;
275 }
276
277 if (line[0] == '*') {
278 int ret = system("clear");
279 if (ret == -1)
280 FATAL("Could not execute subprocess");
281 for (i = 0; i <= indent - 1; i++) {
282 printf("\n");
283 }
284 continue;
285 }
286
287 if (line[0] == '#') {
288 /* Comment */
289 continue;
290 }
291
292 send_data(sockk, line, 0);
293 printf(" >> %s", line);
294 }
295
296 close(sockk);
297
298 printf("\n==================\n");
299 printf("End of the test.\n");
300 exit(0);
301 }
302