1 /* main.c
2 * main()
3 * (c) 2002 Mikulas Patocka
4 * This file is a part of the Links program, released under GPL.
5 */
6
7 #include "links.h"
8
9 int retval = RET_OK;
10
11 static void unhandle_basic_signals(struct terminal *);
12 static void poll_fg(void *);
13
14 #ifdef WIN
sig_terminate(void * t_)15 static void sig_terminate(void *t_)
16 {
17 struct terminal *t = (struct terminal *)t_;
18 unhandle_basic_signals(t);
19 terminate_loop = 1;
20 retval = RET_SIGNAL;
21 }
22 #endif
23
sig_intr(void * t_)24 static void sig_intr(void *t_)
25 {
26 struct terminal *t = (struct terminal *)t_;
27 if (!t) {
28 unhandle_basic_signals(t);
29 terminate_loop = 1;
30 } else {
31 unhandle_basic_signals(t);
32 exit_prog(t, NULL, NULL);
33 }
34 }
35
sig_ctrl_c(void * t_)36 static void sig_ctrl_c(void *t_)
37 {
38 if (!is_blocked()) kbd_ctrl_c();
39 }
40
41 #ifdef SIGTTOU
sig_ign(void * x)42 static void sig_ign(void *x)
43 {
44 }
45 #endif
46
47 static struct timer *fg_poll_timer = NULL;
48
sig_tstp(void * t_)49 void sig_tstp(void *t_)
50 {
51 struct terminal *t = (struct terminal *)t_;
52 #if defined(SIGSTOP) && !defined(NO_CTRL_Z)
53 #if defined(SIGCONT) && defined(SIGTTOU) && defined(HAVE_GETPID)
54 pid_t pid, newpid;
55 EINTRLOOP(pid, getpid());
56 #endif
57 if (!F) block_itrm(1);
58 #ifdef G
59 else if (drv->block) drv->block(NULL);
60 #endif
61 #if defined(SIGCONT) && defined(SIGTTOU) && defined(HAVE_GETPID)
62 EINTRLOOP(newpid, fork());
63 if (!newpid) {
64 while (1) {
65 int rr;
66 portable_sleep(1000);
67 EINTRLOOP(rr, kill(pid, SIGCONT));
68 }
69 }
70 #endif
71 {
72 int rr;
73 EINTRLOOP(rr, raise(SIGSTOP));
74 }
75 #if defined(SIGCONT) && defined(SIGTTOU) && defined(HAVE_GETPID)
76 if (newpid != -1) {
77 int rr;
78 EINTRLOOP(rr, kill(newpid, SIGKILL));
79 }
80 #endif
81 #endif
82 if (fg_poll_timer != NULL) kill_timer(fg_poll_timer);
83 fg_poll_timer = install_timer(FG_POLL_TIME, poll_fg, t);
84 }
85
poll_fg(void * t_)86 static void poll_fg(void *t_)
87 {
88 struct terminal *t = (struct terminal *)t_;
89 int r = 0;
90 fg_poll_timer = NULL;
91 if (!F) r = unblock_itrm(1);
92 #ifdef G
93 else if (drv->unblock) r = drv->unblock(NULL);
94 #endif
95 if (r == -1) {
96 fg_poll_timer = install_timer(FG_POLL_TIME, poll_fg, t);
97 }
98 if (r == -2) {
99 /* This will unblock externally spawned viewer, if it exists */
100 #ifdef SIGCONT
101 EINTRLOOP(r, kill(0, SIGCONT));
102 #endif
103 }
104 }
105
sig_cont(void * t_)106 void sig_cont(void *t_)
107 {
108 if (!F) unblock_itrm(1);
109 #ifdef G
110 else if (drv->unblock) drv->unblock(NULL);
111 #endif
112 }
113
handle_basic_signals(struct terminal * term)114 static void handle_basic_signals(struct terminal *term)
115 {
116 install_signal_handler(SIGHUP, sig_intr, term, 0);
117 if (!F) install_signal_handler(SIGINT, sig_ctrl_c, term, 0);
118 /*install_signal_handler(SIGTERM, sig_terminate, term, 0);*/
119 #ifdef WIN
120 install_signal_handler(SIGQUIT, sig_terminate, term, 0);
121 #endif
122 #ifdef SIGTSTP
123 if (!F) install_signal_handler(SIGTSTP, sig_tstp, term, 0);
124 #endif
125 #ifdef SIGTTIN
126 if (!F) install_signal_handler(SIGTTIN, sig_tstp, term, 0);
127 #endif
128 #ifdef SIGTTOU
129 install_signal_handler(SIGTTOU, sig_ign, term, 0);
130 #endif
131 #ifdef SIGCONT
132 if (!F) install_signal_handler(SIGCONT, sig_cont, term, 0);
133 #endif
134 }
135
unhandle_terminal_signals(struct terminal * term)136 void unhandle_terminal_signals(struct terminal *term)
137 {
138 install_signal_handler(SIGHUP, NULL, NULL, 0);
139 if (!F) install_signal_handler(SIGINT, NULL, NULL, 0);
140 #ifdef SIGTSTP
141 install_signal_handler(SIGTSTP, NULL, NULL, 0);
142 #endif
143 #ifdef SIGTTIN
144 install_signal_handler(SIGTTIN, NULL, NULL, 0);
145 #endif
146 #ifdef SIGTTOU
147 install_signal_handler(SIGTTOU, NULL, NULL, 0);
148 #endif
149 #ifdef SIGCONT
150 install_signal_handler(SIGCONT, NULL, NULL, 0);
151 #endif
152 if (fg_poll_timer != NULL) kill_timer(fg_poll_timer), fg_poll_timer = NULL;
153 }
154
unhandle_basic_signals(struct terminal * term)155 static void unhandle_basic_signals(struct terminal *term)
156 {
157 install_signal_handler(SIGHUP, NULL, NULL, 0);
158 if (!F) install_signal_handler(SIGINT, NULL, NULL, 0);
159 /*install_signal_handler(SIGTERM, NULL, NULL, 0);*/
160 #ifdef SIGTSTP
161 install_signal_handler(SIGTSTP, NULL, NULL, 0);
162 #endif
163 #ifdef SIGTTIN
164 install_signal_handler(SIGTTIN, NULL, NULL, 0);
165 #endif
166 #ifdef SIGTTOU
167 install_signal_handler(SIGTTOU, NULL, NULL, 0);
168 #endif
169 #ifdef SIGCONT
170 install_signal_handler(SIGCONT, NULL, NULL, 0);
171 #endif
172 if (fg_poll_timer != NULL) kill_timer(fg_poll_timer), fg_poll_timer = NULL;
173 }
174
175 int terminal_pipe[2] = { -1, -1 };
176
attach_terminal(int in,int out,int ctl,void * info,int len)177 int attach_terminal(int in, int out, int ctl, void *info, int len)
178 {
179 struct terminal *term;
180 set_nonblock(terminal_pipe[0]);
181 set_nonblock(terminal_pipe[1]);
182 handle_trm(in, out, out, terminal_pipe[1], ctl, info, len);
183 mem_free(info);
184 if ((term = init_term(terminal_pipe[0], out, win_func))) {
185 handle_basic_signals(term); /* OK, this is race condition, but it must be so; GPM installs it's own buggy TSTP handler */
186 return terminal_pipe[1];
187 }
188 close_socket(&terminal_pipe[0]);
189 close_socket(&terminal_pipe[1]);
190 return -1;
191 }
192
193 #ifdef G
194
attach_g_terminal(unsigned char * cwd,void * info,int len)195 int attach_g_terminal(unsigned char *cwd, void *info, int len)
196 {
197 struct terminal *term;
198 term = init_gfx_term(win_func, cwd, info, len);
199 mem_free(info);
200 return term ? 0 : -1;
201 }
202
gfx_connection(int h)203 void gfx_connection(int h)
204 {
205 int r;
206 unsigned char cwd[MAX_CWD_LEN];
207 unsigned char hold_conn;
208 void *info;
209 int info_len;
210 struct terminal *term;
211
212 if (os_send_fg_cookie(h))
213 goto err_close;
214 if (hard_read(h, cwd, MAX_CWD_LEN) != MAX_CWD_LEN)
215 goto err_close;
216 cwd[MAX_CWD_LEN - 1] = 0;
217 if (hard_read(h, &hold_conn, 1) != 1)
218 goto err_close;
219 if (hard_read(h, (unsigned char *)&info_len, sizeof(int)) != sizeof(int) || info_len < 0)
220 goto err_close;
221 info = mem_alloc(info_len);
222 if (hard_read(h, info, info_len) != info_len)
223 goto err_close_free;
224 term = init_gfx_term(win_func, cwd, info, info_len);
225 if (term) {
226 if (hold_conn) {
227 term->handle_to_close = h;
228 } else {
229 hard_write(h, cast_uchar "x", 1);
230 EINTRLOOP(r, close(h));
231 }
232 mem_free(info);
233 return;
234 }
235 err_close_free:
236 mem_free(info);
237 err_close:
238 EINTRLOOP(r, close(h));
239 }
240
gfx_connection_terminate(void * p)241 static void gfx_connection_terminate(void *p)
242 {
243 int h = (int)(my_intptr_t)p;
244 set_handlers(h, NULL, NULL, NULL);
245 terminate_loop = 1;
246 }
247
248 #endif
249
250 static struct object_request *dump_obj;
251 static off_t dump_pos;
252
end_dump(struct object_request * r,void * p)253 static void end_dump(struct object_request *r, void *p)
254 {
255 struct cache_entry *ce;
256 int oh;
257 if (!r->state || (r->state == 1 && dmp != D_SOURCE)) return;
258 if ((oh = get_output_handle()) == -1) return;
259 ce = r->ce;
260 if (dmp == D_SOURCE) {
261 if (ce) {
262 struct fragment *frag;
263 struct list_head *lfrag;
264 nextfrag:
265 foreach(struct fragment, frag, lfrag, ce->frag) if (frag->offset <= dump_pos && frag->offset + frag->length > dump_pos) {
266 off_t l;
267 int w;
268 l = frag->length - (dump_pos - frag->offset);
269 if (l >= MAXINT) l = MAXINT;
270 w = hard_write(oh, frag->data + dump_pos - frag->offset, (int)l);
271 if (w != l) {
272 unsigned char *msg = strerror_alloc(errno, NULL);
273 detach_object_connection(r, dump_pos);
274 if (w < 0) fprintf(stderr, "Error writing to stdout: %s.\n", msg);
275 else fprintf(stderr, "Can't write to stdout.\n");
276 mem_free(msg);
277 retval = RET_ERROR;
278 goto terminate;
279 }
280 dump_pos += w;
281 detach_object_connection(r, dump_pos);
282 goto nextfrag;
283 }
284 }
285 if (r->state >= 0) return;
286 } else if (ce) {
287 struct document_options o;
288 struct f_data_c *fd;
289 int err;
290 fd = create_f_data_c(NULL, NULL);
291 memset(&o, 0, sizeof(struct document_options));
292 o.xp = 0;
293 o.yp = 1;
294 o.xw = screen_width;
295 o.yw = 25;
296 o.col = 0;
297 o.cp = get_commandline_charset();
298 ds2do(&dds, &o, 0);
299 o.plain = 0;
300 o.frames = 0;
301 o.js_enable = 0;
302 o.framename = cast_uchar "";
303 if (!casecmp(r->url, cast_uchar "file://", 7) && !o.hard_assume) {
304 o.assume_cp = get_commandline_charset();
305 }
306 if (!(fd->f_data = cached_format_html(fd, r, r->url, &o, NULL, 0))) goto term_1;
307 if ((err = dump_to_file(fd->f_data, oh))) {
308 fprintf(stderr, "Error writing to stdout: %s.\n", get_err_msg(err, NULL));
309 retval = RET_ERROR;
310 }
311 term_1:
312 reinit_f_data_c(fd);
313 mem_free(fd);
314 }
315 if (r->state != O_OK) {
316 unsigned char *m = get_err_msg(r->stat.state, NULL);
317 fprintf(stderr, "%s\n", get_english_translation(m));
318 retval = RET_ERROR;
319 goto terminate;
320 }
321 terminate:
322 terminate_loop = 1;
323 }
324
325 int g_argc;
326 char **g_argv;
327
328 unsigned char *path_to_exe;
329
330 static unsigned char init_b = 0;
331
332 static void initialize_all_subsystems(void);
333 static void initialize_all_subsystems_2(void);
334
fixup_g(void)335 static void fixup_g(void)
336 {
337 if (ggr_drv[0] || ggr_mode[0] || force_g) ggr = 1;
338 if (dmp) ggr = 0;
339 }
340
init(void)341 static void init(void)
342 {
343 int uh;
344 void *info;
345 int len;
346 unsigned char *u;
347
348 initialize_all_subsystems();
349
350 /* OS/2 has some stupid bug and the pipe must be created before socket :-/ */
351 if (c_pipe(terminal_pipe)) {
352 fatal_exit("ERROR: can't create pipe for internal communication");
353 }
354 if (!(u = parse_options(g_argc - 1, g_argv + 1))) {
355 retval = RET_SYNTAX;
356 goto ttt;
357 }
358 fixup_g();
359 if (!dmp && !ggr) {
360 init_os_terminal();
361 }
362 if (!ggr && !no_connect && (uh = bind_to_af_unix(NULL)) != -1) {
363 close_socket(&terminal_pipe[0]);
364 close_socket(&terminal_pipe[1]);
365 info = create_session_info(base_session, u, default_target, &len);
366 initialize_all_subsystems_2();
367 handle_trm(get_input_handle(), get_output_handle(), uh, uh, get_ctl_handle(), info, len);
368 handle_basic_signals(NULL); /* OK, this is race condition, but it must be so; GPM installs it's own buggy TSTP handler */
369 mem_free(info);
370 #if defined(HAVE_MALLOC_TRIM)
371 malloc_trim(8192);
372 #endif
373 return;
374 }
375 if ((dds.assume_cp = get_cp_index(cast_uchar "ISO-8859-1")) == -1) dds.assume_cp = 0;
376 load_config();
377 if (proxies.only_proxies)
378 reset_settings_for_tor();
379 u = parse_options(g_argc - 1, g_argv + 1);
380 fixup_g();
381 if (!u) {
382 ttt:
383 initialize_all_subsystems_2();
384 tttt:
385 terminate_loop = 1;
386 return;
387 }
388 init_cookies();
389 if (!dmp) {
390 if (ggr) {
391 close_socket(&terminal_pipe[0]);
392 close_socket(&terminal_pipe[1]);
393 #ifdef G
394 {
395 unsigned char *r;
396 if ((r = init_graphics(ggr_drv, ggr_mode, ggr_display))) {
397 fprintf(stderr, "%s", r);
398 mem_free(r);
399 retval = RET_SYNTAX;
400 goto ttt;
401 }
402 handle_basic_signals(NULL);
403 if (drv->get_af_unix_name && !no_connect) {
404 unsigned char *n = stracpy(drv->name);
405 unsigned char *nn = drv->get_af_unix_name();
406 if (*nn) {
407 add_to_strn(&n, cast_uchar "-");
408 add_to_strn(&n, nn);
409 }
410 uh = bind_to_af_unix(n);
411 mem_free(n);
412 if (uh != -1) {
413 unsigned char hold_conn;
414 unsigned char *w;
415 int lw;
416 shutdown_graphics();
417 if (os_receive_fg_cookie(uh)) {
418 retval = RET_ERROR;
419 goto ttt;
420 }
421 w = get_cwd();
422 if (!w) w = stracpy(cast_uchar "");
423 if (strlen(cast_const_char w) >= MAX_CWD_LEN)
424 w[MAX_CWD_LEN - 1] = 0;
425 lw = (int)strlen(cast_const_char w) + 1;
426 if (hard_write(uh, w, lw) != lw) {
427 mem_free(w);
428 retval = RET_ERROR;
429 goto ttt;
430 }
431 mem_free(w);
432 w = mem_calloc(MAX_CWD_LEN - lw);
433 if (hard_write(uh, w, MAX_CWD_LEN - lw) != MAX_CWD_LEN - lw) {
434 mem_free(w);
435 retval = RET_ERROR;
436 goto ttt;
437 }
438 mem_free(w);
439 hold_conn = *u != 0;
440 if (hard_write(uh, &hold_conn, 1) != 1) {
441 retval = RET_ERROR;
442 goto ttt;
443 }
444 info = create_session_info(base_session, u, default_target, &len);
445 if (hard_write(uh, (unsigned char *)&len, sizeof len) != sizeof len) {
446 mem_free(info);
447 retval = RET_ERROR;
448 goto ttt;
449 }
450 if (hard_write(uh, info, len) != len) {
451 mem_free(info);
452 retval = RET_ERROR;
453 goto ttt;
454 }
455 mem_free(info);
456 set_handlers(uh, gfx_connection_terminate, NULL, (void *)(my_intptr_t)uh);
457 initialize_all_subsystems_2();
458 heap_trim();
459 return;
460 }
461 }
462 init_dither(drv->depth);
463 fontconfig_init();
464 freetype_init();
465 }
466 #else
467 fprintf(stderr, "Graphics not enabled when compiling\n");
468 retval = RET_SYNTAX;
469 goto ttt;
470 #endif
471 }
472 init_b = 1;
473 init_bookmarks();
474 create_initial_extensions();
475 load_url_history();
476 initialize_all_subsystems_2();
477 info = create_session_info(base_session, u, default_target, &len);
478 if (!F) {
479 if (attach_terminal(get_input_handle(), get_output_handle(), get_ctl_handle(), info, len) < 0)
480 fatal_exit("Could not open initial session");
481 }
482 #ifdef G
483 else {
484 unsigned char *cwd = get_cwd();
485 if (!cwd)
486 cwd = stracpy(cast_uchar "");
487 if (attach_g_terminal(cwd, info, len) < 0)
488 fatal_exit("Could not open initial session");
489 mem_free(cwd);
490 }
491 #endif
492 } else {
493 unsigned char *uu, *uuu, *wd;
494 initialize_all_subsystems_2();
495 close_socket(&terminal_pipe[0]);
496 close_socket(&terminal_pipe[1]);
497 if (!*u) {
498 fprintf(stderr, "URL expected after %s\n", dmp == D_DUMP ? "-dump" : "-source");
499 retval = RET_SYNTAX;
500 goto tttt;
501 }
502 uu = convert(get_commandline_charset(), utf8_table, u, NULL);
503 if (!(uuu = translate_url(uu, wd = get_cwd()))) uuu = stracpy(uu);
504 mem_free(uu);
505 request_object(NULL, uuu, NULL, PRI_MAIN, NC_RELOAD, ALLOW_ALL, end_dump, NULL, &dump_obj);
506 mem_free(uuu);
507 if (wd) mem_free(wd);
508 }
509 }
510
511 /* Is called before gaphics driver init */
initialize_all_subsystems(void)512 static void initialize_all_subsystems(void)
513 {
514 init_charset();
515 init_trans();
516 set_sigcld();
517 init_home();
518 init_dns();
519 init_session_cache();
520 init_cache();
521 init_blocks();
522 memset(&dd_opt, 0, sizeof dd_opt);
523 }
524
525 /* Is called sometimes after and sometimes before graphics driver init */
initialize_all_subsystems_2(void)526 static void initialize_all_subsystems_2(void)
527 {
528 GF(init_dip());
529 init_bfu();
530 GF(init_imgcache());
531 init_fcache();
532 GF(init_grview());
533 }
534
terminate_all_subsystems(void)535 static void terminate_all_subsystems(void)
536 {
537 check_bottom_halves();
538 abort_all_downloads();
539 check_bottom_halves();
540 destroy_all_terminals();
541 check_bottom_halves();
542 shutdown_bfu();
543 if (!F) free_all_itrms();
544 release_object(&dump_obj);
545 abort_all_connections();
546
547 free_all_caches();
548 #ifdef HAVE_SSL
549 ssl_finish();
550 #endif
551 if (init_b) save_url_history();
552 free_history_lists();
553 free_term_specs();
554 free_types();
555 free_blocks();
556 finalize_bookmarks();
557 free_conv_table();
558 free_blacklist();
559 do_save_cookies();
560 free_cookies();
561 free_auth();
562 check_bottom_halves();
563 end_config();
564 free_strerror_buf();
565 shutdown_trans();
566 GF(freetype_done());
567 GF(free_dither());
568 GF(shutdown_graphics());
569 af_unix_close();
570 os_free_clipboard();
571 if (fg_poll_timer != NULL) kill_timer(fg_poll_timer), fg_poll_timer = NULL;
572 terminate_select();
573 terminate_osdep();
574 }
575
main(int argc,char * argv[])576 int main(int argc, char *argv[])
577 {
578 g_argc = argc;
579 g_argv = (char **)argv; /* we fix this up in init_os in vms.c */
580
581 #if 0
582 if (argc != 3)
583 fprintf(stderr, "two args expected\n"), exit(1);
584 printf("cookie %saccepted\n", allow_cookie_domain(cast_uchar argv[1], cast_uchar argv[2]) ? "" : "not ");
585 return 0;
586 #endif
587 #if 0
588 {
589 unsigned char a[216];
590 double dist[216];
591 int i;
592 memset(&a, 0, sizeof a);
593 for (i = 0; i < 216; i++) dist[i] = 1e30;
594 for (i = 0; i < 216; i++) {
595 int j, b = -1;
596 double maxdist = 0;
597 for (j = 0; j < 216; j++) {
598 if ((j / 36 == 0 || j / 36 == 5) &&
599 (j / 6 % 6 == 0 || j / 6 % 6 == 5) &&
600 (j % 6 == 0 || j % 6 == 5))
601 if (dist[j] && dist[j] > maxdist) {
602 maxdist = dist[j];
603 b = j;
604 }
605 }
606 if (b == -1) for (j = 0; j < 216; j++) {
607 if (dist[j] > maxdist) {
608 maxdist = dist[j];
609 b = j;
610 }
611 }
612 for (j = 0; j < 216; j++) {
613 double d;
614 unsigned rgb1[3];
615 unsigned rgb2[3];
616 q_palette(216, b, 65535, rgb1);
617 q_palette(216, j, 65535, rgb2);
618 d = rgb_distance(rgb1[0], rgb1[1], rgb1[2], rgb2[0], rgb2[1], rgb2[2]);
619 if (d < dist[j])
620 dist[j] = d;
621 }
622 fprintf(stderr, "%d: (%d, %d, %d)\n", b, b / 36, b / 6 % 6, b % 6);
623 }
624 return 0;
625 }
626 #endif
627
628 init_page_size();
629 init_heap();
630 init_os();
631 get_path_to_exe();
632
633 #if 0
634 {
635 int i;
636 int ix, iy, ox, oy, rep;
637 ulonglong tm = 0;
638 parse_options(g_argc - 1, g_argv + 1);
639 ix = getenv("SRC_X") ? atoi(getenv("SRC_X")) : 100;
640 iy = getenv("SRC_Y") ? atoi(getenv("SRC_Y")) : ix;
641 ox = getenv("DST_X") ? atoi(getenv("DST_X")) : 100;
642 oy = getenv("DST_Y") ? atoi(getenv("DST_Y")) : ox;
643 rep = getenv("REP") ? atoi(getenv("REP")) : 1;
644 for (i = 0; i <= rep; i++) {
645 unsigned short *dst;
646 unsigned short *src;
647 struct timeval tv1, tv2;
648 src = mem_alloc(sizeof(unsigned short) * ix * iy * 3);
649 memset(src, 0x12, sizeof(unsigned short) * ix * iy * 3);
650 gettimeofday(&tv1, NULL);
651 scale_color(src, ix, iy, &dst, ox, oy);
652 gettimeofday(&tv2, NULL);
653 if (dst) mem_free(dst);
654 if (i)
655 tm += ((ulonglong)tv2.tv_sec * 1000000 + tv2.tv_usec) - ((ulonglong)tv1.tv_sec * 1000000 + tv1.tv_usec);
656 }
657 fprintf(stderr, "time: %f\n", (double)tm / 1000 / rep);
658 check_memory_leaks();
659 return 0;
660 }
661 #endif
662 #if 0
663 {
664 int i;
665 for (i = 0; i < 100; i++) {
666 unsigned char *a = mem_calloc(i);
667 unsigned char *b = base64_encode(a, i, cast_uchar "", cast_uchar "", 5);
668 fprintf(stderr, "X:\n%.*s\n", (int)strlen(cast_const_char b), b);
669 mem_free(a);
670 mem_free(b);
671 }
672 check_memory_leaks();
673 return 0;
674 }
675 #endif
676 #if 0
677 {
678 unsigned char *puny_encode(unsigned char *s);
679 unsigned char *puny_decode(unsigned char *s);
680 int i;
681 for (i = 1; i < g_argc; i++) {
682 unsigned char *str = puny_encode(cast_uchar g_argv[i]);
683 if (str) {
684 fprintf(stderr, "'%s'\n", str);
685 unsigned char *d = puny_decode(str);
686 if (!d || strcmp(cast_const_char d, cast_const_char g_argv[i])) {
687 internal_error("mismatch - %s", d);
688 }
689 mem_free(str);
690 mem_free(d);
691 }
692 }
693 check_memory_leaks();
694 return 0;
695 }
696 #endif
697 #if 0
698 while (1) {
699 #define maxn 12
700 static unsigned long long count = 0;
701 unsigned char *puny_encode(unsigned char *s, int len);
702 unsigned char *puny_decode(unsigned char *s, int len);
703 int punycode_encode(size_t input_length, const uint32_t input[], const unsigned char case_flags[], size_t *output_length, char output[]);
704 int punycode_decode(size_t input_length, const char input[], size_t * output_length, uint32_t output[], unsigned char case_flags[]);
705 uint32_t unistr[maxn];
706 unsigned i, n;
707 unsigned char *utfstr, *puny, *dec;
708 int utfstr_l;
709 char pce_o[60];
710 size_t pce_ol;
711 int pce_s;
712 n = random() % (maxn + 1);
713 for (i = 0; i < n; i++) {
714 uint32_t uni;
715 uni = random() % (0x10FFFF + 1);
716 if (uni >= 0xd800 && uni <= 0xdfff)
717 uni = random() % 128;
718 while (uni < 128 && !(
719 uni == '-' ||
720 (uni >= '0' && uni <= '9') ||
721 (uni >= 'A' && uni <= 'Z') ||
722 (uni >= 'a' && uni <= 'z'))) {
723 uni = random() % 128;
724 }
725 unistr[i] = uni;
726 }
727 utfstr = init_str();
728 utfstr_l = 0;
729 for (i = 0; i < n; i++) {
730 unsigned char *us = encode_utf_8(unistr[i]);
731 add_to_str(&utfstr, &utfstr_l, us);
732 }
733 puny = puny_encode(utfstr, utfstr_l);
734 if (!puny) {
735 fprintf(stderr, "failed:");
736 goto err;
737 }
738 dec = puny_decode(puny, (int)strlen(cast_const_char puny));
739 if (!dec)
740 dec = stracpy(puny);
741 if (strcmp(cast_const_char utfstr, cast_const_char dec)) {
742 fprintf(stderr, "mismatch(%s,%s):", utfstr, dec);
743 goto err;
744 }
745 pce_ol = 59;
746 pce_s = punycode_encode(n, unistr, NULL, &pce_ol, pce_o);
747 if (pce_s) {
748 fprintf(stderr, "punycode_encode(%d):", pce_s);
749 goto err;
750 }
751 pce_o[pce_ol] = 0;
752 if (!strncmp(cast_const_char puny, "xn--", 4) && strcmp(cast_const_char puny + 4, pce_o)) {
753 fprintf(stderr, "punycode_encode differs(%s,%s):", puny, pce_o);
754 goto err;
755 }
756 mem_free(dec);
757 mem_free(puny);
758 mem_free(utfstr);
759 if (0) {
760 err:
761 for (i = 0; i < n; i++) {
762 fprintf(stderr, " %u", unistr[i]);
763 }
764 internal_error("failed");
765 }
766 count++;
767 if (!(count % 10000)) {
768 printf("%llu\r", count);
769 fflush(stdout);
770 }
771 }
772 #endif
773
774 select_loop(init);
775 terminate_all_subsystems();
776
777 #if 0
778 {
779 char msg[65536] = "";
780 char *p = msg;
781 int i = 1;
782 while (p - msg < 60000) {
783 sprintf(p, "some text %d (%ld) ", i++, p - msg);
784 p = strchr(p, 0);
785 }
786 error(msg);
787 }
788 #endif
789 check_memory_leaks();
790 return retval;
791 }
792
793