"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.1/include/tin.h" (12 Oct 2016, 70580 Bytes) of archive /linux/misc/tin-2.4.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tin.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.0_vs_2.4.1.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : tin.h
    4  *  Author    : I. Lea & R. Skrenta
    5  *  Created   : 1991-04-01
    6  *  Updated   : 2016-04-12
    7  *  Notes     : #include files, #defines & struct's
    8  *
    9  * Copyright (c) 1997-2017 Iain Lea <iain@bricbrac.de>, Rich Skrenta <skrenta@pbm.com>
   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  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. The name of the author may not be used to endorse or promote
   21  *    products derived from this software without specific prior written
   22  *    permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   25  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   28  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   30  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 
   38 /*
   39  * OS specific doda's
   40  */
   41 
   42 #ifndef TIN_H
   43 #define TIN_H 1
   44 
   45 #ifdef HAVE_CONFIG_H
   46 #   ifndef TIN_AUTOCONF_H
   47 #       include <autoconf.h>    /* FIXME: normally we use 'config.h' */
   48 #   endif /* !TIN_AUTOCONF_H */
   49 #else
   50 #   ifndef HAVE_CONFDEFS_H
   51 #       error "configure run missing"
   52 #   endif /* !HAVE_CONFDEFS_H */
   53 #endif /* HAVE_CONFIG_H */
   54 
   55 
   56 /*
   57  * this causes trouble on Linux (forces nameserver lookups even for local
   58  * connections - this is an (unwanted) feature of getaddrinfo) see also
   59  * nntplib.c
   60  */
   61 /* IPv6 support */
   62 #if defined(HAVE_GETADDRINFO) && defined(HAVE_GAI_STRERROR) && defined(ENABLE_IPV6)
   63 #   define INET6
   64 #endif /* HAVE_GETADDRINFO && HAVE_GAI_STRERROR && ENABLE_IPV6 */
   65 
   66 
   67 /*
   68  * Native Language Support.
   69  */
   70 #ifndef NO_LOCALE
   71 #   ifdef HAVE_LOCALE_H
   72 #       include <locale.h>
   73 #   endif /* HAVE_LOCALE_H */
   74 #   ifndef HAVE_SETLOCALE
   75 #       define setlocale(Category, Locale) /* empty */
   76 #   endif /* !HAVE_SETLOCALE */
   77 #endif /* !NO_LOCALE */
   78 
   79 #define N_(Str) Str
   80 
   81 #if defined(ENABLE_NLS) && !defined(__BUILD__)
   82 #   include <libintl.h>
   83 #   define _(Text)  gettext(Text)
   84 #else
   85 #   undef bindtextdomain
   86 #   define bindtextdomain(Domain, Directory) /* empty */
   87 #   undef textdomain
   88 #   define textdomain(Domain) /* empty */
   89 #   define _(Text) Text
   90 #endif /* ENABLE_NLS && !__BUILD__ */
   91 
   92 #ifndef LOCALEDIR
   93 #   define LOCALEDIR "/usr/share/locale"
   94 #endif /* !LOCALEDIR */
   95 
   96 #if defined(__amiga__) || defined(__amiga)
   97 #   define SMALL_MEMORY_MACHINE
   98 #endif /* __amiga__ || __amiga */
   99 
  100 #include <signal.h>
  101 
  102 enum context { cMain, cArt, cAttachment, cAttrib, cConfig, cFilter, cGroup, cHelp, cInfopager, cPage, cPost, cPostCancel, cPostFup, cReconnect, cScope, cSelect, cThread, cURL };
  103 enum icontext { cNone, cGetline, cPromptCONT, cPromptSLK, cPromptYN };
  104 enum resizer { cNo, cYes, cRedraw };
  105 enum rc_state { RC_IGNORE, RC_CHECK, RC_UPGRADE, RC_DOWNGRADE, RC_ERROR };
  106 
  107 #include <stdio.h>
  108 #ifdef HAVE_ERRNO_H
  109 #   include <errno.h>
  110 #else
  111 #   ifdef HAVE_SYS_ERRNO_H
  112 #       include <sys/errno.h>
  113 /*
  114     #   else
  115     #       error "No errno.h or sys/errno.h found"
  116 */
  117 #   endif /* HAVE_SYS_ERRNO_H */
  118 #endif /* HAVE_ERRNO_H */
  119 #if !defined(errno)
  120 #   ifdef DECL_ERRNO
  121         extern int errno;
  122 #   endif /* DECL_ERRNO */
  123 #endif /* !errno */
  124 
  125 #ifdef HAVE_STDDEF_H
  126 #   include <stddef.h>
  127 #endif /* HAVE_STDDEF_H */
  128 #ifdef HAVE_SYS_TYPES_H
  129 #   include <sys/types.h>
  130 #endif /* HAVE_SYS_TYPES_H */
  131 
  132 #ifdef HAVE_SYS_STAT_H
  133 #   include <sys/stat.h>
  134 #endif /* HAVE_SYS_STAT_H */
  135 
  136 #ifdef TIME_WITH_SYS_TIME
  137 #   include <sys/time.h>
  138 #   include <time.h>
  139 #else
  140 #   ifdef HAVE_SYS_TIME_H
  141 #       include <sys/time.h>
  142 #   else
  143 #       include <time.h>
  144 #   endif /* HAVE_SYS_TIME_H */
  145 #endif /* TIME_WITH_SYS_TIME */
  146 
  147 #ifdef HAVE_SYS_TIMES_H
  148 #   include <sys/times.h>
  149 #endif /* HAVE_SYS_TIMES_H */
  150 
  151 #if defined(HAVE_LIBC_H) && defined(__NeXT__)
  152 #   include <libc.h>
  153 #endif /* HAVE_LIBC_H && __NeXT__ */
  154 
  155 #ifdef HAVE_UNISTD_H
  156 #   include <unistd.h>
  157 #endif /* HAVE_UNISTD_H */
  158 
  159 #ifdef HAVE_PWD_H
  160 #   include <pwd.h>
  161 #endif /* HAVE_PWD_H */
  162 
  163 #ifdef HAVE_SYS_PARAM_H
  164 #   include <sys/param.h>
  165 #endif /* HAVE_SYS_PARAM_H */
  166 
  167 #include <ctype.h>
  168 
  169 /*
  170  * FIXME: make this autoconf
  171  * get around broken tolower()/toupper() macros on
  172  * ancient BSDs (at least on sony news os)
  173  */
  174 #if defined(__bsd43__) && defined(__sony_news__)
  175 #   undef tolower
  176 #   undef toupper
  177 #   define tolower(c) ((isalpha(c) && isupper(c)) ? ((unsigned char) (c - 'A' + 'a')) : c)
  178 #   define toupper(c) ((isalpha(c) && islower(c)) ? ((unsigned char) (c - 'a' + 'A')) : c)
  179 #endif /* __bsd43__ && __sony_news__ */
  180 
  181 #ifdef HAVE_STDLIB_H
  182 #   include <stdlib.h>
  183 #endif /* HAVE_STDLIB_H */
  184 
  185 #include <stdarg.h>
  186 
  187 #ifdef HAVE_GETOPT_H
  188 #   include <getopt.h>
  189 #endif /* HAVE_GETOPT_H */
  190 
  191 
  192 #if defined(ENABLE_LONG_ARTICLE_NUMBERS) && !defined(SMALL_MEMORY_MACHINE)
  193 /*
  194  * defines and typedefs for 64 bit article numbers
  195  *
  196  * TODO: what if !CPP_DOES_CONCAT
  197  *       add configure check for PRIdLEAST64
  198  *       add configure check for SCNdLEAST64
  199  */
  200 #   if defined(HAVE_INT_LEAST64_T) && !defined(HAVE_INTTYPES_H)
  201 #       undef HAVE_INT_LEAST64_T
  202 #   endif /* HAVE_INT_LEAST64_T && !HAVE_INTTYPES_H */
  203 #   if defined(HAVE_INT_LEAST64_T) || defined(HAVE_LONG_LONG) || defined(quad_t)
  204 #       if defined(HAVE_ATOLL) || defined(HAVE_ATOQ)
  205 #           ifdef HAVE_STRTOLL
  206 #               define USE_LONG_ARTICLE_NUMBERS 1
  207 #           endif /* HAVE_STRTOLL */
  208 #       endif /* HAVE_ATOLL || HAVE_ATOQ */
  209 #   endif /* HAVE_INT_LEAST64_T || HAVE_LONG_LONG || quad_t */
  210 #   ifdef HAVE_STDINT_H
  211 #       include <stdint.h>
  212 #   endif   /* HAVE_STDINT_H */
  213 #endif /* ENABLE_LONG_ARTICLE_NUMBERS && !SMALL_MEMORY_MACHINE */
  214 #ifdef USE_LONG_ARTICLE_NUMBERS
  215 #   if defined(HAVE_INT_LEAST64_T) && defined(HAVE_INT64_C)
  216 #       include <inttypes.h>
  217         typedef int_least64_t t_artnum;
  218 #       define T_ARTNUM_PFMT PRIdLEAST64
  219 #       define T_ARTNUM_SFMT SCNdLEAST64
  220 #       define T_ARTNUM_CONST(v) INT64_C(v)
  221 #   else
  222         typedef long long t_artnum;
  223 #       define T_ARTNUM_PFMT "lld"
  224 #       define T_ARTNUM_SFMT "lld"
  225 #       define T_ARTNUM_CONST(v) v ## LL
  226 #   endif /* HAVE_INT_LEAST64_T && HAVE_INT64_C */
  227 #   ifdef HAVE_ATOLL
  228 #       define atoartnum atoll
  229 #   else
  230 #       define atoartnum atoq
  231 #   endif /* HAVE_ATOLL */
  232 #   define strtoartnum strtoll
  233 #else
  234     typedef long t_artnum;
  235 #   define T_ARTNUM_PFMT "ld"
  236 #   define T_ARTNUM_SFMT "ld"
  237 #   define T_ARTNUM_CONST(v) v ## L
  238 #   define atoartnum atol
  239 #   define strtoartnum strtol
  240 #endif /* USE_LONG_ARTICLE_NUMBERS */
  241 
  242 /*
  243  * FIXME: make this autoconf
  244  */
  245 #ifndef __QNX__
  246 #   ifdef HAVE_STRING_H
  247 #       include <string.h>
  248 #   else
  249 #       ifdef HAVE_STRINGS_H
  250 #           include <strings.h>
  251 #       endif /* HAVE_STRINGS_H */
  252 #   endif /* HAVE_STRING_H */
  253 #else
  254 #   ifdef HAVE_STRING_H
  255 #       include <string.h>
  256 #   endif /* HAVE_STRING_H */
  257 #   ifdef HAVE_STRINGS_H
  258 #       include <strings.h>
  259 #   endif /* HAVE_STRINGS_H */
  260 #endif /* !__QNX__ */
  261 
  262 /*
  263  * FIXME: make this autoconf
  264  */
  265 #ifdef SEIUX
  266 #   include <bsd/sys/time.h>
  267 #   include <bsd/sys/signal.h>
  268 #   include <bsd/sys/types.h>
  269 #   include <posix/unistd.h>
  270 #   include <bsd/netinet/in.h>
  271 #endif /* SEIUX */
  272 
  273 #ifdef HAVE_FCNTL_H
  274 #   include <fcntl.h>
  275 #endif /* HAVE_FCNTL_H */
  276 
  277 #ifdef HAVE_SYS_IOCTL_H
  278 #   include <sys/ioctl.h>
  279 /* We don't need/use these, and they cause redefinition errors with SunOS 4.x
  280  * when we include termio.h or termios.h
  281  */
  282 #   if defined(sun) && !defined(__svr4)
  283 #       undef NL0
  284 #       undef NL1
  285 #       undef CR0
  286 #       undef CR1
  287 #       undef CR2
  288 #       undef CR3
  289 #       undef TAB0
  290 #       undef TAB1
  291 #       undef TAB2
  292 #       undef XTABS
  293 #       undef BS0
  294 #       undef BS1
  295 #       undef FF0
  296 #       undef FF1
  297 #       undef ECHO
  298 #       undef NOFLSH
  299 #       undef TOSTOP
  300 #       undef FLUSHO
  301 #       undef PENDIN
  302 #   endif /* sun && !__svr4 */
  303 #endif /* HAVE_SYS_IOCTL_H */
  304 
  305 #ifdef HAVE_PROTOTYPES_H
  306 #   include <prototypes.h>
  307 #endif /* HAVE_PROTOTYPES_H */
  308 
  309 #ifdef HAVE_SYS_UTSNAME_H
  310 #   include <sys/utsname.h>
  311 #endif /* HAVE_SYS_UTSNAME_H */
  312 
  313 /*
  314  * Needed for catching child processes
  315  */
  316 #ifdef HAVE_SYS_WAIT_H
  317 #   include <sys/wait.h>
  318 #endif /* HAVE_SYS_WAIT_H */
  319 
  320 #ifndef WEXITSTATUS
  321 #   define WEXITSTATUS(status)  ((int) (((status) >> 8) & 0xFF))
  322 #endif /* !WEXITSTATUS */
  323 
  324 #ifndef WIFEXITED
  325 #   define WIFEXITED(status)    ((int) (((status) & 0xFF) == 0))
  326 #endif /* !WIFEXITED */
  327 
  328 /*
  329  * Needed for timeout in user abort of indexing a group (BSD & SYSV variaties)
  330  */
  331 #ifdef HAVE_SYS_SELECT_H
  332 #   ifdef NEED_TIMEVAL_FIX
  333 #       define timeval fake_timeval
  334 #       include <sys/select.h>
  335 #       undef timeval
  336 #   else
  337 #       include <sys/select.h>
  338 #   endif /* NEED_TIMEVAL_FIX */
  339 #endif /* HAVE_SYS_SELECT_H */
  340 
  341 #if defined(HAVE_STROPTS_H) && !defined(__dietlibc__)
  342 #   include <stropts.h>
  343 #endif /* HAVE_STROPTS_H && !__dietlibc__ */
  344 
  345 #ifdef HAVE_POLL_H
  346 #   include <poll.h>
  347 #else
  348 #   ifdef HAVE_SYS_POLL_H
  349 #       include <sys/poll.h>
  350 #   endif /* HAVE_SYS_POLL_H */
  351 #endif /* HAVE_POLL_H */
  352 
  353 /*
  354  * Directory handling code
  355  */
  356 #ifdef HAVE_DIRENT_H
  357 #   include <dirent.h>
  358 /* #    define NAMLEN(dirent) strlen((dirent)->d_name) */
  359 #else
  360 #   define dirent direct
  361 /* #    define NAMLEN(dirent) (dirent)->d_namlen */
  362 #   ifdef HAVE_SYS_NDIR_H
  363 #       include <sys/ndir.h>
  364 #   endif /* HAVE_SYS_NDIR_H */
  365 #   ifdef HAVE_SYS_DIR_H
  366 #       include <sys/dir.h>
  367 #   endif /* HAVE_SYS_DIR_H */
  368 #   ifdef HAVE_NDIR_H
  369 #       include <ndir.h>
  370 #   endif /* HAVE_NDIR_H */
  371 #endif /* HAVE_DIRENT_H */
  372 
  373 #ifndef DIR_BUF
  374 #   define DIR_BUF struct dirent
  375 #endif /* !DIR_BUF */
  376 
  377 #ifndef HAVE_UNLINK
  378 #   define unlink(file) remove(file)
  379 #endif /* !HAVE_UNLINK */
  380 
  381 /*
  382  * If native OS hasn't defined STDIN_FILENO be a smartass and do it
  383  */
  384 #if !defined(STDIN_FILENO)
  385 #   define STDIN_FILENO 0
  386 #endif /* !STDIN_FILENO */
  387 
  388 /*
  389  * include <paths.h> if available to define _PATH_TMP
  390  */
  391 #ifdef HAVE_PATHS_H
  392 #   include <paths.h>
  393 #endif /* HAVE_PATHS_H */
  394 #ifndef _PATH_TMP
  395 #   define _PATH_TMP    "/tmp/"
  396 #endif /* _PATH_TMP */
  397 
  398 /*
  399  * If OS misses the isascii() function
  400  */
  401 #if !defined(HAVE_ISASCII) && !defined(isascii)
  402 #   define isascii(c) (!((c) & ~0177))
  403 #endif /* !HAVE_ISASCII && !isascii */
  404 
  405 
  406 /*
  407  * any pgp/gpp support possible and wanted
  408  * sort out possible conflicts: gpg is preferred over pgp5 over pgp
  409  */
  410 #if defined(HAVE_PGP) || defined(HAVE_PGPK) || defined(HAVE_GPG)
  411 #   define HAVE_PGP_GPG 1
  412 #   if defined(HAVE_PGP) && defined(HAVE_PGPK)
  413 #       undef HAVE_PGP
  414 #   endif /* HAVE_PGP && HAVE_PGPK */
  415 #   if defined(HAVE_PGPK) && defined(HAVE_GPG)
  416 #       undef HAVE_PGPK
  417 #   endif /* HAVE_PGPK && HAVE_GPG */
  418 #   if defined(HAVE_PGP) && defined(HAVE_GPG)
  419 #       undef HAVE_PGP
  420 #   endif /* HAVE_PGP && HAVE_GPG */
  421 #endif /* HAVE_PGP || HAVE_PGPK || HAVE_GPG */
  422 
  423 /*
  424  * slrnface requires some things
  425  */
  426 #if defined(HAVE_SLRNFACE) && defined(HAVE_MKFIFO) && defined(HAVE_FORK) && defined(HAVE_EXECLP) && defined(HAVE_WAITPID) && !defined(DONT_HAVE_PIPING) && !defined(X_DISPLAY_MISSING)
  427 #   define XFACE_ABLE
  428 #endif /* HAVE_SLRNFACE && HAVE_MKFIFO && HAVE_FORK && HAVE_EXECLP && HAVE_WAITPID && !DONT_HAVE_PIPING && !X_DISPLAY_MISSING */
  429 
  430 /*
  431  * Setup support for reading from NNTP
  432  */
  433 #if defined(NNTP_ABLE) || defined(NNTP_ONLY)
  434 #   ifndef NNTP_ABLE
  435 #       define NNTP_ABLE    1
  436 #   endif /* !NNTP_ABLE */
  437 #   ifndef NNTP_INEWS
  438 #       define NNTP_INEWS   1
  439 #   endif /* !NNTP_INEWS */
  440 #else
  441 #   ifdef XHDR_XREF
  442 #       undef XHDR_XREF
  443 #   endif /* XHDR_XREF */
  444 #   ifdef BROKEN_LISTGROUP
  445 #       undef BROKEN_LISTGROUP
  446 #   endif /* BROKEN_LISTGROUP */
  447 #endif /* NNTP_ABLE || NNTP_ONLY */
  448 
  449 #define FAKE_NNTP_FP        (FILE *) 9999
  450 
  451 /*
  452  * Max time between the first character of a VT terminal escape sequence
  453  * for special keys and the following characters to arrive (msec)
  454  */
  455 #define SECOND_CHARACTER_DELAY  200
  456 
  457 /*
  458  * Maximum time (seconds) for a VT terminal escape sequence
  459  */
  460 #define VT_ESCAPE_TIMEOUT   1
  461 
  462 /*
  463  * Determine machine configuration for external programs & directories
  464  */
  465 #if defined(BSD)
  466 /*
  467  * To catch 4.3 Net2 code base or newer
  468  * (e.g. FreeBSD 1.x, 4.3/Reno, NetBSD 0.9, 386BSD, BSD/386 1.1 and below).
  469  * use
  470  * #if (defined(BSD) && (BSD >= 199103))
  471  *
  472  * To detect if the code is being compiled on a 4.4 code base or newer
  473  * (e.g. FreeBSD 2.x, 4.4, NetBSD 1.0, BSD/386 2.0 or above).
  474  * use
  475  * #if (defined(BSD) && (BSD >= 199306))
  476  *
  477  * (defined in <sys/param.h>)
  478  */
  479 #   ifndef HAVE_MEMCMP
  480 #       define memcmp(s1, s2, n)    bcmp(s2, s1, n)
  481 #   endif /* !HAVE_MEMCMP */
  482 #   ifndef HAVE_MEMCPY
  483 #       define memcpy(s1, s2, n)    bcopy(s2, s1, n)
  484 #   endif /* !HAVE_MEMCPY */
  485 #   ifndef HAVE_MEMSET
  486 #       define memset(s1, s2, n)    bfill(s1, n, s2)
  487 #   endif /* !HAVE_MEMSET */
  488 #   ifndef HAVE_STRCHR
  489 #       define strchr(str, ch)  index(str, ch)
  490 #   endif /* !HAVE_STRCHR */
  491 #   ifndef HAVE_STRRCHR
  492 #       define strrchr(str, ch) rindex(str, ch)
  493 #   endif /* !HAVE_STRRCHR */
  494 #   if defined(__386BSD__) || defined(__bsdi__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
  495 #       define DEFAULT_PRINTER  "/usr/bin/lpr"
  496 #       define DEFAULT_SUM  "/usr/bin/cksum -o 1 <" /* use tailing <, otherwise get filename output too */
  497 #   else
  498 #       define DEFAULT_PRINTER  "/usr/ucb/lpr"
  499 #       define DEFAULT_SUM  "sum"
  500 #   endif /* __386BSD__ || __bsdi__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
  501 #   ifdef DGUX
  502 #       define USE_INVERSE_HACK
  503 #   endif /* DGUX */
  504 #   ifdef pyr
  505 #       define DEFAULT_MAILER   "/usr/.ucbucb/mail"
  506 #   endif /* pyr */
  507 #else /* !BSD */
  508 #   ifdef linux
  509 #       define DEFAULT_PRINTER  "/usr/bin/lpr"
  510 #   endif /* linux */
  511 #   ifdef QNX42
  512 #       ifndef DEFAULT_EDITOR
  513 #           define DEFAULT_EDITOR   "/bin/vedit"
  514 #       endif /* !DEFAULT_EDITOR */
  515 #   endif /* QNX42 */
  516 #   ifdef _AIX
  517 #       define DEFAULT_PRINTER  "/bin/lp"
  518 #       define READ_CHAR_HACK
  519 #   endif /* _AIX */
  520 #   ifdef sinix
  521 #       define DEFAULT_PRINTER  "/bin/lpr"
  522 #   endif /* sinix */
  523 #   ifdef sysV68
  524 #       define DEFAULT_MAILER   "/bin/rmail"
  525 #   endif /* sysV68 */
  526 #   ifdef UNIXPC
  527 #       define DEFAULT_MAILER   "/bin/rmail"
  528 #   endif /* UNIXPC */
  529 
  530 #   ifndef DEFAULT_PRINTER
  531 #       define DEFAULT_PRINTER  "/usr/bin/lp"
  532 #   endif /* !DEFAULT_PRINTER */
  533 #   ifndef PATH_SUM
  534 #       define DEFAULT_SUM  "sum -r"
  535 #   endif /* !PATH_SUM */
  536 #endif /* BSD */
  537 
  538 /*
  539  * fallback values
  540  */
  541 #ifndef DEFAULT_EDITOR
  542 #   define DEFAULT_EDITOR   "/usr/bin/vi"
  543 #endif /* !DEFAULT_EDITOR */
  544 #ifndef DEFAULT_MAILER
  545 #   define DEFAULT_MAILER   "/usr/lib/sendmail"
  546 #endif /* !DEFAULT_MAILER */
  547 #ifndef DEFAULT_MAILBOX
  548 #   define DEFAULT_MAILBOX  "/usr/spool/mail"
  549 #endif /* !DEFAULT_MAILBOX */
  550 
  551 
  552 /* FIXME: remove absolute-paths! */
  553 /*
  554  * Miscellaneous program-paths
  555  */
  556 #ifndef PATH_ISPELL
  557 #   define PATH_ISPELL  "ispell"
  558 #endif /* !PATH_ISPELL */
  559 
  560 #ifndef PATH_METAMAIL   /* only unset if !HAVE_METAMAIL */
  561 #   define PATH_METAMAIL    "metamail"
  562 #endif /* !PATH_METAMAIL */
  563 #define METAMAIL_CMD        PATH_METAMAIL" -e -p -m \"tin\""
  564 
  565 #define INTERNAL_CMD    "--internal"
  566 
  567 /*
  568  * Fix up the 'sum' path and parameter for './configure'd systems
  569  */
  570 #ifdef PATH_SUM
  571 #   ifdef DEFAULT_SUM
  572 #       undef DEFAULT_SUM
  573 #   endif /* DEFAULT_SUM */
  574 #   ifdef SUM_TAKES_DASH_R
  575 #       define DEFAULT_SUM PATH_SUM_R
  576 #   else
  577 #       define DEFAULT_SUM PATH_SUM
  578 #   endif /* SUM_TAKES_DASH_R */
  579 #endif /* PATH_SUM */
  580 
  581 #ifdef HAVE_LONG_FILE_NAMES
  582 #   define PATH_PART    "part"
  583 #   define PATH_PATCH   "patch"
  584 #   define INDEX_LOCK   "tin.%s.LCK"
  585 #else
  586 #   define PATH_PART    ""
  587 #   define PATH_PATCH   "p"
  588 #   define INDEX_LOCK   "%s.LCK"
  589 #endif /* HAVE_LONG_FILE_NAMES */
  590 
  591 /*
  592  * How often should the active file be reread for new news
  593  */
  594 #ifndef REREAD_ACTIVE_FILE_SECS
  595 #   define REREAD_ACTIVE_FILE_SECS 1200 /* seconds (20 mins) */
  596 #endif /* !REREAD_ACTIVE_FILE_SECS */
  597 
  598 /*
  599  * Initial sizes of internal arrays for small (<4MB) & large memory machines
  600  */
  601 #ifdef SMALL_MEMORY_MACHINE
  602 #   define DEFAULT_ARTICLE_NUM  600
  603 #   define DEFAULT_SAVE_NUM 10
  604 #else
  605 #   define DEFAULT_ARTICLE_NUM  1200
  606 #   define DEFAULT_SAVE_NUM 30
  607 #endif /* SMALL_MEMORY_MACHINE */
  608 #define DEFAULT_ACTIVE_NUM  1800
  609 #define DEFAULT_NEWNEWS_NUM 5
  610 #define DEFAULT_MAPKEYS_NUM 100 /* ~remappable keys per level (avoid massiv reallocs) */
  611 #define DEFAULT_SCOPE_NUM   8
  612 
  613 #define RCDIR   ".tin"
  614 #define INDEX_MAILDIR   ".mail"
  615 #define INDEX_NEWSDIR   ".news"
  616 #define INDEX_SAVEDIR   ".save"
  617 
  618 #define ACTIVE_FILE "active"
  619 #define ACTIVE_MAIL_FILE    "active.mail"
  620 #define ACTIVE_SAVE_FILE    "active.save"
  621 #define ACTIVE_TIMES_FILE   "active.times"
  622 #define ATTRIBUTES_FILE "attributes"
  623 #define CONFIG_FILE "tinrc"
  624 #define SERVERCONFIG_FILE   "serverrc"
  625 #define DEFAULT_MAILDIR "Mail"
  626 #define DEFAULT_SAVEDIR "News"
  627 #define DEFAULT_URL_HANDLER "url_handler.pl"
  628 /* Prefixes saved attachments with no set filename */
  629 #define SAVEFILE_PREFIX     "unknown"
  630 
  631 
  632 /* MMDF-mailbox separator */
  633 #ifndef MMDFHDRTXT
  634 #   define MMDFHDRTXT "\01\01\01\01\n"
  635 #endif /* MMDFHDRTXT */
  636 
  637 
  638 /*
  639  * all regexps are extended -> # must be quoted!
  640  */
  641 #ifdef HAVE_COLOR
  642 /* case insensitive */
  643 #   define DEFAULT_QUOTE_REGEX  "^\\s{0,3}(?:[\\]{}>|:)]|\\w{1,3}[>|])(?!-)"
  644 #   define DEFAULT_QUOTE_REGEX2 "^\\s{0,3}(?:(?:[\\]{}>|:)]|\\w{1,3}[>|])\\s*){2}(?!-[})>])"
  645 #   define DEFAULT_QUOTE_REGEX3 "^\\s{0,3}(?:(?:[\\]{}>|:)]|\\w{1,3}[>|])\\s*){3}"
  646 #endif /* HAVE_COLOR */
  647 
  648 /* case insensitive */
  649 #if 0 /* single words only */
  650 #   define DEFAULT_SLASHES_REGEX    "(?:^|(?<=\\s))/[^\\s/]+/(?:(?=[,.!?;]?\\s)|$)"
  651 #   define DEFAULT_STARS_REGEX  "(?:^|(?<=\\s))\\*[^\\s*]+\\*(?:(?=[,.!?;]?\\s)|$)"
  652 #   define DEFAULT_UNDERSCORES_REGEX    "(?:^|(?<=\\s))_[^\\s_]+_(?:(?=[,.!?;]?\\s)|$)"
  653 #   define DEFAULT_STROKES_REGEX    "(?:^|(?<=\\s))-[^-\\s]+-(?:(?=[,.!?;]?\\s)|$)"
  654 #else /* multiple words */
  655 #   define DEFAULT_SLASHES_REGEX    "(?:^|(?<=\\s))/(?(?=[^-*/_\\s][^/\\s])[^-*/_\\s][^/]*[^-*/_\\s]|[^/\\s])/(?:(?=[,.!?;]?\\s)|$)"
  656 #   define DEFAULT_STARS_REGEX  "(?:^|(?<=\\s))\\*(?(?=[^-*/_\\s][^*\\s])[^-*/_\\s][^*]*[^-*/_\\s]|[^*\\s])\\*(?:(?=[,.!?;]?\\s)|$)"
  657 #   define DEFAULT_UNDERSCORES_REGEX    "(?:^|(?<=\\s))_(?(?=[^-*/_\\s][^_\\s])[^-*/_\\s][^_]*[^-*/_\\s]|[^_\\s])_(?:(?=[,.!?;]?\\s)|$)"
  658 #   define DEFAULT_STROKES_REGEX    "(?:^|(?<=\\s))-(?(?=[^-*/_\\s][^-\\s])[^-*/_\\s][^-]*[^-*/_\\s]|[^-\\s])-(?:(?=[,.!?;]?\\s)|$)"
  659 #endif /* 0 */
  660 
  661 /* case sensitive && ^-anchored */
  662 #define DEFAULT_STRIP_RE_REGEX  "(?:R[eE](?:\\^\\d+|\\[\\d+\\])?|A[wW]|Odp|Sv):\\s"
  663 /* case sensitive */
  664 #define DEFAULT_STRIP_WAS_REGEX "(?:(?<=\\S)|\\s)\\((?:[Ww]a[rs]|[Bb]y[l\\xb3]o):.*\\)\\s*$"
  665 #define DEFAULT_U8_STRIP_WAS_REGEX  "(?:(?<=\\S)|\\s)\\((?:[Ww]a[rs]|[Bb]y[l\\x{0142}]o):.*\\)\\s*$"
  666 /*
  667  * overkill regexp for balanced '()':
  668  * #define DEFAULT_STRIP_WAS_REGEX  "(?:(?<=\\S)|\\s)\\((?:[Ww]a[rs]|[Bb]y[l\xb3]o):(?:(?:[^)(])*(?:\\([^)(]*\\))*)+\\)\\s*$"
  669  */
  670 
  671 /* case sensitive & ^-anchored */
  672 #define UUBEGIN_REGEX   "begin\\s\\s?[0-7]{3,4}\\s+"
  673 /* case sensitive & ^-anchored */
  674 #define UUBODY_REGEX    "(?:`|.[\\x20-\\x60]{1,61})$"
  675 
  676 /* case sensitive & ^-anchored */
  677 #define SHAR_REGEX  "\\#(?:!\\s?(?:/usr)?/bin/sh|\\s?(?i)this\\sis\\sa\\sshell\\sarchive)"
  678 
  679 /* slrn verbatim marks, case sensitive & ^-anchored */
  680 #define DEFAULT_VERBATIM_BEGIN_REGEX    "#v\\+\\s$"
  681 #define DEFAULT_VERBATIM_END_REGEX  "#v-\\s$"
  682 
  683 /* quoted text from external sources */
  684 #define DEFAULT_EXTQUOTE_REGEX "^\\|\\s"
  685 
  686 /*
  687  * URL related regexs:
  688  * add TELNET (RFC 4248), WAIS (RFC 4156), IMAP (RFC 2192), NFS (RFC 2224)
  689  *     LDAP (RFC 2255), POP (RFC 2384)
  690  * add IPv6 (RFC 2732, RFC 2373) support
  691  */
  692 /*
  693  * case insensitive
  694  * TODO: - split out ftp (only ftp allows username:passwd@, RFC 1738)?
  695  *       - test IDNA (RFC 3490) case
  696  */
  697 #define URL_REGEX   "\\b(?:https?|ftp|gopher)://(?:[^:@/\\s]*(?::[^:@/\\s]*)?@)?(?:(?:(?:[^\\W_](?:(?:-|[^\\W_]){0,61}(?<!---)[^\\W_])?|xn--[^\\W_](?:-(?!-)|[^\\W_]){1,57}[^\\W_])\\.)+[a-z]{2,14}\\.?|localhost|(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)|\\[(?:(?:[0-9A-F]{0,4}:){1,7}[0-9A-F]{1,4}|(?:[0-9A-F]{0,4}:){1,3}(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?))\\])(?::\\d+)?(?(?=[^\\)\\]\\>\"\\s]*\\()(?:/[^\\]\\>\"\\s]*|$|(?=[)\\]\\>\"\\s]))|(?:/[^)\\]\\>\"\\s]*|$|(?=[)\\]\\>\"\\s])))"
  698 /*
  699  * case insensitive
  700  * TOFO: check against RFC 2368
  701  */
  702 /* #define MAIL_REGEX   "\\b(?:mailto:(?:(?:[-\\w$.+!*'(),;/?:@&=]|(?:%[\\da-f]{2}))+))" */
  703 #define MAIL_REGEX  "\\b(?:mailto:(?:[-\\w$.+!*'(),;/?:@&=]|%[\\da-f]{2})+)"
  704 /*
  705  * case insensitive
  706  * TODO: check against RFC 5538
  707  */
  708 #define NEWS_REGEX "\\b(?:s?news|nntp):(?:(?:(?://(?:(?:[^\\W_](?:(?:-|[^\\W_]){0,61}(?<!---)[^\\W_])?|xn--[^\\W_](?:-(?!-)|[^\\W_]){1,57}[^\\W_])\\.)+[a-z]{2,14}\\.?|localhost|(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?))(?::\\d+)?(?(?=[/])[^()\\^\\[\\]{}\\|\\x00-\\x1f\\x7f\\s\"<>'\\\\:,;]+|$))|[^\\^\\[\\]{}\\|\\x00-\\x1f\\x7f\\s<>\"():,;\\\\'/]+)\\b"
  709 
  710 #if 0 /* not implemented */
  711 /*
  712  * case insensitive
  713  */
  714 #   define TELNET_REGEX "\\btelnet://(?:[^:@/]*(?::[^:@/]*)?@)?(?:(?:[^\\W_](?:(?:-|[^\\W_]){0,61}(?<!---)[^\\W_])?\\.)+[a-z]{2,14}\\.?||localhost|(?:(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(?:2[0-4]\\d|25[0-5]|[01]?\\d\\d?))(?::\\d+)?/?"
  715 #endif /* 0 */
  716 
  717 
  718 #define FILTER_FILE "filter"
  719 #define INPUT_HISTORY_FILE  ".inputhistory"
  720 #ifdef HAVE_MH_MAIL_HANDLING
  721 #   define MAILGROUPS_FILE  "mailgroups"
  722 #endif /* HAVE_MH_MAIL_HANDLING */
  723 #define NEWSRC_FILE ".newsrc"
  724 #define NEWSRCTABLE_FILE    "newsrctable"
  725 /* ifdef APPEND_PID (default) NEWNEWSRC_FILE will be .newnewsrc<pid> */
  726 #define NEWNEWSRC_FILE  ".newnewsrc"
  727 #define OLDNEWSRC_FILE  ".oldnewsrc"
  728 #ifndef OVERVIEW_FILE
  729 #   define OVERVIEW_FILE    ".overview"
  730 #endif /* !OVERVIEW_FILE */
  731 #define OVERVIEW_FMT    "overview.fmt"
  732 #define POSTED_FILE "posted"
  733 #define POSTPONED_FILE  "postponed.articles"
  734 #define SUBSCRIPTIONS_FILE  "subscriptions"
  735 #define NEWSGROUPS_FILE "newsgroups"
  736 #define KEYMAP_FILE "keymap"
  737 
  738 #define SIGDASHES "-- \n"
  739 
  740 #ifndef BOOL_H
  741 #   include "bool.h"
  742 #endif /* BOOL_H */
  743 
  744 /* Philip Hazel's Perl regular expressions library */
  745 #include <pcre.h>
  746 
  747 #ifdef HAVE_ICONV
  748 #   define CHARSET_CONVERSION 1
  749 #   ifdef HAVE_ICONV_H
  750 #       include <iconv.h>
  751 #   endif /* HAVE_ICONV_H */
  752 #endif /* HAVE_ICONV */
  753 
  754 #ifdef HAVE_LANGINFO_H
  755 #   include <langinfo.h>
  756 #else
  757 #   ifdef HAVE_NL_TYPES_H
  758 #       include <nl_types.h>
  759 #   endif /* HAVE_NL_TYPES_H */
  760 #endif /* HAVE_LANGINFO_H */
  761 #ifndef HAVE_NL_ITEM
  762     typedef int nl_item;
  763 #endif /* HAVE_NL_ITEM */
  764 #ifndef CODESET
  765 #   define CODESET ((nl_item) 1)
  766 #endif /* CODESET */
  767 
  768 #ifdef CHARSET_CONVERSION
  769 #   define IS_LOCAL_CHARSET(c)  (!strncasecmp(tinrc.mm_local_charset, c, strlen(c)))
  770 #else
  771 #   define IS_LOCAL_CHARSET(c)  (!strncasecmp(tinrc.mm_charset, c, strlen(c)))
  772 #endif /* CHARSET_CONVERSION */
  773 
  774 /* TODO: move up to the 'right' place */
  775 #ifdef HAVE_SYS_FILE_H
  776 #   include <sys/file.h>
  777 #endif /* HAVE_SYS_FILE_H */
  778 
  779 #ifdef HAVE_LIBUTF8_H
  780 #   include <libutf8.h>
  781 #else
  782 /*
  783  * order is important here:
  784  * - Solaris 2.5.1 requires wchar.h before wctype.h
  785  * - Tru64 with Desktop Toolkit C requires stdio.h before wchar.h
  786  * - BSD/OS 4.0.1 requires stddef.h, stdio.h and time.h before wchar.h
  787  */
  788 #   ifdef HAVE_WCHAR_H
  789 #       include <wchar.h>
  790 #   endif /* HAVE_WCHAR_H */
  791 #   ifdef HAVE_WCTYPE_H
  792 #       include <wctype.h>
  793 #   endif /* HAVE_WCTYPE_H */
  794 #endif /* HAVE_LIBUTF8_H */
  795 
  796 #ifndef MAX
  797 #   define MAX(a,b) (((a) > (b)) ? (a) : (b))
  798 #endif /* !MAX */
  799 #ifndef MIN
  800 #   define MIN(a,b) (((a) > (b)) ? (b) : (a))
  801 #endif /* !MIN */
  802 
  803 #ifndef forever
  804 /*@notfunction@*/
  805 #   define forever  for(;;)
  806 #endif /* !forever */
  807 
  808 /* safe strcpy into fixed-legth buffer */
  809 #define STRCPY(dst, src)    (dst[sizeof(dst) - 1] = '\0', strncpy(dst, src, sizeof(dst) - 1))
  810 
  811 #define STRCMPEQ(s1, s2)    (strcmp((s1), (s2)) == 0)
  812 #define STRNCMPEQ(s1, s2, n)    (strncmp((s1), (s2), n) == 0)
  813 #define STRNCASECMPEQ(s1, s2, n)    (strncasecmp((s1), (s2), n) == 0)
  814 
  815 /*
  816  * PATH_LEN    = max. path length (incl. terminating '\0')
  817  * NAME_LEN    = max. filename length (not incl. terminating '\0')
  818  * LEN         =
  819  * HEADER_LEN  = max. size of a news/mail header-line
  820  * NEWSRC_LINE =
  821  */
  822 
  823 #ifdef M_UNIX
  824 #   ifdef PATH_MAX
  825 #       define PATH_LEN PATH_MAX
  826 #   else
  827 #       ifdef MAXPATHLEN
  828 #           define PATH_LEN MAXPATHLEN
  829 #       else
  830 #           ifdef _POSIX_PATH_MAX
  831 #               define PATH_LEN _POSIX_PATH_MAX
  832 #           else
  833 #               define PATH_LEN 255
  834 #           endif /* _POSIX_PATH_MAX */
  835 #       endif /* MAXPATHLEN */
  836 #   endif /* PATH_MAX */
  837 #   ifdef HAVE_LONG_FILE_NAMES
  838 #       ifdef NAME_MAX
  839 #           define NAME_LEN NAME_MAX
  840 #       else
  841 #           ifdef _POSIX_NAME_MAX
  842 #               define NAME_LEN _POSIX_NAME_MAX
  843 #           else
  844 #               define NAME_LEN 14
  845 #           endif /* _POSIX_NAME_MAX */
  846 #       endif /* NAME_MAX */
  847 #   else
  848 #       define NAME_LEN 14
  849 #   endif /* HAVE_LONG_FILE_NAMES */
  850 #   define LEN  1024
  851 #endif /* M_UNIX */
  852 
  853 #define NEWSRC_LINE 8192
  854 #define HEADER_LEN  1024
  855 
  856 #define TABLE_SIZE  1409
  857 
  858 #define MODULO_COUNT_NUM    50
  859 
  860 #define DAY (60*60*24)      /* Seconds in a day */
  861 
  862 #define ctrl(c) ((c) & 0x1F)
  863 
  864 #ifndef DEFAULT_ISO2ASC
  865 #   define DEFAULT_ISO2ASC  "-1 "   /* ISO -> ASCII charset conversion */
  866 #endif /* !DEFAULT_ISO2ASC */
  867 
  868 #ifndef DEFAULT_COMMENT
  869 #   define DEFAULT_COMMENT  "> "    /* used when by follow-ups & replys */
  870 #endif /* !DEFAULT_COMMENT */
  871 #ifndef ART_MARK_UNREAD
  872 #   define ART_MARK_UNREAD  '+' /* used to show that an art is unread */
  873 #endif /* !ART_MARK_UNREAD */
  874 #ifndef ART_MARK_RETURN
  875 #   define ART_MARK_RETURN  '-' /* used to show that an art will return */
  876 #endif /* !ART_MARK_RETURN */
  877 #ifndef ART_MARK_SELECTED
  878 #   define ART_MARK_SELECTED    '*' /* used to show that an art was auto selected */
  879 #endif /* !ART_MARK_SELECTED */
  880 #ifndef ART_MARK_RECENT
  881 #   define ART_MARK_RECENT  'o' /* used to show that an art is fresh */
  882 #endif /* !ART_MARK_RECENT */
  883 #ifndef ART_MARK_READ
  884 #   define ART_MARK_READ    ' ' /* used to show that an art was not read or seen */
  885 #endif /* !ART_MARK_READ */
  886 #ifndef ART_MARK_READ_SELECTED
  887 #   define ART_MARK_READ_SELECTED ':'   /* used to show that an read art is hot (kill_level >0) */
  888 #endif /* !ART_MARK_READ_SELECTED */
  889 #ifndef ART_MARK_KILLED
  890 #   define ART_MARK_KILLED 'K'      /* art has been killed (kill_level >0) */
  891 #endif /* !ART_MARK_KILLED */
  892 #ifndef ART_MARK_DELETED
  893 #   define ART_MARK_DELETED 'D' /* art has been marked for deletion (mailgroup) */
  894 #endif /* !ART_MARK_DELETED */
  895 #ifndef MARK_INRANGE
  896 #   define MARK_INRANGE '#' /* group/art within a range (# command) */
  897 #endif /* !MARK_INRANGE */
  898 
  899 
  900 /*
  901  * Unicode chars for thread and attachment tree and cursor (instead of "|+`->")
  902  * only available when IS_LOCAL_CHARSET("UTF-8")
  903  */
  904 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  905     /*
  906      * For CURSOR_ARROW and CURSOR_HORIZ tinrc.utf8_graphics ? :
  907      * is handled inside screen.c:draw_arrow_mark().
  908      */
  909 #   define CURSOR_ARROW     (wint_t) 0x25B6
  910 #   define CURSOR_HORIZ     (wint_t) 0x2500
  911 #   define TREE_ARROW       (wchar_t) (tinrc.utf8_graphics ? 0x25B6 : '>')
  912 #   define TREE_ARROW_WRAP  (wchar_t) (tinrc.utf8_graphics ? 0x25B7 : '>')
  913 #   define TREE_BLANK       (wchar_t) ' '
  914 #   define TREE_HORIZ       (wchar_t) (tinrc.utf8_graphics ? 0x2500 : '-')
  915 #   define TREE_UP_RIGHT    (wchar_t) (tinrc.utf8_graphics ? 0x2514 : '`')
  916 #   define TREE_VERT        (wchar_t) (tinrc.utf8_graphics ? 0x2502 : '|')
  917 #   define TREE_VERT_RIGHT  (wchar_t) (tinrc.utf8_graphics ? 0x251C : '+')
  918 #else
  919     /*
  920      * No need for CURSOR_ARROW and CURSOR_HORIZ here. This is handled inside
  921      * screen.c:draw_arrow_mark().
  922      */
  923 #   define TREE_ARROW       '>'
  924 #   define TREE_ARROW_WRAP  '>'
  925 #   define TREE_BLANK       ' '
  926 #   define TREE_HORIZ       '-'
  927 #   define TREE_UP_RIGHT    '`'
  928 #   define TREE_VERT        '|'
  929 #   define TREE_VERT_RIGHT  '+'
  930 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  931 
  932 #ifdef USE_INVERSE_HACK
  933 #   define BLANK_PAGE_COLS  2
  934 #else
  935 #   define BLANK_PAGE_COLS  0
  936 #endif /* USE_INVERSE_HACK */
  937 
  938 /*
  939  * Return values for tin_errno
  940  */
  941 #define TIN_ABORT       1           /* User requested abort or timeout */
  942 
  943 #define TINRC_CONFIRM_ACTION    (tinrc.confirm_choice == 1 || tinrc.confirm_choice == 4 || tinrc.confirm_choice == 5 || tinrc.confirm_choice == 7)
  944 #define TINRC_CONFIRM_TO_QUIT   (tinrc.confirm_choice == 3 || tinrc.confirm_choice == 4 || tinrc.confirm_choice == 6 || tinrc.confirm_choice == 7)
  945 #define TINRC_CONFIRM_SELECT    (tinrc.confirm_choice == 2 || tinrc.confirm_choice == 5 || tinrc.confirm_choice == 6 || tinrc.confirm_choice == 7)
  946 
  947 /*
  948  * defines for tinrc.auto_cc_bcc
  949  */
  950 #define AUTO_CC                 1
  951 #define AUTO_BCC                2
  952 #define AUTO_CC_BCC             3
  953 
  954 /*
  955  * defines for tinrc.goto_next_unread
  956  */
  957 #define NUM_GOTO_NEXT_UNREAD    4
  958 #define GOTO_NEXT_UNREAD_PGDN   1
  959 #define GOTO_NEXT_UNREAD_TAB    2
  960 
  961 /*
  962  * defines for tinrc.trim_article_body
  963  */
  964 #define NUM_TRIM_ARTICLE_BODY   8
  965 #define SKIP_LEADING            1
  966 #define SKIP_TRAILING           2
  967 #define COMPACT_MULTIPLE        4
  968 
  969 /*
  970  * MIME Encodings
  971  */
  972 enum {
  973     MIME_ENCODING_8BIT = 0,
  974     MIME_ENCODING_BASE64,
  975     MIME_ENCODING_QP,
  976     MIME_ENCODING_7BIT
  977 };
  978 
  979 /*
  980  * Number of charset-traslation tables (iso2asci)
  981  */
  982 #define NUM_ISO_TABLES  7
  983 
  984 /*
  985  * Maximum permissible colour number
  986  */
  987 #define MAX_COLOR   15
  988 #define MAX_BACKCOLOR   7
  989 
  990 /*
  991  * Count of available attributes for highlighting
  992  */
  993 #define MAX_ATTR    6
  994 
  995 /*
  996  * Maximal permissible word mark type
  997  * 0 = nothing, 1 = mark, 2 = space
  998  */
  999 #define MAX_MARK    2
 1000 
 1001 /* Line number (starting at 0) of 1st non-header data on the screen */
 1002 /* ie, size of header */
 1003 #define INDEX_TOP   2
 1004 #define INDEX2LNUM(i)   (INDEX_TOP + (i) - currmenu->first)
 1005 #ifndef USE_CURSES
 1006 #   define INDEX2SNUM(i)    ((i) - currmenu->first)
 1007 #endif /* !USE_CURSES */
 1008 
 1009 #define GROUP_MATCH(s1, pat, case)      (wildmat(s1, pat, case))
 1010 
 1011 #define REGEX_FMT (tinrc.wildcard ? "%s" : "*%s*")
 1012 
 1013 #define IGNORE_ART(i)   ((tinrc.kill_level != KILL_THREAD && arts[i].killed) || (arts[i].thread == ART_EXPIRED))
 1014 /* only used for threading */
 1015 #define IGNORE_ART_THREAD(i)    (arts[i].thread != ART_UNTHREADED || (tinrc.kill_level == KILL_NOTHREAD && arts[i].killed))
 1016 
 1017 /*
 1018  * Is this part text/plain?
 1019  */
 1020 #define IS_PLAINTEXT(x) \
 1021             (x->type == TYPE_TEXT && strcasecmp("plain", x->subtype) == 0)
 1022 
 1023 /* TRUE if basenote has responses */
 1024 #define HAS_FOLLOWUPS(i)    (arts[base[i]].thread >= 0)
 1025 
 1026 /*
 1027  * Only close off our stream when reading on local spool
 1028  */
 1029 #ifdef NNTP_ABLE
 1030 #   define TIN_FCLOSE(x)    if (x != FAKE_NNTP_FP) fclose(x)
 1031 #else
 1032 #   define TIN_FCLOSE(x)    fclose(x)
 1033 #endif /* NNTP_ABLE */
 1034 
 1035 /*
 1036  * Often used macro to point to the group we are currenty in
 1037  */
 1038 #define CURR_GROUP  (active[my_group[selmenu.curr]])
 1039 
 1040 /*
 1041  * Defines an unread group
 1042  */
 1043 #define UNREAD_GROUP(i)     (!active[my_group[i]].bogus && active[my_group[i]].newsrc.num_unread > 0)
 1044 
 1045 /*
 1046  * Expands to singlar/plural version of string
 1047  */
 1048 #define PLURAL(x,y)         ((x == 1) ? _(y##_singular) : _(y##_plural))
 1049 
 1050 /*
 1051  * News/Mail group types
 1052  */
 1053 #define GROUP_TYPE_MAIL 0
 1054 #define GROUP_TYPE_NEWS 1
 1055 #define GROUP_TYPE_SAVE 2   /* saved news, read with tin -R */
 1056 
 1057 /*
 1058  * used by get_arrow_key()
 1059  */
 1060 #   define KEYMAP_UNKNOWN       0
 1061 #   define KEYMAP_UP        1
 1062 #   define KEYMAP_DOWN      2
 1063 #   define KEYMAP_LEFT      3
 1064 #   define KEYMAP_RIGHT     4
 1065 #   define KEYMAP_PAGE_UP       5
 1066 #   define KEYMAP_PAGE_DOWN 6
 1067 #   define KEYMAP_HOME      7
 1068 #   define KEYMAP_END       8
 1069 #   define KEYMAP_DEL       9
 1070 #   define KEYMAP_INS       10
 1071 #   define KEYMAP_MOUSE     11
 1072 
 1073 
 1074 /*
 1075  * used in curses.c and signal.c
 1076  * it's useless trying to run tin below these sizes
 1077  * (values acquired by testing ;-) )
 1078  */
 1079 #define MIN_LINES_ON_TERMINAL        8
 1080 #define MIN_COLUMNS_ON_TERMINAL     50
 1081 
 1082 
 1083 /*
 1084  * indicate given cmd-line options
 1085  */
 1086 #define CMDLINE_GETART_LIMIT    1
 1087 #define CMDLINE_MAILDIR         2
 1088 #define CMDLINE_NNTPSERVER      4
 1089 #define CMDLINE_SAVEDIR         8
 1090 #define CMDLINE_USE_COLOR       16
 1091 
 1092 
 1093 /*
 1094  * used by feed_articles() & show_mini_help() & quick_filter & add_filter_rule
 1095  */
 1096 #define SELECT_LEVEL    1
 1097 #define GROUP_LEVEL 2
 1098 #define THREAD_LEVEL    3
 1099 #define PAGE_LEVEL  4
 1100 #define INFO_PAGER  5
 1101 #define SCOPE_LEVEL 6
 1102 #define CONFIG_LEVEL    7
 1103 #define ATTRIB_LEVEL    8
 1104 #define ATTACHMENT_LEVEL    9
 1105 #define URL_LEVEL   10
 1106 
 1107 #define MINI_HELP_LINES     5
 1108 
 1109 #define FEED_MAIL       1
 1110 #define FEED_PIPE       2
 1111 #define FEED_PRINT      3
 1112 #define FEED_SAVE       4
 1113 #define FEED_AUTOSAVE   5
 1114 #define FEED_REPOST     6
 1115 #define FEED_MARK_READ      7
 1116 #define FEED_MARK_UNREAD    8
 1117 
 1118 
 1119 /*
 1120  * Threading strategies available
 1121  */
 1122 #define THREAD_NONE     0
 1123 #define THREAD_SUBJ     1
 1124 #define THREAD_REFS     2
 1125 #define THREAD_BOTH     3
 1126 #define THREAD_MULTI        4
 1127 #define THREAD_PERC     5
 1128 
 1129 #define THREAD_MAX      THREAD_PERC
 1130 
 1131 #define THREAD_PERC_DEFAULT 75
 1132 
 1133 /*
 1134  * Values for show_author
 1135  */
 1136 #define SHOW_FROM_NONE      0
 1137 #define SHOW_FROM_ADDR      1
 1138 #define SHOW_FROM_NAME      2
 1139 #define SHOW_FROM_BOTH      3
 1140 
 1141 /*
 1142  * Values for thread_score
 1143  */
 1144 #define THREAD_SCORE_MAX    0
 1145 #define THREAD_SCORE_SUM    1
 1146 #define THREAD_SCORE_WEIGHT 2
 1147 
 1148 /*
 1149  * Values for interactive_mailer
 1150  */
 1151 enum {
 1152     INTERACTIVE_NONE = 0,
 1153     INTERACTIVE_WITH_HEADERS,
 1154     INTERACTIVE_WITHOUT_HEADERS
 1155 };
 1156 
 1157 /*
 1158  * used in feed.c & save.c
 1159  */
 1160 #define POST_PROC_NO        0
 1161 #define POST_PROC_SHAR      1
 1162 #define POST_PROC_YES       2
 1163 
 1164 /*
 1165  * used in art.c
 1166  * sort types on arts[] array
 1167  */
 1168 #define SORT_ARTICLES_BY_NOTHING        0
 1169 #define SORT_ARTICLES_BY_SUBJ_DESCEND   1
 1170 #define SORT_ARTICLES_BY_SUBJ_ASCEND    2
 1171 #define SORT_ARTICLES_BY_FROM_DESCEND   3
 1172 #define SORT_ARTICLES_BY_FROM_ASCEND    4
 1173 #define SORT_ARTICLES_BY_DATE_DESCEND   5
 1174 #define SORT_ARTICLES_BY_DATE_ASCEND    6
 1175 #define SORT_ARTICLES_BY_SCORE_DESCEND  7
 1176 #define SORT_ARTICLES_BY_SCORE_ASCEND   8
 1177 #define SORT_ARTICLES_BY_LINES_DESCEND  9
 1178 #define SORT_ARTICLES_BY_LINES_ASCEND   10
 1179 
 1180 /*
 1181  * used in art.c
 1182  * sort types on base[] array
 1183  */
 1184 #define SORT_THREADS_BY_NOTHING         0
 1185 #define SORT_THREADS_BY_SCORE_DESCEND   1
 1186 #define SORT_THREADS_BY_SCORE_ASCEND    2
 1187 #define SORT_THREADS_BY_LAST_POSTING_DATE_DESCEND   3
 1188 #define SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND    4
 1189 
 1190 /*
 1191  * Different values of strip_bogus - the ways to handle bogus groups
 1192  */
 1193 #define BOGUS_KEEP      0   /* not used */
 1194 #define BOGUS_REMOVE        1
 1195 #define BOGUS_SHOW      2
 1196 
 1197 /*
 1198  * Different extents to which we can hide killed articles
 1199  */
 1200 #define KILL_UNREAD     0       /* Kill only unread articles */
 1201 #define KILL_THREAD     1       /* Kill all articles and show as K */
 1202 #define KILL_NOTHREAD   2       /* Kill all articles, never show them */
 1203 
 1204 /*
 1205  * Various types of quoting behaviour
 1206  */
 1207 #define QUOTE_COMPRESS  1       /* Compress quotes */
 1208 #define QUOTE_SIGS      2       /* Quote signatures */
 1209 #define QUOTE_EMPTY     4       /* Quote empty lines */
 1210 
 1211 
 1212 /*
 1213  * used in save.c/main.c
 1214  */
 1215 #define CHECK_ANY_NEWS      0
 1216 #define START_ANY_NEWS      1
 1217 #define MAIL_ANY_NEWS       2
 1218 #define SAVE_ANY_NEWS       3
 1219 
 1220 
 1221 /*
 1222  * used in post.c
 1223  */
 1224 #define POSTED_NONE     0           /* Article wasn't posted */
 1225 #define POSTED_REDRAW       1           /* redraw needed in any case */
 1226 #define POSTED_OK       2           /* posted normally */
 1227 
 1228 
 1229 /*
 1230  * used in pager
 1231  */
 1232 #define UUE_NO          0       /* Don't hide uue data */
 1233 #define UUE_YES         1       /* Hide uue data */
 1234 #define UUE_ALL         2       /* Hide uue data harder */
 1235 
 1236 /*
 1237  * used in misc.c/rfc1524.c
 1238  */
 1239 enum quote_enum {
 1240     no_quote = 0,
 1241     dbl_quote,
 1242     sgl_quote
 1243 };
 1244 
 1245 
 1246 /*
 1247  * index_point variable values used throughout tin
 1248  */
 1249 
 1250 /*
 1251  * -1 is kind of overloaded as an error from which_thread() and other functions
 1252  * where we wish to return to the next level up
 1253  */
 1254 enum {
 1255     GRP_RETSELECT   = -1,   /* Pager 'T' command only -> return to selection screen */
 1256     GRP_QUIT        = -2,   /* Set by 'Q' when coming all the way out */
 1257     GRP_NEXTUNREAD  = -3,   /* (After catchup) goto next unread item */
 1258     GRP_NEXT        = -4,   /* (After catchup) move to next item */
 1259     GRP_ARTUNAVAIL  = -5,   /* show_page() Article is unavailable */
 1260     GRP_ARTABORT    = -6,   /* show_page() User aborted article read */
 1261     GRP_KILLED      = -7,   /* ?? Thread was killed at pager level */
 1262     GRP_GOTOTHREAD  = -8,   /* show_page() only. Goto thread menu */
 1263     GRP_ENTER       = -9,   /* New group is set, spin in read_groups() */
 1264     GRP_EXIT        = -10   /* Normal return to higher level */
 1265 };
 1266 
 1267 #ifndef EXIT_SUCCESS
 1268 #   define EXIT_SUCCESS 0   /* Successful exit status */
 1269 #endif /* !EXIT_SUCCESS */
 1270 
 1271 #ifndef EXIT_FAILURE
 1272 #   define EXIT_FAILURE 1   /* Failing exit status */
 1273 #endif /* !EXIT_FAILURE */
 1274 
 1275 #define NEWS_AVAIL_EXIT 2
 1276 #define NNTP_ERROR_EXIT 3
 1277 
 1278 /*
 1279  * Assertion verifier
 1280  */
 1281 #ifdef assert
 1282 #   undef assert
 1283 #endif /* assert */
 1284 #ifdef CPP_DOES_EXPAND
 1285 #   define assert(p)    if(! (p)) asfail(__FILE__, __LINE__, #p); else (void)0;
 1286 #else
 1287 #   define assert(p)    if(! (p)) asfail(__FILE__, __LINE__, "p"); else (void)0;
 1288 #endif /* CPP_DOES_EXPAND */
 1289 
 1290 #define ESC 27
 1291 
 1292 /*
 1293  * filter entrys expire after DEFAULT_FILTER_DAYS
 1294  */
 1295 #define DEFAULT_FILTER_DAYS     28
 1296 
 1297 /*
 1298  * art.thread
 1299  */
 1300 #define ART_UNTHREADED  -1
 1301 #define ART_EXPIRED     -2
 1302 
 1303 /*
 1304  * Where does this belong?? It is overloaded
 1305  */
 1306 #define ART_NORMAL      -1
 1307 
 1308 /*
 1309  * art.status
 1310  */
 1311 #define ART_READ        0
 1312 #define ART_UNREAD      1
 1313 #define ART_WILL_RETURN     2
 1314 #define ART_UNAVAILABLE     -1 /* Also used by msgid.article */
 1315 
 1316 /*
 1317  * art.killed
 1318  */
 1319 #define ART_NOTKILLED       0
 1320 #define ART_KILLED      1
 1321 #define ART_KILLED_UNREAD   2
 1322 
 1323 /*
 1324  * Additionally used for user aborts in art_open()
 1325  */
 1326 #define ART_ABORT       -2
 1327 
 1328 /*
 1329  * used by t_group & my_group[]
 1330  */
 1331 #define UNSUBSCRIBED    '!'
 1332 #define SUBSCRIBED  ':'
 1333 
 1334 /* Converts subscription status to char for .newsrc */
 1335 #define SUB_CHAR(x) (x ? SUBSCRIBED : UNSUBSCRIBED)
 1336 /* Converts .newsrc subscription char to boolean */
 1337 #define SUB_BOOL(x) (x == SUBSCRIBED)
 1338 
 1339 /*
 1340  * filter_type used in struct t_filter
 1341  */
 1342 #define SCORE_MAX       10000
 1343 
 1344 #define FILTER_SUBJ_CASE_SENSITIVE      0
 1345 #define FILTER_SUBJ_CASE_IGNORE     1
 1346 #define FILTER_FROM_CASE_SENSITIVE      2
 1347 #define FILTER_FROM_CASE_IGNORE     3
 1348 #define FILTER_MSGID        4
 1349 #define FILTER_MSGID_LAST   5
 1350 #define FILTER_MSGID_ONLY   6
 1351 #define FILTER_REFS_ONLY    7
 1352 #define FILTER_LINES        8
 1353 
 1354 #define FILTER_LINES_NO     0
 1355 #define FILTER_LINES_EQ     1
 1356 #define FILTER_LINES_LT     2
 1357 #define FILTER_LINES_GT     3
 1358 
 1359 /*
 1360  * default format strings for selection, group, thread level
 1361  * and the date display in the page header.
 1362  * Don't change without adjusting rc_update() and the like accordingly!
 1363  */
 1364 #define DEFAULT_SELECT_FORMAT   "%f %n %U  %G  %d"
 1365 #define DEFAULT_GROUP_FORMAT    "%n %m %R %L  %s  %F"
 1366 #define DEFAULT_THREAD_FORMAT   "%n %m  [%L]  %T  %F"
 1367 #define DEFAULT_DATE_FORMAT     "%a, %d %b %Y %H:%M:%S"
 1368 
 1369 /*
 1370  * unicode normalization
 1371  */
 1372 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1373 #   ifdef HAVE_LIBICUUC
 1374 #       define HAVE_UNICODE_NORMALIZATION 3
 1375 #   else
 1376 #       ifdef HAVE_LIBUNISTRING
 1377 #           define HAVE_UNICODE_NORMALIZATION 2
 1378 #       else
 1379 #           if defined(HAVE_LIBIDN) && defined(HAVE_STRINGPREP_H)
 1380 #               define HAVE_UNICODE_NORMALIZATION 1
 1381 #           endif /* HAVE_LIBIDN */
 1382 #       endif /* HAVE_LIBUNISTRING */
 1383 #   endif /* HAVE_LIBICUUC */
 1384 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1385 
 1386 /*
 1387  * normalization forms, we prefer NFC (see RFC 6532) if possible
 1388  */
 1389 #ifdef HAVE_UNICODE_NORMALIZATION
 1390 enum {
 1391     NORMALIZE_NONE = 0,
 1392 #   if (HAVE_UNICODE_NORMALIZATION >= 2)
 1393     NORMALIZE_NFKC = 1,
 1394     NORMALIZE_NFKD = 2,
 1395     NORMALIZE_NFC = 3,
 1396     NORMALIZE_NFD = 4
 1397 #       define DEFAULT_NORMALIZE NORMALIZE_NFC
 1398 #   else
 1399     NORMALIZE_NFKC = 1
 1400 #       define DEFAULT_NORMALIZE NORMALIZE_NFKC
 1401 #   endif /* HAVE_UNICODE_NORMALIZATION >= 2 */
 1402 };
 1403 #endif /* HAVE_UNICODE_NORMALIZATION */
 1404 
 1405 #ifdef HAVE_LIBICUUC
 1406 #   ifdef HAVE_UNICODE_USTRING_H
 1407 #       include <unicode/ustring.h>
 1408 #   endif /* HAVE_UNICODE_USTRING_H */
 1409 #   ifdef HAVE_UNICODE_UNORM_H
 1410 #       include <unicode/unorm.h>
 1411 #   endif /* HAVE_UNICODE_UNORM_H */
 1412 #   ifdef HAVE_UNICODE_UIDNA_H
 1413 #       include <unicode/uidna.h>
 1414 #   endif /* HAVE_UNICODE_UIDNA_H */
 1415 #   ifdef HAVE_UNICODE_UBIDI_H
 1416 #       include <unicode/ubidi.h>
 1417 #   endif /* HAVE_UNICODE_UBIDI_H */
 1418 #endif /* HAVE_LIBICUUC */
 1419 
 1420 
 1421 /*
 1422  * used in checking article header before posting
 1423  */
 1424 #define MAX_COL     78  /* Max. line length before issuing a warning */
 1425 #define MAX_SIG_LINES   4   /* Max. num. of signature lines before warning */
 1426 
 1427 typedef unsigned char   t_bitmap;
 1428 
 1429 /*
 1430  * Keys for add_msgid()
 1431  */
 1432 #define REF_REF             1       /* Add a ref->ref entry */
 1433 #define MSGID_REF           2       /* Add a msgid->ref entry */
 1434 
 1435 /*
 1436  * Size of msgid hash table
 1437  */
 1438 #define MSGID_HASH_SIZE     2609
 1439 
 1440 /*
 1441  * cmd-line options
 1442  */
 1443 struct t_cmdlineopts {
 1444     int getart_limit;           /* getart_limit */
 1445     char maildir[PATH_LEN];     /* maildir */
 1446     char nntpserver[PATH_LEN];  /* nntpserver */
 1447     char savedir[PATH_LEN];     /* savedir */
 1448     unsigned int args:5;        /* given options */
 1449 };
 1450 
 1451 /*
 1452  * Archive-Name: header
 1453  */
 1454 struct t_archive {
 1455     char *name;         /* name of archive */
 1456     char *partnum;          /* part/patch no. in archive */
 1457     t_bool ispart:1;        /* TRUE if part, FALSE if patch */
 1458 };
 1459 
 1460 /*
 1461  * struct t_msgid - message id
 1462  */
 1463 struct t_msgid {
 1464     struct t_msgid *next;       /* Next in hash chain */
 1465     struct t_msgid *parent;     /* Message-id followed up to */
 1466     struct t_msgid *sibling;    /* Next followup to parent */
 1467     struct t_msgid *child;      /* First followup to this article */
 1468     int article;            /* index in arts[] or ART_NORMAL */
 1469     char txt[1];            /* The actual msgid */
 1470 };
 1471 
 1472 /*
 1473  * struct t_article - article header
 1474  *
 1475  * article.thread:
 1476  * the next article in thread
 1477  *  -1  (ART_UNTHREADED) article exists but is not (yet) threaded
 1478  *  -2  (ART_EXPIRED) article has expired (wasn't found in search of spool
 1479  *      directory for the group)
 1480  *  >=0 points to another arts[] (struct t_article)
 1481  *
 1482  * article.prev:
 1483  *  the previous article in thread
 1484  *  -1  (ART_NORMAL) initial default, first (no previous) article in thread
 1485  *  >=0 points to the previous arts[] (struct t_article)
 1486  */
 1487 struct t_article {
 1488     t_artnum artnum;        /* Article number in spool directory for group */
 1489     char *subject;          /* Subject: line from mail header */
 1490     char *from;         /* From: line from mail header (address) */
 1491     char *name;         /* From: line from mail header (full name) */
 1492     int gnksa_code;         /* From: line from mail header (GNKSA error code) */
 1493     time_t date;            /* Date: line from header in seconds */
 1494     char *xref;         /* Xref: cross posted article reference line */
 1495     /* NB: The msgid and refs are only retained until the reference tree is built */
 1496     char *msgid;            /* Message-ID: unique message identifier */
 1497     char *refs;         /* References: article reference id's */
 1498     struct t_msgid *refptr;     /* Pointer to us in the reference tree */
 1499     int line_count;         /* Lines: number of lines in article */
 1500     struct t_archive *archive;  /* Archive-Name: header */
 1501     int tagged;         /* 0 = not tagged, >0 = tagged */
 1502     int thread;
 1503     int prev;
 1504     int score;          /* score article has reached after filtering */
 1505     unsigned int status:2;  /* 0 = read, 1 = unread, 2 = will return */
 1506     unsigned int killed:2;  /* 0 = not killed, 1 = killed, 2 = killed unread */
 1507     t_bool zombie:1;    /* 1 = was alive (unread) before 'X' command */
 1508     t_bool delete_it:1; /* 1 = delete art when leaving group [mail group] */
 1509     t_bool selected:1;  /* FALSE = not selected, TRUE = selected */
 1510     t_bool inrange:1;   /* TRUE = article selected via # range command */
 1511     t_bool matched:1;   /* TRUE = article matched regex in feed.c */
 1512     t_bool keep_in_base:1;  /* TRUE = keep (read) article in base[] (show_only_unread_arts) */
 1513 };
 1514 
 1515 /*
 1516  * struct t_newsheader - holds an array of which news headers to [not] display
 1517  */
 1518 struct t_newsheader {
 1519     char **header;  /* array of which headers to [not] display */
 1520     int num;        /* number of headers in array header */
 1521 };
 1522 
 1523 /*
 1524  * struct t_attribute - configurable attributes on a per group basis
 1525  */
 1526 struct t_attribute {
 1527     char *maildir;              /* mail dir if other than ~/Mail */
 1528     char *savedir;              /* save dir if other than ~/News */
 1529     char *savefile;             /* save articles to specified file */
 1530     char *sigfile;              /* sig file if other than ~/.Sig */
 1531     char *group_format;         /* format string for group level */
 1532     char *thread_format;        /* format string for thread level */
 1533     char *date_format;          /* format string for the date display */
 1534     char *editor_format;        /* editor + parameters  %E +%N %F */
 1535     char *organization;         /* organization name */
 1536     char *fcc;                  /* Fcc folder for mail */
 1537     char *followup_to;          /* where posts should be redirected */
 1538     char *quick_kill_scope;     /* quick filter kill scope */
 1539     char *quick_select_scope;   /* quick filter select scope */
 1540     char *mailing_list;         /* mail list email address */
 1541     char *news_headers_to_display;  /* which headers to display */
 1542     char *news_headers_to_not_display;  /* which headers to not display */
 1543     char *x_headers;            /* extra headers for message header */
 1544     char *x_body;               /* boilerplate text for message body */
 1545     char *from;                 /* from line */
 1546     char *news_quote_format;    /* another way to begin a posting format */
 1547     char *quote_chars;          /* string to precede quoted text on each line */
 1548     char *mime_types_to_save;   /* MIME content major/minors we want to save */
 1549 #ifdef HAVE_ISPELL
 1550     char *ispell;               /* path to ispell and options */
 1551 #endif /* HAVE_ISPELL */
 1552 #ifdef CHARSET_CONVERSION
 1553     char *undeclared_charset;       /* charset of articles without MIME charset declaration */
 1554     int mm_network_charset;         /* network charset */
 1555 #endif /* CHARSET_CONVERSION */
 1556     struct t_newsheader *headers_to_display;    /* array of which headers to display */
 1557     struct t_newsheader *headers_to_not_display;    /* array of which headers to not display */
 1558     unsigned global:1;          /* global/group specific */
 1559     unsigned quick_kill_header:3;   /* quick filter kill header */
 1560     unsigned quick_kill_expire:1;   /* quick filter kill limited/unlimited time */
 1561     unsigned quick_kill_case:1;     /* quick filter kill case sensitive? */
 1562     unsigned quick_select_header:3; /* quick filter select header */
 1563     unsigned quick_select_expire:1; /* quick filter select limited/unlimited time */
 1564     unsigned quick_select_case:1;   /* quick filter select case sensitive? */
 1565     unsigned add_posted_to_filter:1;    /* add posted articles to filter */
 1566     unsigned advertising:1;         /* add User-Agent: -header */
 1567     unsigned alternative_handling:1;    /* skip multipart/alternative parts */
 1568     unsigned ask_for_metamail:1;    /* ask before using MIME viewer */
 1569     unsigned auto_cc_bcc:2;         /* add your name to cc/bcc automatically */
 1570     unsigned auto_list_thread:1;    /* list thread when entering it using right arrow */
 1571     unsigned auto_select:1;         /* 0=show all unread, 1='X' just hot arts */
 1572     unsigned auto_save:1;           /* 0=none, 1=save */
 1573     unsigned batch_save:1;          /* 0=none, 1=save -S/mail -M */
 1574     unsigned delete_tmp_files:1;    /* 0=leave, 1=delete */
 1575     unsigned group_catchup_on_exit:1;   /* ask if read groups are to be marked read */
 1576     unsigned mail_8bit_header:1;    /* allow 8bit chars. in header of mail message */
 1577     unsigned mail_mime_encoding:2;
 1578     unsigned mark_ignore_tags:1;    /* Ignore tags for GROUP_MARK_THREAD_READ/THREAD_MARK_ARTICLE_READ */
 1579     unsigned mark_saved_read:1;     /* mark saved article/thread as read */
 1580     unsigned pos_first_unread:1;    /* position cursor at first/last unread article */
 1581     unsigned post_8bit_header:1;    /* allow 8bit chars. in header when posting to newsgroup */
 1582     unsigned post_mime_encoding:2;
 1583     unsigned post_process_view:1;   /* set TRUE to invoke mailcap viewer app */
 1584 #ifndef DISABLE_PRINTING
 1585     unsigned print_header:1;        /* print all of mail header or just Subject: & From lines */
 1586 #endif /* !DISABLE_PRINTING */
 1587     unsigned process_only_unread:1; /* save/print//mail/pipe unread/all articles */
 1588     unsigned prompt_followupto:1;   /* display empty Followup-To header in editor */
 1589     unsigned show_only_unread_arts:1;   /* 0=all, 1=only unread */
 1590     unsigned sigdashes:1;           /* set TRUE to prepend every signature with dashes */
 1591     unsigned signature_repost:1;    /* set TRUE to add signature when reposting articles */
 1592     unsigned start_editor_offset:1; /* start editor with line offset */
 1593     unsigned thread_articles:3;         /* 0=unthread, 1=subject, 2=refs, 3=both, 4=multipart, 5=percentage */
 1594     unsigned thread_catchup_on_exit:1;  /* catchup thread with left arrow key or not */
 1595     unsigned thread_perc:7;         /* percentage threading threshold */
 1596     unsigned show_author:2;         /* 0=none, 1=name, 2=addr, 3=both */
 1597     unsigned show_signatures:1;     /* 0=none, 1=show signatures */
 1598     unsigned trim_article_body:3;   /* 0=Don't trim article body, 1=Skip leading blank lines,
 1599                         2=Skip trailing blank lines, 3=Skip leading and trailing blank lines,
 1600                         4=Compact multiple blank lines between textblocks,
 1601                         5=Compact multiple blank lines between textblocks and skip leading blank lines,
 1602                         6=Compact multiple blank lines between textblocks and skip trailing blank lines,
 1603                         7=Compact multiple blank lines between textblocks and skip leading and trailing
 1604                           blank lines */
 1605     unsigned verbatim_handling:1;   /* 0=none, 1=detect verbatim blocks */
 1606 #ifdef HAVE_COLOR
 1607     unsigned extquote_handling:1;       /* 0=none, 1=detect quoted text from external sources */
 1608 #endif /* HAVE_COLOR */
 1609     unsigned wrap_on_next_unread:1; /* Wrap around threads when searching next unread article */
 1610     unsigned sort_article_type:4;       /* 0=none, 1=subj descend, 2=subj ascend,
 1611                            3=from descend, 4=from ascend,
 1612                            5=date descend, 6=date ascend,
 1613                            7=score descend, 8=score ascend */
 1614     unsigned sort_threads_type:3;   /* 0=none, 1=score descend, 2=score ascend,
 1615                            3=last posting date descend, 4=last posting date ascend */
 1616     unsigned post_process_type:2;   /* 0=none, 1=shar, 2=uudecode */
 1617     unsigned x_comment_to:1;    /* insert X-Comment-To: in Followup */
 1618     unsigned tex2iso_conv:1;    /* Convert TeX2ISO */
 1619     unsigned mime_forward:1;    /* forward articles as attachment or inline */
 1620 };
 1621 
 1622 /*
 1623  * struct t_attribute_state - holds additional information
 1624  * about numeric attributes within a scope
 1625  */
 1626 struct t_attribute_state {
 1627     unsigned add_posted_to_filter:1;
 1628     unsigned advertising:1;
 1629     unsigned alternative_handling:1;
 1630     unsigned ask_for_metamail:1;
 1631     unsigned auto_cc_bcc:1;
 1632     unsigned auto_list_thread:1;
 1633     unsigned auto_save:1;
 1634     unsigned auto_select:1;
 1635     unsigned batch_save:1;
 1636     unsigned date_format:1;
 1637     unsigned delete_tmp_files:1;
 1638     unsigned editor_format:1;
 1639     unsigned fcc:1;
 1640     unsigned followup_to:1;
 1641     unsigned from:1;
 1642     unsigned group_catchup_on_exit:1;
 1643     unsigned group_format:1;
 1644 #ifdef HAVE_ISPELL
 1645     unsigned ispell:1;
 1646 #endif /* HAVE_ISPELL */
 1647     unsigned mail_8bit_header:1;
 1648     unsigned mail_mime_encoding:1;
 1649     unsigned maildir:1;
 1650     unsigned mailing_list:1;
 1651     unsigned mark_ignore_tags:1;
 1652     unsigned mark_saved_read:1;
 1653     unsigned mime_forward:1;
 1654     unsigned mime_types_to_save:1;
 1655     unsigned news_headers_to_display:1;
 1656     unsigned news_headers_to_not_display:1;
 1657     unsigned news_quote_format:1;
 1658     unsigned organization:1;
 1659     unsigned pos_first_unread:1;
 1660     unsigned post_8bit_header:1;
 1661     unsigned post_mime_encoding:1;
 1662     unsigned post_process_view:1;
 1663     unsigned post_process_type:1;
 1664 #ifndef DISABLE_PRINTING
 1665     unsigned print_header:1;
 1666 #endif /* !DISABLE_PRINTING */
 1667     unsigned process_only_unread:1;
 1668     unsigned prompt_followupto:1;
 1669     unsigned quick_kill_case:1;
 1670     unsigned quick_kill_expire:1;
 1671     unsigned quick_kill_header:1;
 1672     unsigned quick_kill_scope:1;
 1673     unsigned quick_select_case:1;
 1674     unsigned quick_select_expire:1;
 1675     unsigned quick_select_header:1;
 1676     unsigned quick_select_scope:1;
 1677     unsigned quote_chars:1;
 1678     unsigned savedir:1;
 1679     unsigned savefile:1;
 1680     unsigned show_author:1;
 1681     unsigned show_only_unread_arts:1;
 1682     unsigned show_signatures:1;
 1683     unsigned sigdashes:1;
 1684     unsigned sigfile:1;
 1685     unsigned signature_repost:1;
 1686     unsigned sort_article_type:1;
 1687     unsigned sort_threads_type:1;
 1688     unsigned start_editor_offset:1;
 1689     unsigned tex2iso_conv:1;
 1690     unsigned thread_articles:1;
 1691     unsigned thread_catchup_on_exit:1;
 1692     unsigned thread_format:1;
 1693     unsigned thread_perc:1;
 1694     unsigned trim_article_body:1;
 1695 #ifdef CHARSET_CONVERSION
 1696     unsigned undeclared_charset:1;
 1697     unsigned mm_network_charset:1;
 1698 #endif /* CHARSET_CONVERSION */
 1699     unsigned verbatim_handling:1;
 1700 #ifdef HAVE_COLOR
 1701     unsigned extquote_handling:1;
 1702 #endif /* HAVE_COLOR */
 1703     unsigned wrap_on_next_unread:1;
 1704     unsigned x_body:1;
 1705     unsigned x_comment_to:1;
 1706     unsigned x_headers:1;
 1707 };
 1708 
 1709 /*
 1710  * struct t_scope
 1711  */
 1712 struct t_scope {
 1713     char *scope;                /* scope for these group attributes */
 1714     struct t_attribute *attribute;  /* the attributes itself */
 1715     struct t_attribute_state *state;    /* additional information about numeric attributes */
 1716     unsigned global:1;          /* TRUE for scopes from global_attributes_file */
 1717 };
 1718 
 1719 /*
 1720  * struct t_newsrc - newsrc related info.
 1721  */
 1722 struct t_newsrc {
 1723     t_bool present:1;       /* update newsrc? */
 1724     t_artnum num_unread;        /* unread articles in group */
 1725     t_artnum xmax;          /* newsrc max */
 1726     t_artnum xmin;          /* newsrc min */
 1727     t_artnum xbitlen;           /* bitmap length (max-min+1) */
 1728     t_bitmap *xbitmap;  /* bitmap read/unread (max-min+1+7)/8 */
 1729 };
 1730 
 1731 /*
 1732  * struct t_group - newsgroup info from active file
 1733  */
 1734 struct t_group {
 1735     char *name;         /* newsgroup/mailbox name */
 1736     char *aliasedto;        /* =new.group in active file, NULL if not */
 1737     char *description;  /* text from NEWSLIBDIR/newsgroups file */
 1738     char *spooldir;     /* groups spool directory */
 1739     char moderated;     /* state of group moderation */
 1740     t_artnum count;     /* article number count */
 1741     t_artnum xmax;      /* max. article number */
 1742     t_artnum xmin;      /* min. article number */
 1743     unsigned int type:4;        /* grouptype - newsgroup/mailbox/savebox */
 1744     t_bool inrange:1;       /* TRUE if group selected via # range command */
 1745     t_bool read_during_session:1;   /* TRUE if group entered during session */
 1746     t_bool art_was_posted:1;    /* TRUE if art was posted to group */
 1747     t_bool subscribed:1;        /* TRUE if subscribed to group */
 1748     t_bool newgroup:1;      /* TRUE if group was new this session */
 1749     t_bool bogus:1;         /* TRUE if group is not in active list */
 1750     int next;           /* next active entry in hash chain */
 1751     struct t_newsrc newsrc;     /* newsrc bitmap specific info. */
 1752     struct t_attribute *attribute;  /* group specific attributes */
 1753     struct t_filters *glob_filter;  /* points to filter array */
 1754 };
 1755 
 1756 /*
 1757  * used in hashstr.c
 1758  */
 1759 struct t_hashnode {
 1760     struct t_hashnode *next;    /* chain for spillover */
 1761     int aptr;           /* used in subject threading */
 1762     char txt[1];            /* stub for the string data, \0 terminated */
 1763 };
 1764 
 1765 /*
 1766  * used for variable screen layout
 1767  *
 1768  * holds a preparsed format string, a date format string and some
 1769  * precalculated length
 1770  */
 1771 struct t_fmt {
 1772     char str[LEN];
 1773     char date_str[LEN];
 1774     size_t len_date;        /* %D Date */
 1775     size_t len_date_max;
 1776     size_t len_grpdesc;     /* %d newsgroup description */
 1777     size_t len_from;        /* %F From */
 1778     size_t len_grpname;     /* %G groupname */
 1779     size_t len_grpname_dsc;
 1780     size_t len_grpname_max;
 1781     size_t len_initials;    /* %I initials */
 1782     size_t len_linenumber;  /* %n linenumber on screen */
 1783     size_t len_linecnt;     /* %L line count (article) */
 1784     size_t len_msgid;       /* %M message-id */
 1785     size_t len_respcnt;     /* %R count, number of responses */
 1786     size_t len_score;       /* %S score */
 1787     size_t len_subj;        /* %s subject */
 1788     size_t len_ucnt;        /* %U unread count */
 1789     size_t flags_offset;
 1790     size_t mark_offset;
 1791     size_t ucnt_offset;
 1792     t_bool show_grpdesc;
 1793     t_bool d_before_f;
 1794     t_bool g_before_f;
 1795     t_bool d_before_u;
 1796     t_bool g_before_u;
 1797 };
 1798 
 1799 /*
 1800  * used in filter.c
 1801  *
 1802  * Create 2 filter arrays - global & local. Local will be part of group_t
 1803  * structure and will have priority over global filter. Should help to
 1804  * speed kill/selecting within a group. The long value number that is in
 1805  * ~/.tin/kill will be replaced by group name so that it is more human
 1806  * readable and that if hash routine is changed it will still work.
 1807  *
 1808  * Add time period to filter_t struct to allow timed kills & auto-selection
 1809  * Default kill & select time 28 days. Store as a long and compare when
 1810  * loading against present time. If time secs is passed set flag to save
 1811  * filter file and don't load expired entry. Renamed to filter because of
 1812  * future directions in adding other retrieval methods to present kill &
 1813  * auto selection.
 1814  *
 1815  * Also separate kill/select screen to allow ^K=kill ^A=auto-select
 1816  */
 1817 struct t_filters {
 1818     int max;
 1819     int num;
 1820     struct t_filter *filter;
 1821 };
 1822 
 1823 /*
 1824  * struct t_filter_comment: allow multiple comment-lines in filter-file.
 1825  */
 1826 struct t_filter_comment {
 1827     char *text;         /* One line of comment. */
 1828     struct t_filter_comment *next;  /* points to next comment-entry */
 1829 };
 1830 
 1831 /*
 1832  * struct t_filter - local & global filtering (ie. kill & auto-selection)
 1833  */
 1834 struct t_filter {
 1835     struct t_filter_comment *comment;
 1836     char *scope;            /* NULL='*' (all groups) or 'comp.os.*' */
 1837     char *subj;         /* Subject: line */
 1838     char *from;         /* From: line */
 1839     char *msgid;            /* Message-ID: line */
 1840     char lines_cmp;         /* Lines compare <> */
 1841     int lines_num;          /* Lines: line */
 1842     char gnksa_cmp;         /* GNKSA compare <> */
 1843     int gnksa_num;          /* GNKSA code */
 1844     int score;          /* score to give if rule matches */
 1845     char *xref;         /* groups in xref line */
 1846     time_t time;            /* expire time in seconds */
 1847     struct t_filter *next;      /* next rule valid in group */
 1848     unsigned int inscope:4;     /* if group matches scope e.g. 'comp.os.*' */
 1849     unsigned int icase:2;       /* Case sensitive filtering */
 1850     unsigned int fullref:4;     /* use full references or last entry only */
 1851 };
 1852 
 1853 /*
 1854  * struct t_filter_rule - provides parameters to build filter rule from
 1855  */
 1856 struct t_filter_rule {
 1857     struct t_filter_comment *comment;
 1858     char text[PATH_LEN];
 1859     char scope[PATH_LEN];
 1860     int counter;
 1861     int icase;
 1862     int fullref;
 1863     int lines_cmp;
 1864     int lines_num;
 1865     int score;
 1866     int expire_time;
 1867     t_bool from_ok:1;
 1868     t_bool lines_ok:1;
 1869     t_bool msgid_ok:1;
 1870     t_bool subj_ok:1;
 1871     t_bool check_string:1;
 1872 };
 1873 
 1874 /*
 1875  * Filter cache structure using Philip Hazel's Perl regular expression
 1876  * library (see pcre/pcre.[ch] for details)
 1877  */
 1878 struct regex_cache {
 1879     pcre *re;
 1880     pcre_extra *extra;
 1881 };
 1882 
 1883 struct t_save {
 1884     char *path;
 1885     char *file;                 /* ptr to file part of *path */
 1886     t_bool mailbox:1;           /* Set if path is a mailbox */
 1887 };
 1888 
 1889 #ifndef USE_CURSES
 1890 struct t_screen {
 1891     char *col;
 1892 };
 1893 #endif /* !USE_CURSES */
 1894 
 1895 struct t_posted {
 1896     char date[10];
 1897     char group[80];
 1898     char action;
 1899     char subj[120];
 1900 };
 1901 
 1902 struct t_art_stat {
 1903     char art_mark;      /* mark to use for this thread - not used for groups */
 1904     int total;      /* total article count */
 1905     int unread;     /* number of unread articles (does not include seen) arts */
 1906     int seen;       /* number of seen articles (ART_WILL_RETURN) */
 1907     int deleted;        /* number of articles marked for deletion (mailgroups) */
 1908     int inrange;        /* number of articles marked in a range */
 1909     int selected_total; /* total selected count */
 1910     int selected_unread;    /* selected and unread */
 1911     int selected_seen;  /* selected and seen */
 1912     int killed;     /* killed */
 1913     int score;      /* maximum score */
 1914     int multipart_total; /* 0=not multipart, >0 = number of articles in the multipart */
 1915     int multipart_have; /* number of articles we actually have found */
 1916     int multipart_compare_len; /* length of subject which contains non-specific multipart info */
 1917     time_t time;        /* latest time */
 1918 };
 1919 
 1920 
 1921 /*
 1922  * Used for detecting changes in active file size on different news servers
 1923  */
 1924 struct t_newnews {
 1925     char *host;
 1926     time_t time;
 1927 };
 1928 
 1929 typedef const char constext;
 1930 
 1931 /*
 1932  * Defines text strings used by a tinrc variable
 1933  */
 1934 struct opttxt {
 1935     constext *help;                 /* Helptext on Option Menu */
 1936     constext *opt;                  /* Text on body of Option Menu screen */
 1937     constext *tinrc;                /* (optional) Text written with variable to tinrc file */
 1938 };
 1939 
 1940 /*
 1941  * Used for building option menu
 1942  */
 1943 struct t_option {
 1944     int var_type;       /* type of variable (see tincfg.h) */
 1945     int var_index;      /* index in corresponding table */
 1946     int *variable;      /* ptr to variable to change */
 1947     constext **opt_list;    /* ptr to list entries if OPT_LIST */
 1948     struct opttxt *txt; /* ptr to information/help on option */
 1949 };
 1950 
 1951 /*
 1952  * Multipart article detection
 1953  */
 1954 typedef struct {
 1955     char *subject;
 1956     int subject_compare_len;
 1957     int part_number;
 1958     int total;
 1959     int base_index;
 1960 } MultiPartInfo;
 1961 
 1962 
 1963 /*
 1964  * Key information about current menu screen
 1965  */
 1966 typedef struct {
 1967     int curr;                   /* Current cursor pos (cur_groupnum, index_point, thread_index_point) */
 1968     int max;                    /* Max # on current menu (group_top, top_base, top_thread) */
 1969     int first;                  /* First # on current menu */
 1970     void (*redraw) (void);      /* Redraw function */
 1971     void (*draw_arrow) (void);  /* Arrow draw */
 1972     void (*draw_item) (int item);   /* draw the specified item */
 1973 } t_menu;
 1974 
 1975 
 1976 /*
 1977  * Packet of data needed to enter pager
 1978  */
 1979 typedef struct {
 1980     int art;
 1981     t_bool ignore_unavail:1;
 1982 } t_pagerinfo;
 1983 
 1984 
 1985 /*
 1986  * Time functions.
 1987  */
 1988 typedef struct _TIMEINFO {
 1989     time_t time;
 1990     long usec;
 1991     long tzone;
 1992 } TIMEINFO;
 1993 
 1994 
 1995 struct t_tintime {
 1996     time_t tv_sec; /* seconds */
 1997     long tv_nsec; /* nanoseconds */
 1998 };
 1999 
 2000 
 2001 /*
 2002  * mailcap fields
 2003  * the x-token field is missing, we would need something like
 2004  * struct t_xtoken { char *xtoken; t_xtoken *next; } for that ...
 2005  */
 2006 typedef struct {
 2007     char *type;     /* content-type, mandatory */
 2008     char *command;  /* view-command, mandatory */
 2009     char *compose;
 2010     char *composetyped;
 2011     char *description;
 2012     char *edit;
 2013     char *nametemplate;
 2014     char *print;
 2015     char *test;
 2016     char *x11bitmap;
 2017     int textualnewlines;
 2018     t_bool needsterminal:1;
 2019     t_bool copiousoutput:1;
 2020 } t_mailcap;
 2021 
 2022 
 2023 typedef struct urllist {
 2024     char *url;
 2025     struct urllist *next;
 2026 } t_url;
 2027 
 2028 
 2029 /*
 2030  * Determine signal return type
 2031  */
 2032 #ifndef RETSIGTYPE
 2033 #   define RETSIGTYPE void
 2034 #endif /* !RETSIGTYPE */
 2035 
 2036 /*
 2037  * Determine qsort compare type
 2038  */
 2039 #ifdef HAVE_COMPTYPE_VOID
 2040 #   ifdef __STDC__
 2041         typedef const void *t_comptype;
 2042 #   else
 2043         typedef void *t_comptype;
 2044 #   endif /* __STDC__ */
 2045 #else
 2046 #   ifdef HAVE_COMPTYPE_CHAR
 2047         typedef char *t_comptype;
 2048 #   endif /* HAVE_COMPTYPE_CHAR */
 2049 #endif /* HAVE_COMPTYPE_VOID */
 2050 
 2051 /* Define a matching function pointer type */
 2052 typedef int (*t_compfunc)(t_comptype, t_comptype);
 2053 typedef void (*t_sortfunc)(void *, size_t, size_t, t_compfunc);
 2054 
 2055 #define _CDECL
 2056 
 2057 /* set to (void)heapsort or qsort */
 2058 #ifndef USE_HEAPSORT
 2059 #   define tin_sort qsort
 2060 #else
 2061 #   define MAX_SORT_FUNCS 1
 2062 #endif /* !USE_HEAPSORT */
 2063 
 2064 /* Separator between dir part of path & the filename */
 2065 #define DIRSEP  '/'
 2066 
 2067 /*
 2068  * mouse buttons for use in xterm
 2069  */
 2070 #define MOUSE_BUTTON_1      0
 2071 #define MOUSE_BUTTON_2      1
 2072 #define MOUSE_BUTTON_3      2
 2073 
 2074 #define TIN_EDITOR_FMT_OFF      "%E %F"
 2075 
 2076 #ifdef M_UNIX
 2077 #   define REDIRECT_OUTPUT      "> /dev/null 2>&1"
 2078 #   define REDIRECT_PGP_OUTPUT      "> /dev/null"
 2079 #   define ENV_VAR_MAILER       "MAILER"
 2080 #   define ENV_VAR_SHELL        "SHELL"
 2081 #   define TIN_EDITOR_FMT_ON        "%E +%N %F"
 2082 #   define MAILER_FORMAT        "%M -oi -t < %F"
 2083 #   define TMPDIR   get_val("TMPDIR", _PATH_TMP)
 2084 #   ifdef HAVE_KEY_PREFIX
 2085 #       define KEY_PREFIX       0x8f: case 0x9b
 2086 #   endif /* HAVE_KEY_PREFIX */
 2087 #endif /* M_UNIX */
 2088 
 2089 /* fallback values */
 2090 /* FIXME! */
 2091 #ifndef REDIRECT_OUTPUT
 2092 #   define REDIRECT_OUTPUT      ""
 2093 #endif /* !REDIRECT_OUTPUT */
 2094 #ifndef REDIRECT_PGP_OUTPUT
 2095 #   define REDIRECT_PGP_OUTPUT      ""
 2096 #endif /* !REDIRECT_PGP_OUTPUT */
 2097 #ifndef ENV_VAR_MAILER
 2098 #   define ENV_VAR_MAILER       ""
 2099 #endif /* !ENV_VAR_MAILER */
 2100 #ifndef ENV_VAR_SHELL
 2101 #   define ENV_VAR_SHELL        ""
 2102 #endif /* !ENV_VAR_SHELL */
 2103 #ifndef TIN_EDITOR_FMT_ON
 2104 #   define TIN_EDITOR_FMT_ON        TIN_EDITOR_FMT_OFF
 2105 #endif /* !TIN_EDITOR_FMT_ON */
 2106 #ifndef MAILER_FORMAT
 2107 #   define MAILER_FORMAT        ""
 2108 #endif /* !MAILER_FORMAT */
 2109 #ifndef TMPDIR
 2110 #   define TMPDIR   _PATH_TMP
 2111 #endif /* !TMPDIR */
 2112 
 2113 #if !defined(S_ISDIR)
 2114 #   if defined(M_UNIX)
 2115 #       define S_ISDIR(m)   (((m) & S_IFMT) == S_IFDIR)
 2116 #   endif /* M_UNIX */
 2117 #endif /* !S_ISDIR */
 2118 
 2119 #if !defined(S_ISREG)
 2120 #   define S_ISREG(m)   (((m) & S_IFMT) == S_IFREG)
 2121 #endif /* !S_ISREG */
 2122 
 2123 #ifndef S_IRWXU /* should be defined in <sys/stat.h> */
 2124 #   define S_IRWXU  0000700 /* read, write, execute permission (owner) */
 2125 #   define S_IRUSR  0000400 /* read permission (owner) */
 2126 #   define S_IWUSR  0000200 /* write permission (owner) */
 2127 #   define S_IXUSR  0000100 /* execute permission (owner) */
 2128 
 2129 #   define S_IRWXG  0000070 /* read, write, execute permission (group) */
 2130 #   define S_IRGRP  0000040 /* read permission (group) */
 2131 #   define S_IWGRP  0000020 /* write permission (group) */
 2132 #   define S_IXGRP  0000010 /* execute permission (group) */
 2133 
 2134 #   define S_IRWXO  0000007 /* read, write, execute permission (other) */
 2135 #   define S_IROTH  0000004 /* read permission (other) */
 2136 #   define S_IWOTH  0000002 /* write permission (other) */
 2137 #   define S_IXOTH  0000001 /* execute permission (other) */
 2138 #endif /* !S_IRWXU */
 2139 
 2140 /* the next two are needed for fcc 1.0 on linux */
 2141 #ifndef S_IFMT
 2142 #   define S_IFMT   0xF000  /* type of file */
 2143 #endif /* S_IFMT */
 2144 #ifndef S_IFREG
 2145 #   define S_IFREG  0x8000  /* regular */
 2146 #endif /* S_IFREG */
 2147 
 2148 #ifndef S_IRWXUGO
 2149 #   define S_IRWXUGO    (S_IRWXU|S_IRWXG|S_IRWXO)   /* read, write, execute permission (all) */
 2150 #   define S_IRUGO  (S_IRUSR|S_IRGRP|S_IROTH)   /* read permission (all) */
 2151 #   define S_IWUGO  (S_IWUSR|S_IWGRP|S_IWOTH)   /* write permission (all) */
 2152 #   define S_IXUGO  (S_IXUSR|S_IXGRP|S_IXOTH)   /* execute permission (all) */
 2153 #endif /* !S_IRWXUGO */
 2154 
 2155 #ifndef S_ISVTX
 2156 #   define S_ISVTX 0
 2157 #endif /* !S_ISVTX */
 2158 
 2159 #ifdef DONT_HAVE_PIPING
 2160 #   define TIN_PRINTFILE "tinprint%d.tmp"
 2161 #endif /* DONT_HAVE_PIPING */
 2162 
 2163 /*
 2164  * Defines for access()
 2165  */
 2166 #ifndef R_OK
 2167 #   define R_OK 4   /* Test for Read permission */
 2168 #endif /* !R_OK */
 2169 #ifndef W_OK
 2170 #   define W_OK 2   /* Test for Write permission */
 2171 #endif /* !W_OK */
 2172 #ifndef X_OK
 2173 #   define X_OK 1   /* Test for eXecute permission */
 2174 #endif /* !X_OK */
 2175 #ifndef F_OK
 2176 #   define F_OK 0   /* Test for existence of File */
 2177 #endif /* !F_OK */
 2178 
 2179 /* Various function redefinitions */
 2180 #if defined(USE_DBMALLOC) || defined(USE_DMALLOC)
 2181 #   define my_malloc(size)  malloc(size)
 2182 #   define my_calloc(nmemb, size)   calloc((nmemb), (size))
 2183 #   define my_realloc(ptr, size)    realloc((ptr), (size))
 2184 #else
 2185 #   define my_malloc(size)  my_malloc1(__FILE__, __LINE__, (size))
 2186 #   define my_calloc(nmemb, size)   my_calloc1(__FILE__, __LINE__, (nmemb), (size))
 2187 #   define my_realloc(ptr, size)    my_realloc1(__FILE__, __LINE__, (ptr), (size))
 2188 #endif /* USE_DBMALLOC || USE_DMALLOC */
 2189 
 2190 #define ARRAY_SIZE(array)   ((int) (sizeof(array) / sizeof(array[0])))
 2191 
 2192 #define FreeIfNeeded(p) if (p != NULL) free((void *) p)
 2193 #define FreeAndNull(p)  if (p != NULL) { free((void *) p); p = NULL; }
 2194 
 2195 #define BlankIfNull(p)  ((p) ? (p) : "")
 2196 
 2197 #define my_group_find(x)    add_my_group(x, FALSE, FALSE)
 2198 #define my_group_add(x, y)      add_my_group(x, TRUE, y)
 2199 #define for_each_group(x)   for (x = 0; x < num_active; x++)
 2200 #define for_each_art(x)     for (x = 0; x < top_art; x++)
 2201 #define for_each_art_in_thread(x, y)    for (x = (int) base[y]; x >= 0; x = arts[x].thread)
 2202 
 2203 /*
 2204  * Cast for the (few!) places where we need to examine 8-bit characters w/o
 2205  * sign-extension, and a corresponding test-macro.
 2206  */
 2207 #define EIGHT_BIT(ptr)  (unsigned char *)ptr
 2208 #define is_EIGHT_BIT(p) ((*EIGHT_BIT(p) < 32 && !isspace((int)*p)) || *EIGHT_BIT(p) > 127)
 2209 
 2210 /*
 2211  * function prototypes & extern definitions
 2212  */
 2213 
 2214 #ifndef SIG_ARGS
 2215 #   if defined(__STDC__)
 2216 #       define SIG_ARGS int sig
 2217 #   endif /* __STDC__ */
 2218 #endif /* !SIG_ARGS */
 2219 
 2220 #ifndef __LCLINT__ /* lclint doesn't like it */
 2221 /* stifle complaints about not-a-prototype from gcc */
 2222 #   ifdef DECL_SIG_CONST
 2223 #       undef   SIG_DFL
 2224 #       define SIG_DFL  (void (*)(SIG_ARGS))0
 2225 #       undef   SIG_IGN
 2226 #       define SIG_IGN  (void (*)(SIG_ARGS))1
 2227 #       undef   SIG_ERR
 2228 #       define SIG_ERR  (void (*)(SIG_ARGS))-1
 2229 #   endif /* DECL_SIG_CONST */
 2230 #endif /* !__LCLINT__ */
 2231 
 2232 /*
 2233  * tputs() function-param
 2234  */
 2235 #ifdef OUTC_RETURN
 2236 #   define OUTC_RETTYPE int
 2237 #else
 2238 #   define OUTC_RETTYPE void
 2239 #endif /* OUTC_RETURN */
 2240 
 2241 #ifndef OUTC_ARGS
 2242 #   define OUTC_ARGS    int c
 2243 #endif /* !OUTC_ARGS */
 2244 
 2245 #if __STDC__ || defined(__cplusplus)
 2246 #   define OUTC_FUNCTION(func)  OUTC_RETTYPE func (OUTC_ARGS)
 2247 #else
 2248 #   define OUTC_FUNCTION(func)  OUTC_RETTYPE func (c) int c;
 2249 #endif /* __STDC__ || __cplusplus */
 2250 
 2251 typedef OUTC_RETTYPE (*OutcPtr) (OUTC_ARGS);
 2252 typedef FILE TCP;
 2253 
 2254 #ifndef EXTERN_H
 2255 #   include "extern.h"
 2256 #endif /* !EXTERN_H */
 2257 #ifndef TINRC_H
 2258 #   include "tinrc.h"
 2259 #endif /* !TINRC_H */
 2260 #ifndef NNTPLIB_H
 2261 #   include "nntplib.h"
 2262 #endif /* !NNTPLIB_H */
 2263 
 2264 #ifndef __CPROTO__
 2265 #   ifndef PROTO_H
 2266 #       include "proto.h"
 2267 #   endif /* !PROTO_H */
 2268 #endif /* !__CPROTO__ */
 2269 
 2270 /*
 2271  * rfc1521/rfc1522 interface
 2272  */
 2273 typedef void (*BodyPtr) (char *, FILE *, int);
 2274 
 2275 #ifdef USE_DBMALLOC
 2276 #   undef strchr
 2277 #   undef strrchr
 2278 #   include <dbmalloc.h> /* dbmalloc 1.4 */
 2279 #endif /* USE_DBMALLOC */
 2280 
 2281 #ifdef USE_DMALLOC
 2282 #   include <dmalloc.h>
 2283 #   define DMALLOC_FUNC_CHECK
 2284 #   ifdef HAVE_STRDUP
 2285 #       define my_strdup(s) strdup((s))
 2286 #   endif /* HAVE_STRDUP */
 2287 #endif /* USE_DMALLOC */
 2288 
 2289 #ifdef DOALLOC
 2290     extern char *doalloc(char *, size_t);
 2291     extern char *docalloc(size_t, size_t);
 2292     extern void dofree(char *);
 2293 #   undef malloc
 2294 #   undef realloc
 2295 #   undef calloc
 2296 #   undef free
 2297 #   define malloc(n)    doalloc((char *) 0, n)
 2298 #   define realloc      doalloc
 2299 #   define calloc       docalloc
 2300 #   define free     dofree
 2301     extern void fail_alloc(char *, char *);
 2302     extern void Trace(char *, ...);
 2303     extern void Elapsed(char *);
 2304     extern void WalkBack(void);
 2305     extern void show_alloc(void);
 2306     extern void no_leaks(void);
 2307 #endif /* DOALLOC */
 2308 
 2309 /* define some standard places to look for a tin.defaults file */
 2310 #define TIN_DEFAULTS_BUILTIN "/etc/opt/tin","/etc/tin","/etc","/usr/local/lib/tin","/usr/local/lib","/usr/local/etc/tin","/usr/local/etc","/usr/lib/tin","/usr/lib",NULL
 2311 #ifdef TIN_DEFAULTS_DIR
 2312 #   define TIN_DEFAULTS TIN_DEFAULTS_DIR,TIN_DEFAULTS_BUILTIN
 2313 #else
 2314 #   define TIN_DEFAULTS TIN_DEFAULTS_BUILTIN
 2315 #endif /* TIN_DEFAULTS_DIR */
 2316 
 2317 /*
 2318  * We force this include-ordering since socks.h contains redefinitions of
 2319  * functions that probably are prototyped via other includes. The socks.h
 2320  * definitions have to be included everywhere, since they're making wrappers
 2321  * for the stdio functions as well as the network functions.
 2322  */
 2323 #ifdef USE_SOCKS5
 2324 #   define SOCKS
 2325 #   include <socks.h>
 2326 /* socks.h doesn't define prototypes for use */
 2327 extern size_t read(int, char *, size_t);
 2328 extern int dup(int);
 2329 extern int close(int);
 2330 extern int fprintf(FILE *, const char *, ...);
 2331 extern int fclose(FILE *);
 2332 extern struct tm *localtime(time_t *);
 2333 #endif /* USE_SOCKS5 */
 2334 
 2335 #ifdef SETVBUF_REVERSED
 2336 #   define SETVBUF(stream, buf, mode, size) setvbuf(stream, mode, buf, size)
 2337 #else
 2338 #   define SETVBUF(stream, buf, mode, size) setvbuf(stream, buf, mode, size)
 2339 #endif /* SETVBUF_REVERSED */
 2340 
 2341 #ifdef CLOSEDIR_VOID
 2342 #   define CLOSEDIR(DIR)    closedir(DIR)
 2343 #else
 2344 #   define CLOSEDIR(DIR)    if (closedir(DIR)) error_message(2, "closedir() failed: %s %d", __FILE__, __LINE__)
 2345 #endif /* CLOSEDIR_VOID */
 2346 
 2347 #ifdef HAVE_GETTIMEOFDAY
 2348 #   ifndef GETTIMEOFDAY_2ARGS
 2349 #       define gettimeofday(a,b) gettimeofday(a)
 2350 #   endif /* GETTIMEOFDAY_2ARGS */
 2351 #endif /* HAVE_GETTIMEOFDAY */
 2352 
 2353 /* libmss */
 2354 #ifdef MSS
 2355 #   ifdef strdup
 2356 #       undef strdup
 2357 #   endif /* strdup */
 2358 #   include <mss.h>
 2359 #   undef my_malloc
 2360 #   undef my_realloc
 2361 #   undef my_calloc
 2362 #   define my_malloc(size)  malloc(size)
 2363 #   define my_realloc(ptr, size)    realloc((ptr), (size))
 2364 #   define my_calloc(nmemb, size) calloc((nmemb), (size))
 2365 #endif /* MSS */
 2366 
 2367 /* libcanlock */
 2368 #ifdef USE_CANLOCK
 2369 #   include "../libcanlock/include/canlock.h"
 2370 #endif /* USE_CANLOCK */
 2371 
 2372 /* gsasl */
 2373 #ifdef USE_SASL
 2374 #   include <gsasl.h>
 2375 #endif /* USE_SASL */
 2376 
 2377 /* snprintf(), vsnprintf() */
 2378 #ifndef HAVE_SNPRINTF
 2379 #   define snprintf plp_snprintf
 2380 #endif /* HAVE_SNPRINTF */
 2381 #ifndef HAVE_VSNPRINTF
 2382 #   define vsnprintf    plp_vsnprintf
 2383 #endif /* HAVE_VSNPRINTF */
 2384 
 2385 /*
 2386  * TODO: might need an extra check for gcc-version >= 2.5
 2387  *       __GNUC__ __GNUC_MINOR__
 2388  */
 2389 /* gcc-specific attributes */
 2390 #if defined(__GNUC__) && !defined(__cplusplus) && !defined(__APPLE_CC__) && !defined(__NeXT__)
 2391 #   define UNUSED(x) x __attribute__((unused))
 2392 #else
 2393 #   define UNUSED(x) x
 2394 #endif /* __GNUC__ && !__cplusplus && !__APPLE_CC__ && !__NeXT__ */
 2395 
 2396 /* init_selfinfo() needs MM_CHARSET */
 2397 #ifndef MM_CHARSET
 2398 #   define MM_CHARSET "US-ASCII"
 2399 #endif /* !MM_CHARSET */
 2400 
 2401 
 2402 #if !defined(SEEK_SET)
 2403 #   define SEEK_SET 0L
 2404 #endif /* !SEEK_SET */
 2405 
 2406 #if !defined(EOF)
 2407 #   define EOF -1
 2408 #endif /* !EOF */
 2409 
 2410 /* various filenames used by tin */
 2411 #define TIN_ARTICLE_NAME    ".article"
 2412 #define TIN_CANCEL_NAME ".cancel"
 2413 #define TIN_LETTER_NAME ".letter"
 2414 #define TIN_BUGREPORT_NAME  ".bugreport"
 2415 
 2416 /* read_news_active_file() / open_newsgroups_fp() */
 2417 #ifndef DISABLE_PIPELINING
 2418 #   define PIPELINE_LIMIT 45
 2419 #else
 2420 #   define PIPELINE_LIMIT 1
 2421 #endif /* DISABLE_PIPELINING */
 2422 
 2423 #ifndef DEBUG_H
 2424 #   include "debug.h"
 2425 #endif /* !DEBUG_H */
 2426 
 2427 struct t_overview_fmt {
 2428     char *name;
 2429     enum f_type type;
 2430 };
 2431 
 2432 #endif /* !TIN_H */