tin  2.6.1
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.6.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

signal.c
Go to the documentation of this file.
1/*
2 * Project : tin - a Usenet reader
3 * Module : signal.c
4 * Author : I.Lea
5 * Created : 1991-04-01
6 * Updated : 2021-09-30
7 * Notes : signal handlers for different modes and window resizing
8 *
9 * Copyright (c) 1991-2022 Iain Lea <iain@bricbrac.de>
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. Neither the name of the copyright holder nor the names of its
24 * contributors may be used to endorse or promote products derived from
25 * this software without specific prior written permission.
26 *
27 * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40
41#ifndef TIN_H
42# include "tin.h"
43#endif /* !TIN_H */
44#ifndef TCURSES_H
45# include "tcurses.h"
46#endif /* !TCURSES_H */
47#ifndef included_trace_h
48# include "trace.h"
49#endif /* !included_trace_h */
50#ifndef VERSION_H
51# include "version.h"
52#endif /* !VERSION_H */
53
54/*
55 * Needed for resizing under an xterm
56 */
57#ifdef HAVE_TERMIOS_H
58# include <termios.h>
59#else
60# ifdef HAVE_TERMIO_H
61# include <termio.h>
62# endif /* HAVE_TERMIO_H */
63#endif /* HAVE_TERMIOS_H */
64
65#ifdef NEED_PTEM_H
66# include <sys/stream.h>
67# include <sys/ptem.h>
68#endif /* NEED_PTEM_H */
69
70#if defined(SIGWINCH) && !defined(DONT_HAVE_SIGWINCH)
71# if !defined(TIOCGWINSZ) && !defined(TIOCGSIZE)
72# ifdef HAVE_SYS_STREAM_H
73# include <sys/stream.h>
74# endif /* HAVE_SYS_STREAM_H */
75# ifdef HAVE_SYS_PTY_H
76# if !defined(_h_BSDTYPES) && defined(HAVE_SYS_BSDTYPES_H)
77# include <sys/bsdtypes.h>
78# endif /* !_h_BSDTYPES && HAVE_SYS_BSDTYPES_H */
79# include <sys/pty.h>
80# endif /* HAVE_SYS_PTY_H */
81# endif /* !TIOCGWINSZ && !TIOCGSIZE */
82#endif /* SIGWINCH && !DONT_HAVE_SIGWINCH */
83
84#ifdef MINIX
85# undef SIGTSTP
86#endif /* MINIX */
87
88/*
89 * local prototypes
90 */
91static const char *signal_name(int code);
92#ifdef SIGTSTP
93 static void handle_suspend(void);
94#endif /* SIGTSTP */
95static void _CDECL signal_handler(SIG_ARGS);
96
97
98#ifdef SIGTSTP
99 static t_bool do_sigtstp = FALSE;
100#endif /* SIGTSTP */
101#if defined(SIGWINCH) || defined(SIGTSTP)
102 static t_bool redraw_after_suspend;
103#endif /* SIGWINCH || SIGTSTP */
104
108/*
109 * # lines of non-static data available for display
110 */
112
113
114#ifndef __LCLINT__ /* lclint doesn't like it */
115static const struct {
116 int code;
117 const char *name;
118} signal_list[] = {
119# ifdef SIGINT
120 { SIGINT, "SIGINT" }, /* ctrl-C */
121# endif /* SIGINT */
122# ifdef SIGQUIT
123 { SIGQUIT, "SIGQUIT" }, /* ctrl-\ */
124# endif /* SIGQUIT */
125# ifdef SIGILL
126 { SIGILL, "SIGILL" }, /* illegal instruction */
127# endif /* SIGILL */
128# ifdef SIGFPE
129 { SIGFPE, "SIGFPE" }, /* floating point exception */
130# endif /* SIGFPE */
131# ifdef SIGBUS
132 { SIGBUS, "SIGBUS" }, /* bus error */
133# endif /* SIGBUS */
134# ifdef SIGSEGV
135 { SIGSEGV, "SIGSEGV" }, /* segmentation violation */
136# endif /* SIGSEGV */
137# ifdef SIGPIPE
138 { SIGPIPE, "SIGPIPE" }, /* broken pipe */
139# endif /* SIGPIPE */
140# ifdef SIGALRM
141 { SIGALRM, "SIGALRM" }, /* real-time timer expired */
142# endif /* SIGALRM */
143# ifdef SIGCHLD
144 { SIGCHLD, "SIGCHLD" }, /* death of a child process */
145# endif /* SIGCHLD */
146# ifdef SIGPWR
147 { SIGPWR, "SIGPWR" }, /* powerfail */
148# endif /* SIGPWR */
149# ifdef SIGTSTP
150 { SIGTSTP, "SIGTSTP" }, /* terminal-stop */
151# endif /* SIGTSTP */
152# ifdef SIGHUP
153 { SIGHUP, "SIGHUP" }, /* hang up */
154# endif /* SIGHUP */
155# ifdef SIGUSR1
156 { SIGUSR1, "SIGUSR1" }, /* User-defined signal 1 */
157# endif /* SIGUSR1 */
158# ifdef SIGUSR2
159 { SIGUSR2, "SIGUSR2" }, /* User-defined signal 2 */
160# endif /* SIGUSR2 */
161# ifdef SIGTERM
162 { SIGTERM, "SIGTERM" }, /* termination */
163# endif /* SIGTERM */
164# if defined(SIGWINCH) && !(defined(USE_CURSES) && defined(KEY_RESIZE))
165 { SIGWINCH, "SIGWINCH" }, /* window-size change */
166# endif /* SIGWINCH && !(USE_CURSES && KEY_RESIZE) */
168#endif /* !__LCLINT__ */
169
170
171#ifdef HAVE_NESTED_PARAMS
172 RETSIGTYPE (*sigdisp(int signum, RETSIGTYPE (_CDECL *func)(SIG_ARGS)))(SIG_ARGS)
173#else
174 RETSIGTYPE (*sigdisp(signum, func))(SIG_ARGS)
175 int signum;
176 RETSIGTYPE (_CDECL *func)(SIG_ARGS);
177#endif /* HAVE_NESTED_PARAMS */
178{
179#ifdef HAVE_POSIX_JC
180# define RESTORE_HANDLER(x, y)
181 struct sigaction sa, osa;
182
183 sa.sa_handler = func;
184 sigemptyset(&sa.sa_mask);
185 sa.sa_flags = 0;
186# ifdef SA_RESTART
187 sa.sa_flags |= SA_RESTART;
188# endif /* SA_RESTART */
189 if (sigaction(signum, &sa, &osa) < 0)
190 return SIG_ERR;
191 return (osa.sa_handler);
192#else
193# define RESTORE_HANDLER(x, y) signal(x, y)
194 return (signal(signum, func));
195#endif /* HAVE_POSIX_JC */
196}
197
198
199/*
200 * Block/unblock SIGWINCH/SIGTSTP restarting syscalls
201 */
202void
204 t_bool allow)
205{
206#ifdef HAVE_POSIX_JC
207 struct sigaction sa, osa;
208
209 sa.sa_handler = signal_handler;
210 sigemptyset(&sa.sa_mask);
211 sa.sa_flags = 0;
212# ifdef SA_RESTART
213 if (!allow)
214 sa.sa_flags |= SA_RESTART;
215# endif /* SA_RESTART */
216# if defined(SIGWINCH) && !(defined(USE_CURSES) && defined(KEY_RESIZE))
217 sigaction(SIGWINCH, &sa, &osa);
218# endif /* SIGWINCH && !(USE_CURSES && KEY_RESIZE) */
219# ifdef SIGTSTP
220 sigaction(SIGTSTP, &sa, &osa);
221# endif /* SIGTSTP */
222#endif /* HAVE_POSIX_JC */
223}
224
225
226static const char *
228 int code)
229{
230 size_t n;
231 const char *name = "unknown";
232
233 for (n = 0; n < ARRAY_SIZE(signal_list); n++) {
234 if (signal_list[n].code == code) {
235 name = signal_list[n].name;
236 break;
237 }
238 }
239 return name;
240}
241
242
243/*
244 * Rescale the display buffer and redraw the contents according to
245 * the current context
246 * This should NOT be called from an interrupt context
247 */
248void
250 t_bool repaint)
251{
252#if defined(SIGWINCH) || defined(SIGTSTP)
253# ifdef SIGWINCH
254 repaint |= set_win_size(&cLINES, &cCOLS);
255# endif /* SIGWINCH */
256
258 ring_bell();
260 }
261
262 TRACE(("handle_resize(%d:%d)", signal_context, repaint));
263
264 if (!repaint)
265 return;
266
267# ifdef USE_CURSES
268# ifdef HAVE_RESIZETERM
269 resizeterm(cLINES + 1, cCOLS);
270 my_retouch(); /* seems necessary if win size unchanged */
271# else
272 my_retouch();
273# endif /* HAVE_RESIZETERM */
274# endif /* USE_CURSES */
275
276 switch (signal_context) {
277 case cArt:
278 ClearScreen();
280 break;
281
282 case cAttrib:
283 case cConfig:
284 refresh_config_page(SIGNAL_HANDLER);
285 break;
286
287 case cFilter:
288 refresh_filter_menu();
289 break;
290
291 case cInfopager:
293 break;
294
295 case cAttachment:
296 case cGroup:
297 case cPOSTED:
298 case cScope:
299 case cSelect:
300 case cThread:
301 case cURL:
302 ClearScreen();
303 currmenu->redraw();
304 break;
305
306 case cPage:
309 break;
310
311 case cPost:
312 case cPostCancel:
313 refresh_post_screen(signal_context);
314 break;
315
316 case cPostFup:
319 /*
320 * Reset signal_context because draw_page()
321 * sets signal_context to cPage.
322 */
324 refresh_post_screen(signal_context);
325 break;
326
327 case cReconnect:
328 ClearScreen();
330 break;
331
332 case cMain:
333 break;
334 }
335 switch (input_context) {
336 case cGetline:
337 gl_redraw();
338 break;
339
340 case cPromptCONT:
341 if (redraw_after_suspend)
343 break;
344
345 case cPromptSLK:
347 break;
348
349 case cPromptYN:
351 break;
352
353 default:
354 break;
355 }
356 my_fflush(stdout);
357 redraw_after_suspend = FALSE;
358#endif /* SIGWINCH || SIGTSTP */
359}
360
361
362#ifdef SIGTSTP
363static void
364handle_suspend(
365 void)
366{
367 t_bool save_cmd_line = cmd_line;
368 t_bool save_state = (!batch_mode || !cmd_line);
369
370 TRACE(("handle_suspend(%d)", signal_context));
371
373 if (!cmd_line)
375
376 if (save_state) {
377 EndWin();
378 Raw(FALSE);
379 }
380
382
383 kill(0, SIGSTOP); /* Put ourselves to sleep */
384
386
387 if (save_state) {
388 Raw(TRUE);
389 InitWin();
390 cmd_line = save_cmd_line;
391 if (!cmd_line)
392 my_retouch();
393 need_resize = cRedraw; /* Flag a redraw */
394 redraw_after_suspend = TRUE;
395 }
397 if (!cmd_line)
399}
400#endif /* SIGTSTP */
401
402
403static void _CDECL
405 int sig)
406{
407#ifdef SIGCHLD
408# ifdef HAVE_TYPE_UNIONWAIT
409 union wait wait_status;
410# else
411 int wait_status = 1;
412# endif /* HAVE_TYPE_UNIONWAIT */
413#endif /* SIGCHLD */
414
415 /* In this case statement, we handle only the non-fatal signals */
416 switch (sig) {
417#ifdef SIGINT
418 case SIGINT:
420 return;
421#endif /* SIGINT */
422
423/*
424 * fatal error but we don't want the "signal handler caught signal"
425 * message here
426 */
427#if defined(HAVE_ALARM) && defined(SIGALRM)
428 case SIGALRM:
429# ifdef DEBUG
430 if ((debug & DEBUG_NNTP) && verbose > 1)
431 debug_print_file("NNTP", "get_server() %d sec elapsed without response", tinrc.nntp_read_timeout_secs);
432# endif /* DEBUG */
433 tin_done(NNTP_ERROR_EXIT, _("NNTP connection error. Exiting..."));
434 return;
435#endif /* HAVE_ALARM && SIGALRM */
436
437#ifdef SIGCHLD
438 case SIGCHLD:
439 wait(&wait_status);
440 RESTORE_HANDLER(sig, signal_handler); /* death of a child */
441 system_status = WIFEXITED(wait_status) ? WEXITSTATUS(wait_status) : 0;
442 return;
443#endif /* SIGCHLD */
444
445#ifdef SIGTSTP
446 case SIGTSTP:
447 handle_suspend();
448 return;
449#endif /* SIGTSTP */
450
451#ifdef SIGWINCH
452 case SIGWINCH:
455 return;
456#endif /* SIGWINCH */
457
458#ifdef SIGUSR2
459 case SIGUSR2:
460 if (!no_write) /* TODO: add more config-files to be saved */
461 write_newsrc();
463 return;
464#endif /* SIGUSR2 */
465
466 default:
467 break;
468 }
469
470 fprintf(stderr, "\n%s: signal handler caught %s signal (%d).\n", tin_progname, signal_name(sig), sig);
471
472 switch (sig) {
473#ifdef SIGHUP
474 case SIGHUP:
475#endif /* SIGHUP */
476#ifdef SIGUSR1
477 case SIGUSR1:
478#endif /* SIGUSR1 */
479#ifdef SIGTERM
480 case SIGTERM:
481#endif /* SIGTERM */
482#if defined(SIGHUP) || defined(SIGUSR1) || defined(SIGTERM)
484 tin_done(-sig, NULL);
485 /* NOTREACHED */
486 break;
487#endif /* SIGHUP || SIGUSR1 || SIGTERM */
488
489#ifdef SIGSEGV
490 case SIGSEGV:
491# if defined(SIGBUS) && (SIGSEGV != SIGBUS) /* on Haiku SIGSEGV == SIGBUS */
492 case SIGBUS:
493# endif /* SIGBUS && SIGSEGV != SIGBUS */
494#else
495# ifdef SIGBUS
496 case SIGBUS:
497# endif /* SIGBUS */
498#endif /* SIGSEGV */
499
500#if defined(SIGBUS) || defined(SIGSEGV)
502 my_fflush(stderr);
503 break;
504#endif /* SIGBUS || SIGSEGV */
505
506 default:
507 break;
508 }
509
511
512#if 1
513/* #if defined(apollo) || defined(HAVE_COREFILE) */
514 /* do this so we can get a traceback (doesn't dump core) */
515 abort();
516#else
517 giveup();
518#endif /* 1 */ /* apollo || HAVE_COREFILE */
519}
520
521
522/*
523 * Turn on (flag != FALSE) our signal handler for TSTP and WINCH
524 * Otherwise revert to the default handler
525 */
526void
528 int flag)
529{
530#ifdef SIGTSTP
531 if (do_sigtstp)
532 sigdisp(SIGTSTP, flag ? signal_handler : SIG_DFL);
533#endif /* SIGTSTP */
534
535#if defined(SIGWINCH) && !(defined(USE_CURSES) && defined(KEY_RESIZE))
536 sigdisp(SIGWINCH, flag ? signal_handler : SIG_DFL);
537#endif /* SIGWINCH && !(USE_CURSES && KEY_RESIZE) */
538}
539
540
541void
543 void)
544{
545 size_t n;
546 int code;
547#ifdef SIGTSTP
548 RETSIGTYPE (*ptr)(SIG_ARGS);
549#endif /* SIGTSTP */
550
551 for (n = 0; n < ARRAY_SIZE(signal_list); n++) {
552 switch ((code = signal_list[n].code)) {
553#ifdef SIGPIPE
554 case SIGPIPE:
555 sigdisp(code, SIG_IGN);
556 break;
557#endif /* SIGPIPE */
558
559#ifdef SIGTSTP
560 case SIGTSTP:
561 ptr = sigdisp(code, SIG_DFL);
562 sigdisp(code, ptr);
563 if (ptr != SIG_IGN) {
564 /*
565 * SIGTSTP is ignored when starting from shells
566 * without job-control
567 */
568 do_sigtstp = TRUE;
570 }
571 break;
572#endif /* SIGTSTP */
573
574 default:
576 }
577 }
578}
579
580
581/*
582 * Size the display at startup or rescale following a SIGWINCH etc.
583 */
584t_bool
586 int *num_lines,
587 int *num_cols)
588{
589 int old_lines;
590 int old_cols;
591#ifdef TIOCGSIZE
592 struct ttysize win;
593#else
594# ifdef TIOCGWINSZ
595 struct winsize win;
596# endif /* TIOCGWINSZ */
597#endif /* TIOCGSIZE */
598
599 old_lines = *num_lines;
600 old_cols = *num_cols;
601
602#ifdef HAVE_XCURSES
603 *num_lines = LINES - 1; /* FIXME */
604 *num_cols = COLS;
605#else /* curses/ncurses */
606
607# ifndef USE_CURSES
608 init_screen_array(FALSE); /* deallocate screen array */
609# endif /* !USE_CURSES */
610
611# ifdef TIOCGSIZE
612 if (ioctl(0, TIOCGSIZE, &win) == 0) {
613 if (win.ts_lines != 0)
614 *num_lines = win.ts_lines - 1;
615 if (win.ts_cols != 0)
616 *num_cols = win.ts_cols;
617 }
618# else
619# ifdef TIOCGWINSZ
620 if (ioctl(0, TIOCGWINSZ, &win) == 0) {
621 if (win.ws_row != 0)
622 *num_lines = win.ws_row - 1;
623 if (win.ws_col != 0)
624 *num_cols = win.ws_col;
625 }
626# else
627# endif /* TIOCGWINSZ */
628# endif /* TIOCGSIZE */
629
630# ifndef USE_CURSES
631 init_screen_array(TRUE); /* allocate screen array for resize */
632# endif /* !USE_CURSES */
633
634#endif /* HAVE_XCURSES */
635
636 set_noteslines(*num_lines);
637 return (*num_lines != old_lines || *num_cols != old_cols);
638}
639
640
641void
643 int num_lines)
644{
646 if (NOTESLINES <= 0)
647 NOTESLINES = 1;
648}
unsigned t_bool
Definition: bool.h:77
#define TRUE
Definition: bool.h:74
#define FALSE
Definition: bool.h:70
#define DEBUG_NNTP
Definition: debug.h:47
int verbose
Definition: init.c:154
char bug_addr[LEN]
Definition: post.c:124
t_openartinfo pgart
Definition: page.c:63
t_bool cmd_line
Definition: init.c:129
int system_status
Definition: init.c:122
t_bool dangerous_signal_exit
Definition: init.c:131
constext txt_send_bugreport[]
Definition: lang.c:854
t_menu * currmenu
Definition: init.c:166
constext txt_screen_too_small_exiting[]
Definition: lang.c:834
int cCOLS
Definition: curses.c:53
int cLINES
Definition: curses.c:52
char * tin_progname
Definition: init.c:105
constext txt_return_key[]
Definition: lang.c:799
constext txt_suspended_message[]
Definition: lang.c:868
struct t_group * curr_group
Definition: group.c:55
struct t_config tinrc
Definition: init.c:192
unsigned short debug
Definition: debug.c:51
t_bool no_write
Definition: init.c:145
t_bool batch_mode
Definition: init.c:127
void set_keypad_on(void)
Definition: curses.c:381
void gl_redraw(void)
Definition: getline.c:512
_Noreturn void tin_done(int ret, const char *fmt,...)
Definition: misc.c:562
void refresh_config_page(enum option_enum act_option)
Definition: options_menu.c:800
void ClearScreen(void)
Definition: curses.c:410
void set_xclick_on(void)
Definition: curses.c:691
void info_message(const char *fmt,...)
Definition: screen.c:102
void set_keypad_off(void)
Definition: curses.c:394
void EndWin(void)
Definition: curses.c:368
void prompt_slk_redraw(void)
Definition: prompt.c:783
void cleanup_tmp_files(void)
Definition: misc.c:2116
void ring_bell(void)
Definition: screen.c:480
void Raw(int state)
Definition: curses.c:624
void set_xclick_off(void)
Definition: curses.c:703
void InitWin(void)
Definition: curses.c:355
void resize_article(t_bool wrap_lines, t_openartinfo *artinfo)
Definition: page.c:2152
signed long int write_newsrc(void)
Definition: newsrc.c:201
void wait_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:133
void draw_page(const char *group, int part)
Definition: page.c:1175
void show_art_msg(const char *group)
Definition: art.c:110
void init_screen_array(t_bool allocate)
Definition: memory.c:210
void show_title(const char *title)
Definition: screen.c:457
void prompt_yn_redraw(void)
Definition: prompt.c:266
_Noreturn void giveup(void)
Definition: main.c:1058
void display_info_page(int part)
Definition: page.c:2320
static const struct @9 signal_list[]
int input_context
Definition: signal.c:106
void set_signal_handlers(void)
Definition: signal.c:542
int NOTESLINES
Definition: signal.c:111
void(* func)(SIG_ARGS)
Definition: signal.c:176
int code
Definition: signal.c:116
t_bool set_win_size(int *num_lines, int *num_cols)
Definition: signal.c:585
#define RESTORE_HANDLER(x, y)
int need_resize
Definition: signal.c:107
void allow_resize(t_bool allow)
Definition: signal.c:203
void set_signal_catcher(int flag)
Definition: signal.c:527
static const char * signal_name(int code)
Definition: signal.c:227
const char * name
Definition: signal.c:117
int signal_context
Definition: signal.c:105
void handle_resize(t_bool repaint)
Definition: signal.c:249
void(*)(SIG_ARGS) sigdisp(signum, func)
Definition: signal.c:174
void set_noteslines(int num_lines)
Definition: signal.c:642
static void signal_handler(SIG_ARGS)
t_bool beginner_level
Definition: tinrc.h:219
char * name
Definition: tin.h:1817
void(* redraw)(void)
Definition: tin.h:2059
#define my_fprintf
Definition: tcurses.h:176
#define my_fflush(stream)
Definition: tcurses.h:178
#define my_retouch()
Definition: tcurses.h:179
@ cPromptYN
Definition: tin.h:108
@ cNone
Definition: tin.h:108
@ cGetline
Definition: tin.h:108
@ cPromptCONT
Definition: tin.h:108
@ cPromptSLK
Definition: tin.h:108
#define _CDECL
Definition: tin.h:2144
@ cMain
Definition: tin.h:107
@ cAttachment
Definition: tin.h:107
@ cThread
Definition: tin.h:107
@ cPOSTED
Definition: tin.h:107
@ cURL
Definition: tin.h:107
@ cConfig
Definition: tin.h:107
@ cPage
Definition: tin.h:107
@ cPostCancel
Definition: tin.h:107
@ cScope
Definition: tin.h:107
@ cPostFup
Definition: tin.h:107
@ cSelect
Definition: tin.h:107
@ cArt
Definition: tin.h:107
@ cPost
Definition: tin.h:107
@ cReconnect
Definition: tin.h:107
@ cFilter
Definition: tin.h:107
@ cGroup
Definition: tin.h:107
@ cInfopager
Definition: tin.h:107
@ cAttrib
Definition: tin.h:107
#define NNTP_ERROR_EXIT
Definition: tin.h:1306
#define ARRAY_SIZE(array)
Definition: tin.h:2250
#define EXIT_FAILURE
Definition: tin.h:1302
#define MIN_LINES_ON_TERMINAL
Definition: tin.h:1095
#define CURR_GROUP
Definition: tin.h:1054
#define WEXITSTATUS(status)
Definition: tin.h:330
#define _(Text)
Definition: tin.h:94
@ cNo
Definition: tin.h:109
@ cYes
Definition: tin.h:109
@ cRedraw
Definition: tin.h:109
#define WIFEXITED(status)
Definition: tin.h:334
#define INDEX_TOP
Definition: tin.h:1019
#define RETSIGTYPE
Definition: tin.h:2122
#define MINI_HELP_LINES
Definition: tin.h:1124
#define MIN_COLUMNS_ON_TERMINAL
Definition: tin.h:1096
#define TRACE(p)
Definition: trace.h:65
#define VERSION
Definition: version.h:46
#define RELEASENAME
Definition: version.h:49
#define RELEASEDATE
Definition: version.h:48