"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.7/nail.h" (16 Feb 2018, 102985 Bytes) of package /linux/misc/s-nail-14.9.7.tar.xz:


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 "nail.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.6_vs_14.9.7.

    1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
    2  *@ Header inclusion, macros, constants, types and the global var declarations.
    3  *@ TODO Place in include/, split in object-based subheaders.  And please: sort.
    4  *
    5  * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
    6  * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
    7  */
    8 /*
    9  * Copyright (c) 1980, 1993
   10  *      The Regents of the University of California.  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. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  */
   36 #ifndef n_NAIL_H
   37 # define n_NAIL_H
   38 
   39 /*
   40  * Mail -- a mail program
   41  *
   42  * Author: Kurt Shoens (UCB) March 25, 1978
   43  */
   44 
   45 #include <mk-config.h>
   46 
   47 #include <sys/stat.h>
   48 #include <sys/types.h>
   49 #include <sys/wait.h>
   50 
   51 #ifdef HAVE_GETTIMEOFDAY
   52 # include <sys/time.h>
   53 #endif
   54 
   55 #include <errno.h>
   56 #include <fcntl.h>
   57 #include <inttypes.h>
   58 #include <limits.h>
   59 #include <setjmp.h>
   60 #include <signal.h>
   61 #include <stdarg.h>
   62 #include <stdio.h>
   63 #include <stdlib.h>
   64 #include <string.h>
   65 #include <termios.h>
   66 #include <time.h>
   67 #include <unistd.h>
   68 
   69 #ifdef HAVE_C90AMEND1
   70 # include <wchar.h>
   71 # include <wctype.h>
   72 #endif
   73 #ifdef HAVE_DEBUG
   74 # include <assert.h>
   75 #endif
   76 #ifdef HAVE_ICONV
   77 # include <iconv.h>
   78 #endif
   79 #ifdef HAVE_REGEX
   80 # include <regex.h>
   81 #endif
   82 
   83 #ifdef HAVE_XSSL_MD5
   84 # include <openssl/md5.h>
   85 #endif
   86 
   87 /* Many things possibly of interest for adjustments have been outsourced */
   88 #include <config.h>
   89 
   90 /* Special FD requests for n_child_run(), n_child_start() */
   91 #define n_CHILD_FD_PASS -1
   92 #define n_CHILD_FD_NULL -2
   93 
   94 /* Colour stuff */
   95 #ifdef HAVE_COLOUR
   96 # define n_COLOUR(X) X
   97 #else
   98 # define n_COLOUR(X)
   99 #endif
  100 
  101 /*  */
  102 #define n_FROM_DATEBUF 64        /* Size of RFC 4155 From_ line date */
  103 #define n_DATE_DAYSYEAR 365u
  104 #define n_DATE_NANOSSEC (n_DATE_MICROSSEC * 1000)
  105 #define n_DATE_MICROSSEC (n_DATE_MILLISSEC * 1000)
  106 #define n_DATE_MILLISSEC 1000u
  107 #define n_DATE_SECSMIN 60u
  108 #define n_DATE_MINSHOUR 60u
  109 #define n_DATE_HOURSDAY 24u
  110 #define n_DATE_SECSHOUR (n_DATE_SECSMIN * n_DATE_MINSHOUR)
  111 #define n_DATE_SECSDAY (n_DATE_SECSHOUR * n_DATE_HOURSDAY)
  112 
  113 /* Network protocol newline */
  114 #define NETNL           "\015\012"
  115 #define NETLINE(X)      X NETNL
  116 
  117 /*
  118  * OS, CC support, generic macros etc.
  119  */
  120 
  121 #define n_ISPOW2(X) ((((X) - 1) & (X)) == 0)
  122 #define n_MIN(A,B) ((A) < (B) ? (A) : (B))
  123 #define n_MAX(A,B) ((A) < (B) ? (B) : (A))
  124 #define n_CLIP(X,A,B) (((X) <= (A)) ? (A) : (((X) >= (B)) ? (B) : (X)))
  125 #define n_ABS(A) ((A) < 0 ? -(A) : (A))
  126 
  127 /* OS: we're not a library, only set what needs special treatment somewhere */
  128 #define n_OS_DRAGONFLY 0
  129 #define n_OS_OPENBSD 0
  130 #define n_OS_SOLARIS 0
  131 #define n_OS_SUNOS 0
  132 
  133 #ifdef __DragonFly__
  134 # undef n_OS_DRAGONFLY
  135 # define n_OS_DRAGONFLY 1
  136 #elif defined __OpenBSD__
  137 # undef n_OS_OPENBSD
  138 # define n_OS_OPENBSD 1
  139 #elif defined __solaris__ || defined __sun
  140 # if defined __SVR4 || defined __svr4__
  141 #  undef n_OS_SOLARIS
  142 #  define n_OS_SOLARIS 1
  143 # else
  144 #  undef n_OS_SUNOS
  145 #  define n_OS_SUNOS 1
  146 # endif
  147 #endif
  148 
  149 /* CC */
  150 #define CC_CLANG           0
  151 #define PREREQ_CLANG(X,Y)  0
  152 #define CC_GCC             0
  153 #define PREREQ_GCC(X,Y)    0
  154 #define CC_TCC             0
  155 #define PREREQ_TCC(X,Y)    0
  156 
  157 #ifdef __clang__
  158 # undef CC_CLANG
  159 # undef PREREQ_CLANG
  160 # define CC_CLANG          1
  161 # define PREREQ_CLANG(X,Y) \
  162    (__clang_major__ + 0 > (X) || \
  163     (__clang_major__ + 0 == (X) && __clang_minor__ + 0 >= (Y)))
  164 # define __EXTEN           __extension__
  165 
  166 #elif defined __GNUC__
  167 # undef CC_GCC
  168 # undef PREREQ_GCC
  169 # define CC_GCC            1
  170 # define PREREQ_GCC(X,Y)   \
  171    (__GNUC__ + 0 > (X) || (__GNUC__ + 0 == (X) && __GNUC_MINOR__ + 0 >= (Y)))
  172 # define __EXTEN           __extension__
  173 
  174 #elif defined __TINYC__
  175 # undef CC_TCC
  176 # define CC_TCC            1
  177 #endif
  178 
  179 #ifndef __EXTEN
  180 # define __EXTEN
  181 #endif
  182 
  183 /* Suppress some technical warnings via #pragma's unless developing.
  184  * XXX Wild guesses: clang(1) 1.7 and (OpenBSD) gcc(1) 4.2.1 don't work */
  185 #ifndef HAVE_DEVEL
  186 # if PREREQ_CLANG(3, 4)
  187 #  pragma clang diagnostic ignored "-Wassign-enum"
  188 #  pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
  189 #  pragma clang diagnostic ignored "-Wformat"
  190 #  pragma clang diagnostic ignored "-Wunused-result"
  191 # elif PREREQ_GCC(4, 7)
  192 #  pragma GCC diagnostic ignored "-Wunused-local-typedefs"
  193 #  pragma GCC diagnostic ignored "-Wunused-result"
  194 #  pragma GCC diagnostic ignored "-Wformat"
  195 # endif
  196 #endif
  197 
  198 /* For injection macros like DBG(), n_NATCH_CHAR() */
  199 #define COMMA           ,
  200 
  201 #define EMPTY_FILE()    typedef int n_CONCAT(avoid_empty_file__, n_FILE);
  202 
  203 /* Pointer to size_t */
  204 #define PTR2SIZE(X)     ((size_t)(uintptr_t)(X))
  205 
  206 /* Pointer comparison (types from below) */
  207 #define PTRCMP(A,C,B)   ((uintptr_t)(A) C (uintptr_t)(B))
  208 
  209 /* Ditto, compare (maybe mixed-signed) integers cases to T bits, unsigned;
  210  * Note: doesn't sign-extend correctly, that's still up to the caller */
  211 #define UICMP(T,A,C,B)  ((ui ## T ## _t)(A) C (ui ## T ## _t)(B))
  212 
  213 /* Align something to a size/boundary that cannot cause just any problem */
  214 #define n_ALIGN(X) (((X) + 2*sizeof(void*)) & ~((2*sizeof(void*)) - 1))
  215 #define n_ALIGN_SMALL(X) \
  216    (((X) + n_MAX(sizeof(size_t), sizeof(void*))) &\
  217     ~(n_MAX(sizeof(size_t), sizeof(void*)) - 1))
  218 
  219 /* Members in constant array */
  220 #define n_NELEM(A) (sizeof(A) / sizeof((A)[0]))
  221 
  222 /* sizeof() for member fields */
  223 #define n_SIZEOF_FIELD(T,F) sizeof(((T *)NULL)->F)
  224 
  225 /* Casts-away (*NOT* cast-away) */
  226 #define n_UNUSED(X) ((void)(X))
  227 #define n_UNCONST(P) ((void*)(uintptr_t)(void const*)(P))
  228 #define n_UNVOLATILE(P) ((void*)(uintptr_t)(void volatile*)(P))
  229 /* To avoid warnings with modern compilers for "char*i; *(si32_t*)i=;" */
  230 #define n_UNALIGN(T,P) ((T)(uintptr_t)(P))
  231 #define n_UNXXX(T,C,P) ((T)(uintptr_t)(C)(P))
  232 
  233 /* __STDC_VERSION__ is ISO C99, so also use __STDC__, which should work */
  234 #if defined __STDC__ || defined __STDC_VERSION__ /*|| defined __cplusplus*/
  235 # define n_STRING(X) #X
  236 # define n_XSTRING(X) n_STRING(X)
  237 # define n_CONCAT(S1,S2) n__CONCAT_1(S1, S2)
  238 # define n__CONCAT_1(S1,S2) S1 ## S2
  239 #else
  240 # define n_STRING(X) "X"
  241 # define n_XSTRING STRING
  242 # define n_CONCAT(S1,S2) S1/* won't work out */S2
  243 #endif
  244 
  245 #if defined __STDC_VERSION__ && __STDC_VERSION__ + 0 >= 199901L
  246 # define n_FIELD_INITN(N) n_CONCAT(., N) =
  247 # define n_FIELD_INITI(I) [I] =
  248 #else
  249 # define n_FIELD_INITN(N)
  250 # define n_FIELD_INITI(N)
  251 #endif
  252 
  253 #if defined __STDC_VERSION__ && __STDC_VERSION__ + 0 >= 199901L
  254 # define n_VFIELD_SIZE(X)
  255 # define n_VSTRUCT_SIZEOF(T,F) sizeof(T)
  256 #else
  257 # define n_VFIELD_SIZE(X) \
  258   ((X) == 0 ? sizeof(size_t) \
  259    : ((ssize_t)(X) < 0 ? sizeof(size_t) - n_ABS(X) : (size_t)(X)))
  260 # define n_VSTRUCT_SIZEOF(T,F) (sizeof(T) - n_SIZEOF_FIELD(T, F))
  261 #endif
  262 
  263 #ifndef HAVE_INLINE
  264 # define n_INLINE static
  265 #endif
  266 
  267 #undef __FUN__
  268 #if defined __STDC_VERSION__ && __STDC_VERSION__ + 0 >= 199901L
  269 # define __FUN__        __func__
  270 #elif CC_CLANG || PREREQ_GCC(3, 4)
  271 # define __FUN__        __extension__ __FUNCTION__
  272 #else
  273 # define __FUN__        n_empty /* Something that is not a literal */
  274 #endif
  275 
  276 #if defined __predict_true && defined __predict_false
  277 # define n_LIKELY(X) __predict_true(X)
  278 # define n_UNLIKELY(X) __predict_false(X)
  279 #elif CC_CLANG || PREREQ_GCC(2, 96)
  280 # define n_LIKELY(X) __builtin_expect(X, 1)
  281 # define n_UNLIKELY(X) __builtin_expect(X, 0)
  282 #else
  283 # define n_LIKELY(X) (X)
  284 # define n_UNLIKELY(X) (X)
  285 #endif
  286 
  287 #undef HAVE_NATCH_CHAR
  288 #if defined HAVE_SETLOCALE && defined HAVE_C90AMEND1 && defined HAVE_WCWIDTH
  289 # define HAVE_NATCH_CHAR
  290 # define n_NATCH_CHAR(X) X
  291 #else
  292 # define n_NATCH_CHAR(X)
  293 #endif
  294 
  295 /* Compile-Time-Assert
  296  * Problem is that some compilers warn on unused local typedefs, so add
  297  * a special local CTA to overcome this */
  298 #if defined __STDC_VERSION__ && __STDC_VERSION__ + 0 >= 201112L
  299 # define n_CTA(T,M) _Static_assert(T, M)
  300 # define n_LCTA(T,M) _Static_assert(T, M)
  301 #else
  302 # define n_CTA(T,M)  n__CTA_1(T, n_FILE, __LINE__)
  303 # define n_LCTA(T,M) n__LCTA_1(T, n_FILE, __LINE__)
  304 #endif
  305 #define n_CTAV(T) n_CTA(T, "Unexpected value of constant")
  306 #define n_LCTAV(T) n_LCTA(T, "Unexpected value of constant")
  307 
  308 #ifdef n_MAIN_SOURCE
  309 # define n_MCTA(T,M) n_CTA(T, M);
  310 #else
  311 # define n_MCTA(T,M)
  312 #endif
  313 
  314 #define n__CTA_1(T,F,L)   n__CTA_2(T, F, L)
  315 #define n__CTA_2(T,F,L) \
  316    typedef char ASSERTION_failed_in_file_## F ## _at_line_ ## L[(T) ? 1 : -1]
  317 #define n__LCTA_1(T,F,L)  n__LCTA_2(T, F, L)
  318 #define n__LCTA_2(T,F,L) \
  319 do{\
  320    typedef char ASSERTION_failed_in_file_## F ## _at_line_ ## L[(T) ? 1 : -1];\
  321    ASSERTION_failed_in_file_## F ## _at_line_ ## L __i_am_unused__;\
  322    n_UNUSED(__i_am_unused__);\
  323 }while(0)
  324 
  325 #define n_UNINIT(N,V)     N = V
  326 
  327 /* Create a bit mask for the bit range LO..HI -- HI can't use highest bit! */
  328 #define n_BITENUM_MASK(LO,HI) (((1u << ((HI) + 1)) - 1) & ~((1u << (LO)) - 1))
  329 
  330 #undef DBG
  331 #undef NDBG
  332 #ifndef HAVE_DEBUG
  333 # undef assert
  334 # define assert(X)      n_UNUSED(0)
  335 # define DBG(X)
  336 # define NDBG(X)        X
  337 # define DBGOR(X,Y)     Y
  338 #else
  339 # define DBG(X)         X
  340 # define NDBG(X)
  341 # define DBGOR(X,Y)     X
  342 #endif
  343 
  344 /* Translation (init in main.c): may NOT set errno! */
  345 #undef _
  346 #undef N_
  347 #undef V_
  348 #define _(S)            S
  349 #define N_(S)           S
  350 #define V_(S)           S
  351 
  352 /*
  353  * Types TODO v15: n_XX_t
  354  */
  355 
  356 #ifdef UINT8_MAX
  357 # define UI8_MAX        UINT8_MAX
  358 # define SI8_MIN        INT8_MIN
  359 # define SI8_MAX        INT8_MAX
  360 typedef uint8_t         ui8_t;
  361 typedef int8_t          si8_t;
  362 #elif UCHAR_MAX != 255
  363 # error UCHAR_MAX must be 255
  364 #else
  365 # define UI8_MAX        UCHAR_MAX
  366 # define SI8_MIN        CHAR_MIN
  367 # define SI8_MAX        CHAR_MAX
  368 typedef unsigned char   ui8_t;
  369 typedef signed char     si8_t;
  370 #endif
  371 
  372 #if !defined PRIu8 || !defined PRId8
  373 # undef PRIu8
  374 # undef PRId8
  375 # define PRIu8          "hhu"
  376 # define PRId8          "hhd"
  377 #endif
  378 
  379 #ifdef UINT16_MAX
  380 # define UI16_MAX       UINT16_MAX
  381 # define SI16_MIN       INT16_MIN
  382 # define SI16_MAX       INT16_MAX
  383 typedef uint16_t        ui16_t;
  384 typedef int16_t         si16_t;
  385 #elif USHRT_MAX != 0xFFFFu
  386 # error USHRT_MAX must be 0xFFFF
  387 #else
  388 # define UI16_MAX       USHRT_MAX
  389 # define SI16_MIN       SHRT_MIN
  390 # define SI16_MAX       SHRT_MAX
  391 typedef unsigned short  ui16_t;
  392 typedef signed short    si16_t;
  393 #endif
  394 
  395 #if !defined PRIu16 || !defined PRId16
  396 # undef PRIu16
  397 # undef PRId16
  398 # if UI16_MAX == UINT_MAX
  399 #  define PRIu16        "u"
  400 #  define PRId16        "d"
  401 # else
  402 #  define PRIu16        "hu"
  403 #  define PRId16        "hd"
  404 # endif
  405 #endif
  406 
  407 #ifdef UINT32_MAX
  408 # define UI32_MAX       UINT32_MAX
  409 # define SI32_MIN       INT32_MIN
  410 # define SI32_MAX       INT32_MAX
  411 typedef uint32_t        ui32_t;
  412 typedef int32_t         si32_t;
  413 #elif ULONG_MAX == 0xFFFFFFFFu
  414 # define UI32_MAX       ULONG_MAX
  415 # define SI32_MIN       LONG_MIN
  416 # define SI32_MAX       LONG_MAX
  417 typedef unsigned long int  ui32_t;
  418 typedef signed long int    si32_t;
  419 #elif UINT_MAX != 0xFFFFFFFFu
  420 # error UINT_MAX must be 0xFFFFFFFF
  421 #else
  422 # define UI32_MAX       UINT_MAX
  423 # define SI32_MIN       INT_MIN
  424 # define SI32_MAX       INT_MAX
  425 typedef unsigned int    ui32_t;
  426 typedef signed int      si32_t;
  427 #endif
  428 
  429 #if !defined PRIu32 || !defined PRId32
  430 # undef PRIu32
  431 # undef PRId32
  432 # if UI32_MAX == ULONG_MAX
  433 #  define PRIu32        "lu"
  434 #  define PRId32        "ld"
  435 # else
  436 #  define PRIu32        "u"
  437 #  define PRId32        "d"
  438 # endif
  439 #endif
  440 
  441 #ifdef UINT64_MAX
  442 # define UI64_MAX       UINT64_MAX
  443 # define SI64_MIN       INT64_MIN
  444 # define SI64_MAX       INT64_MAX
  445 typedef uint64_t        ui64_t;
  446 typedef int64_t         si64_t;
  447 #elif ULONG_MAX <= 0xFFFFFFFFu
  448 # if !defined ULLONG_MAX || (ULLONG_MAX >> 31) < 0xFFFFFFFFu
  449 #  error We need a 64 bit integer
  450 # else
  451 #  define UI64_MAX      ULLONG_MAX
  452 #  define SI64_MIN      LLONG_MIN
  453 #  define SI64_MAX      LLONG_MAX
  454 __EXTEN typedef unsigned long long  ui64_t;
  455 __EXTEN typedef signed long long    si64_t;
  456 # endif
  457 #else
  458 # define UI64_MAX       ULONG_MAX
  459 # define SI64_MIN       LONG_MIN
  460 # define SI64_MAX       LONG_MAX
  461 typedef unsigned long   ui64_t;
  462 typedef signed long     si64_t;
  463 #endif
  464 
  465 /* PRIo64 for `vexpr' */
  466 #if !defined PRIu64 || !defined PRId64 || !defined PRIX64 || !defined PRIo64
  467 # undef PRIu64
  468 # undef PRId64
  469 # undef PRIX64
  470 # undef PRIo64
  471 # if defined ULLONG_MAX && UI64_MAX == ULLONG_MAX
  472 #  define PRIu64        "llu"
  473 #  define PRId64        "lld"
  474 #  define PRIX64        "llX"
  475 #  define PRIo64        "llo"
  476 # else
  477 #  define PRIu64        "lu"
  478 #  define PRId64        "ld"
  479 #  define PRIX64        "lX"
  480 #  define PRIo64        "lo"
  481 # endif
  482 #endif
  483 
  484 /* (So that we can use UICMP() for size_t comparison, too) */
  485 typedef size_t          uiz_t;
  486 typedef ssize_t         siz_t;
  487 
  488 #undef PRIuZ
  489 #undef PRIdZ
  490 #if defined __STDC_VERSION__ && __STDC_VERSION__ + 0 >= 199901L
  491 # define PRIuZ          "zu"
  492 # define PRIdZ          "zd"
  493 # define UIZ_MAX        SIZE_MAX
  494 #elif defined SIZE_MAX
  495   /* UnixWare has size_t as unsigned as required but uses a signed limit
  496    * constant (which is thus false!) */
  497 # if SIZE_MAX == UI64_MAX || SIZE_MAX == SI64_MAX
  498 #  define PRIuZ         PRIu64
  499 #  define PRIdZ         PRId64
  500 n_MCTA(sizeof(size_t) == sizeof(ui64_t),
  501    "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
  502 # elif SIZE_MAX == UI32_MAX || SIZE_MAX == SI32_MAX
  503 #  define PRIuZ         PRIu32
  504 #  define PRIdZ         PRId32
  505 n_MCTA(sizeof(size_t) == sizeof(ui32_t),
  506    "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
  507 # else
  508 #  error SIZE_MAX is neither UI64_MAX nor UI32_MAX (please report this)
  509 # endif
  510 # define UIZ_MAX        SIZE_MAX
  511 #endif
  512 #ifndef PRIuZ
  513 # define PRIuZ          "lu"
  514 # define PRIdZ          "ld"
  515 n_MCTA(sizeof(size_t) == sizeof(unsigned long),
  516    "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
  517 # define UIZ_MAX        ULONG_MAX
  518 #endif
  519 
  520 #ifndef UINTPTR_MAX
  521 # ifdef SIZE_MAX
  522 #  define uintptr_t     size_t
  523 # else
  524 #  define uintptr_t     unsigned long
  525 # endif
  526 #endif
  527 
  528 #ifdef HAVE_C90AMEND1
  529 typedef wchar_t         wc_t;
  530 # define n_WC_C(X)      L ## X
  531 #else
  532 typedef char            wc_t; /* Yep: really 8-bit char */
  533 # define n_WC_C(X)      X
  534 #endif
  535 
  536 enum {FAL0, TRU1, TRUM1 = -1};
  537 typedef si8_t           bool_t;
  538 
  539 /* Add shorter aliases for "normal" integers TODO v15 -> n_XX_t */
  540 typedef unsigned long   ul_i;
  541 typedef unsigned int    ui_i;
  542 typedef unsigned short  us_i;
  543 typedef unsigned char   uc_i;
  544 
  545 typedef signed long     sl_i;
  546 typedef signed int      si_i;
  547 typedef signed short    ss_i;
  548 typedef signed char     sc_i;
  549 
  550 typedef void (          *sighandler_type)(int); /* TODO v15 obsolete */
  551 typedef void (          *n_sighdl_t)(int);
  552 
  553 enum n_announce_flags{
  554    n_ANNOUNCE_NONE = 0,          /* Only housekeeping */
  555    n_ANNOUNCE_MAIN_CALL = 1u<<0, /* POSIX covered startup call */
  556    n_ANNOUNCE_STATUS = 1u<<1,    /* Only print status */
  557    n_ANNOUNCE_CHANGE = 1u<<2,    /* Folder changed */
  558 
  559    n__ANNOUNCE_HEADER = 1u<<6,
  560    n__ANNOUNCE_ANY = 1u<<7
  561 };
  562 
  563 enum authtype {
  564    AUTHTYPE_NONE     = 1<<0,
  565    AUTHTYPE_PLAIN    = 1<<1,  /* POP3: APOP is covered by this */
  566    AUTHTYPE_LOGIN    = 1<<2,
  567    AUTHTYPE_CRAM_MD5 = 1<<3,
  568    AUTHTYPE_GSSAPI   = 1<<4
  569 };
  570 
  571 enum expand_addr_flags {
  572    EAF_NONE       = 0,        /* -> EAF_NOFILE | EAF_NOPIPE */
  573    EAF_RESTRICT   = 1<<0,     /* "restrict" (do unless interaktive / -[~#]) */
  574    EAF_FAIL       = 1<<1,     /* "fail" */
  575    EAF_FAILINVADDR = 1<<2,    /* "failinvaddr" */
  576    /* TODO HACK!  In pre-v15 we have a control flow problem (it is a general
  577     * TODO design problem): if collect() calls makeheader(), e.g., for -t or
  578     * TODO because of ~e diting, then that will checkaddr() and that will
  579     * TODO remove invalid headers.  However, this code path does not know
  580     * TODO about keeping track of senderrors unless a pointer has been passed,
  581     * TODO but which it doesn't for ~e, and shall not, too.  Thus, invalid
  582     * TODO addresses may be automatically removed, silently, and noone will
  583     * TODO ever know, in particular not regarding "failinvaddr".
  584     * TODO The hacky solution is this bit -- which can ONLY be used for fields
  585     * TODO which will be subject to namelist_vaporise_head() later on!! --,
  586     * TODO if it is set (by extract_header()) then checkaddr() will NOT strip
  587     * TODO invalid headers off IF it deals with a NULL senderror pointer */
  588    EAF_MAYKEEP    = 1<<3,
  589    /* Bits reused by enum expand_addr_check_mode! */
  590    EAF_FILE       = 1<<4,     /* +"file" targets */
  591    EAF_PIPE       = 1<<5,     /* +"pipe" command pipe targets */
  592    EAF_NAME       = 1<<6,     /* +"name"s (non-address) names / MTA aliases */
  593    EAF_ADDR       = 1<<7,     /* +"addr" network address (contain "@") */
  594 
  595    EAF_TARGET_MASK  = EAF_FILE | EAF_PIPE | EAF_NAME | EAF_ADDR,
  596    EAF_RESTRICT_TARGETS = EAF_NAME | EAF_ADDR /* (default set if not set) */
  597 };
  598 
  599 enum expand_addr_check_mode {
  600    EACM_NONE      = 0,        /* Don't care about *expandaddr* */
  601    EACM_NORMAL    = 1<<0,     /* Use our normal *expandaddr* checking */
  602    EACM_STRICT    = 1<<1,     /* Never allow any file or pipe addresse */
  603    EACM_MODE_MASK = 0x3,      /* _NORMAL and _STRICT are mutual! */
  604 
  605    EACM_NOLOG     = 1<<2,     /* Don't log check errors */
  606 
  607    /* Some special overwrites of EAF_TARGETs.
  608     * May NOT clash with EAF_* bits which may be ORd to these here! */
  609 
  610    EACM_NONAME    = 1<<16
  611 };
  612 
  613 enum n_cmd_arg_flags{ /* TODO Most of these need to change, in fact in v15
  614    * TODO i rather see the mechanism that is used in c_bind() extended and used
  615    * TODO anywhere, i.e. n_cmd_arg_parse().
  616    * TODO Note that we may NOT support arguments with strlen()>=UI32_MAX (?) */
  617    n_CMD_ARG_TYPE_MSGLIST = 0,   /* Message list type */
  618    n_CMD_ARG_TYPE_NDMLIST = 1,   /* Message list, no defaults */
  619    n_CMD_ARG_TYPE_RAWDAT = 2,    /* The plain string in an argv[] */
  620      n_CMD_ARG_TYPE_STRING = 3,  /* A pure string TODO obsolete */
  621    n_CMD_ARG_TYPE_WYSH = 4,      /* getrawlist(), sh(1) compatible */
  622       n_CMD_ARG_TYPE_RAWLIST = 5, /* getrawlist(), old style TODO obsolete */
  623      n_CMD_ARG_TYPE_WYRA = 6,    /* _RAWLIST or _WYSH (with `wysh') TODO obs. */
  624    n_CMD_ARG_TYPE_ARG = 7,       /* n_cmd_arg_desc/n_cmd_arg() new-style */
  625    n_CMD_ARG_TYPE_MASK = 7,      /* Mask of the above */
  626 
  627    n_CMD_ARG_A = 1u<<4,    /* Needs an active mailbox */
  628    n_CMD_ARG_F = 1u<<5,    /* Is a conditional command */
  629    n_CMD_ARG_G = 1u<<6,    /* Is supposed to produce "gabby" history */
  630    n_CMD_ARG_H = 1u<<7,    /* Never place in `history' */
  631    n_CMD_ARG_I = 1u<<8,    /* Interactive command bit */
  632    n_CMD_ARG_L = 1u<<9,    /* Supports `local' prefix (only WYSH/WYRA) */
  633    n_CMD_ARG_M = 1u<<10,   /* Legal from send mode bit */
  634    n_CMD_ARG_O = 1u<<11,   /* n_OBSOLETE()d command */
  635    n_CMD_ARG_P = 1u<<12,   /* Autoprint dot after command */
  636    n_CMD_ARG_R = 1u<<13,   /* Forbidden in compose mode recursion */
  637    n_CMD_ARG_SC = 1u<<14,  /* Forbidden pre-n_PSO_STARTED_CONFIG */
  638    n_CMD_ARG_S = 1u<<15,   /* Forbidden pre-n_PSO_STARTED (POSIX) */
  639    n_CMD_ARG_T = 1u<<16,   /* Is a transparent command */
  640    n_CMD_ARG_V = 1u<<17,   /* Supports `vput' prefix (only WYSH/WYRA) */
  641    n_CMD_ARG_W = 1u<<18,   /* Invalid when read only bit */
  642    n_CMD_ARG_X = 1u<<19,   /* Valid command in n_PS_COMPOSE_FORKHOOK mode */
  643    /* XXX Note that CMD_ARG_EM implies a _real_ return value for $! */
  644    n_CMD_ARG_EM = 1u<<30   /* If error: n_pstate_err_no (4 $! aka. ok_v___em) */
  645 };
  646 
  647 enum n_cmd_arg_desc_flags{/* TODO incomplete, misses getmsglist() */
  648    /* - A type */
  649    n_CMD_ARG_DESC_STRING = 1u<<0,   /* A !blankspacechar() string */
  650    n_CMD_ARG_DESC_WYSH = 1u<<1,     /* sh(1)ell-style quoted */
  651 
  652    n__CMD_ARG_DESC_TYPE_MASK = n_CMD_ARG_DESC_STRING | n_CMD_ARG_DESC_WYSH,
  653 
  654    /* - Optional flags */
  655    /* It is not an error if an optional argument is missing; once an argument
  656     * has been declared optional only optional arguments may follow */
  657    n_CMD_ARG_DESC_OPTION = 1u<<16,
  658    /* GREEDY: parse as many of that type as possible; must be last entry */
  659    n_CMD_ARG_DESC_GREEDY = 1u<<17,
  660    /* If greedy, join all given arguments separated by ASCII SP right away */
  661    n_CMD_ARG_DESC_GREEDY_JOIN = 1u<<18,
  662    /* Honour an overall "stop" request in one of the arguments (\c@ or #) */
  663    n_CMD_ARG_DESC_HONOUR_STOP = 1u<<19,
  664 
  665    n__CMD_ARG_DESC_FLAG_MASK = n_CMD_ARG_DESC_OPTION | n_CMD_ARG_DESC_GREEDY |
  666          n_CMD_ARG_DESC_GREEDY_JOIN | n_CMD_ARG_DESC_HONOUR_STOP
  667 };
  668 
  669 #ifdef HAVE_COLOUR
  670 /* We do have several contexts of colour IDs; since only one of them can be
  671  * active at any given time let's share the value range */
  672 enum n_colour_ctx{
  673    n_COLOUR_CTX_SUM,
  674    n_COLOUR_CTX_VIEW,
  675    n_COLOUR_CTX_MLE,
  676    n__COLOUR_CTX_MAX1
  677 };
  678 
  679 enum n_colour_id{
  680    /* Header summary */
  681    n_COLOUR_ID_SUM_DOTMARK = 0,
  682    n_COLOUR_ID_SUM_HEADER,
  683    n_COLOUR_ID_SUM_THREAD,
  684 
  685    /* Message display */
  686    n_COLOUR_ID_VIEW_FROM_ = 0,
  687    n_COLOUR_ID_VIEW_HEADER,
  688    n_COLOUR_ID_VIEW_MSGINFO,
  689    n_COLOUR_ID_VIEW_PARTINFO,
  690 
  691    /* Mailx-Line-Editor */
  692    n_COLOUR_ID_MLE_POSITION = 0,
  693    n_COLOUR_ID_MLE_PROMPT,
  694 
  695    n__COLOUR_IDS = n_COLOUR_ID_VIEW_PARTINFO + 1
  696 };
  697 
  698 /* Colour preconditions, let's call them tags, cannot be an enum because for
  699  * message display they are the actual header name of the current header.  Thus
  700  * let's use constants of pseudo pointers */
  701 # define n_COLOUR_TAG_SUM_DOT ((char*)-2)
  702 # define n_COLOUR_TAG_SUM_OLDER ((char*)-3)
  703 #endif /* HAVE_COLOUR */
  704 
  705 enum conversion {
  706    CONV_NONE,        /* no conversion */
  707    CONV_7BIT,        /* no conversion, is 7bit */
  708    CONV_FROMQP,      /* convert from quoted-printable */
  709    CONV_TOQP,        /* convert to quoted-printable */
  710    CONV_8BIT,        /* convert to 8bit (iconv) */
  711    CONV_FROMB64,     /* convert from base64 */
  712    CONV_FROMB64_T,   /* convert from base64/text */
  713    CONV_TOB64,       /* convert to base64 */
  714    CONV_FROMHDR,     /* convert from RFC1522 format */
  715    CONV_TOHDR,       /* convert to RFC1522 format */
  716    CONV_TOHDR_A      /* convert addresses for header */
  717 };
  718 
  719 enum cproto {
  720    CPROTO_CCRED,     /* Special dummy credential proto (S/MIME etc.) */
  721    CPROTO_SOCKS,     /* Special dummy SOCKS5 proxy proto */
  722    CPROTO_SMTP,
  723    CPROTO_POP3
  724 ,CPROTO_IMAP
  725 };
  726 
  727 enum n_dotlock_state{
  728    n_DLS_NONE,
  729    n_DLS_CANT_CHDIR,    /* Failed to chdir(2) into desired path */
  730    n_DLS_NAMETOOLONG,   /* Lock file name would be too long */
  731    n_DLS_ROFS,          /* Read-only filesystem (no error, mailbox RO) */
  732    n_DLS_NOPERM,        /* No permission to creat lock file */
  733    n_DLS_NOEXEC,        /* Privilege separated dotlocker not found */
  734    n_DLS_PRIVFAILED,    /* Rising privileges failed in dotlocker */
  735    n_DLS_EXIST,         /* Lock file already exists, stale lock? */
  736    n_DLS_FISHY,         /* Something makes us think bad of situation */
  737    n_DLS_DUNNO,         /* Catch-all error */
  738    n_DLS_PING,          /* Not an error, but have to wait for lock */
  739    n_DLS_ABANDON = 1<<7 /* ORd to any but _NONE: give up, don't retry */
  740 };
  741 
  742 /* enum n_err_number from mk-config.h, which is in sync with
  743  * n_err_to_doc(), n_err_to_name() and n_err_from_name() */
  744 
  745 enum n_exit_status{
  746    n_EXIT_OK = EXIT_SUCCESS,
  747    n_EXIT_ERR = EXIT_FAILURE,
  748    n_EXIT_USE = 64,           /* sysexits.h:EX_USAGE */
  749    n_EXIT_NOUSER = 67,        /* :EX_NOUSER */
  750    n_EXIT_COLL_ABORT = 1<<1,  /* Message collection was aborted */
  751    n_EXIT_SEND_ERROR = 1<<2   /* Unspecified send error occurred */
  752 };
  753 
  754 enum fedit_mode {
  755    FEDIT_NONE     = 0,
  756    FEDIT_SYSBOX   = 1<<0,     /* %: prefix */
  757    FEDIT_RDONLY   = 1<<1,     /* Readonly (per-box, n_OPT_R_FLAG is global) */
  758    FEDIT_NEWMAIL  = 1<<2      /* `newmail' operation TODO OBSOLETE THIS! */
  759 };
  760 
  761 enum fexp_mode {
  762    FEXP_FULL,                 /* Full expansion */
  763    FEXP_NOPROTO = 1<<0,       /* TODO no which_protocol() to decide expansion */
  764    FEXP_SILENT = 1<<1,        /* Don't print but only return errors */
  765    FEXP_MULTIOK = 1<<2,       /* Expansion to many entries is ok */
  766    FEXP_LOCAL = 1<<3,         /* Result must be local file/maildir */
  767    FEXP_NSHORTCUT = 1<<4,     /* Don't expand shortcuts */
  768    FEXP_NSPECIAL = 1<<5,      /* No %,#,& specials */
  769    FEXP_NFOLDER = 1<<6,       /* NSPECIAL and no + folder, too */
  770    FEXP_NSHELL = 1<<7,        /* Don't do shell word exp. (but ~/, $VAR) */
  771    FEXP_NVAR = 1<<8           /* ..not even $VAR expansion */
  772 };
  773 
  774 enum n_file_lock_type{
  775    FLT_READ,
  776    FLT_WRITE
  777 };
  778 
  779 enum n_fopen_state{ /* TODO add n_fopen_mode, too */
  780    /* First n__PROTO_SHIFT bits are enum protocol!  n_MCTA()d below */
  781    n_FOPEN_STATE_NONE = 0,
  782    n_FOPEN_STATE_EXISTS = 1u<<5
  783 };
  784 
  785 enum n_go_input_flags{
  786    n_GO_INPUT_NONE,
  787    n_GO_INPUT_CTX_BASE = 0,            /* Generic shared base: don't use! */
  788    n_GO_INPUT_CTX_DEFAULT = 1,         /* Default input */
  789    n_GO_INPUT_CTX_COMPOSE = 2,         /* Compose mode input */
  790    n__GO_INPUT_CTX_MASK = 3,
  791    n__GO_INPUT_CTX_MAX1 = n_GO_INPUT_CTX_COMPOSE + 1,
  792 
  793    n_GO_INPUT_HOLDALLSIGS = 1u<<8,     /* hold_all_sigs() active TODO */
  794    /* `xcall' is `call' (at the level where this is set): to be set when
  795     * teardown of top level has undesired effects, e.g., for `account's and
  796     * folder hooks etc., where we do not to loose our `localopts' unroll list */
  797    n_GO_INPUT_NO_XCALL = 1u<<9,
  798 
  799    n_GO_INPUT_FORCE_STDIN = 1u<<10,    /* Even in macro, use stdin (`read')! */
  800    n_GO_INPUT_NL_ESC = 1u<<11,         /* Support "\\$" line continuation */
  801    n_GO_INPUT_NL_FOLLOW = 1u<<12,      /* ..on such a follow line */
  802    n_GO_INPUT_PROMPT_NONE = 1u<<13,    /* Don't print prompt */
  803    n_GO_INPUT_PROMPT_EVAL = 1u<<14,    /* Instead, evaluate *prompt* */
  804 
  805    n_GO_INPUT_HIST_ADD = 1u<<16,       /* Add the result to history list */
  806    n_GO_INPUT_HIST_GABBY = 1u<<17,     /* Consider history entry as gabby */
  807 
  808    n__GO_FREEBIT = 24
  809 };
  810 
  811 enum n_go_input_inject_flags{
  812    n_GO_INPUT_INJECT_NONE = 0,
  813    n_GO_INPUT_INJECT_COMMIT = 1u<<0,   /* Auto-commit input */
  814    n_GO_INPUT_INJECT_HISTORY = 1u<<1   /* Allow history addition */
  815 };
  816 
  817 enum n_iconv_flags{
  818    n_ICONV_NONE = 0,
  819    n_ICONV_IGN_ILSEQ = 1<<0,     /* Ignore EILSEQ in input (replacement char) */
  820    n_ICONV_IGN_NOREVERSE = 1<<1, /* .. non-reversible conversions in output */
  821    n_ICONV_UNIREPL = 1<<2,       /* Use Unicode replacement 0xFFFD = EF BF BD */
  822    n_ICONV_DEFAULT = n_ICONV_IGN_ILSEQ | n_ICONV_IGN_NOREVERSE,
  823    n_ICONV_UNIDEFAULT = n_ICONV_DEFAULT | n_ICONV_UNIREPL
  824 };
  825 
  826 /* Special ignore (where _TYPE is covered by POSIX `ignore' / `retain').
  827  * _ALL is very special in that it doesn't have a backing object.
  828  * Go over enum to avoid cascads of (different) CC warnings for used CTA()s */
  829 #define n_IGNORE_ALL ((struct n_ignore*)n__IGNORE_ALL)
  830 #define n_IGNORE_TYPE ((struct n_ignore*)n__IGNORE_TYPE)
  831 #define n_IGNORE_SAVE ((struct n_ignore*)n__IGNORE_SAVE)
  832 #define n_IGNORE_FWD ((struct n_ignore*)n__IGNORE_FWD)
  833 #define n_IGNORE_TOP ((struct n_ignore*)n__IGNORE_TOP)
  834 
  835 enum{
  836    n__IGNORE_ALL = -2,
  837    n__IGNORE_TYPE = -3,
  838    n__IGNORE_SAVE = -4,
  839    n__IGNORE_FWD = -5,
  840    n__IGNORE_TOP = -6,
  841    n__IGNORE_ADJUST = 3,
  842    n__IGNORE_MAX = 6 - n__IGNORE_ADJUST
  843 };
  844 
  845 enum n_idec_mode{
  846    n_IDEC_MODE_NONE,
  847    n_IDEC_MODE_SIGNED_TYPE = 1u<<0, /* To choose limits, error constants etc. */
  848    /* If a power-of-two is used explicitly, or if base 0 is used and a known
  849     * standard prefix is seen, enforce interpretation as unsigned.  This only
  850     * makes a difference in conjunction with n_IDEC_MODE_SIGNED_TYPE */
  851    n_IDEC_MODE_POW2BASE_UNSIGNED = 1u<<1,
  852 #if 0
  853    n_IDEC_MODE_SIGN_FORCE_SIGNED_TYPE = 1u<<2,
  854 #endif
  855    n_IDEC_MODE_LIMIT_8BIT = 1u<<3,  /* Saturate if result exceeds 8-bit */
  856    n_IDEC_MODE_LIMIT_16BIT = 2u<<3,
  857    n_IDEC_MODE_LIMIT_32BIT = 3u<<3,
  858    n__IDEC_MODE_LIMIT_MASK = 3u<<3,
  859    n_IDEC_MODE_LIMIT_NOERROR = 1u<<5, /* Not an error if limit is excessed! */
  860    /* These bits are duplicated in the _state result bits! */
  861    n__IDEC_MODE_MASK = (1u<<6) - 1
  862 };
  863 
  864 enum n_idec_state{
  865    n_IDEC_STATE_NONE,
  866    /* Malformed input, no usable result has been stored */
  867    n_IDEC_STATE_EINVAL = 1u<<8,
  868    /* Bad character according to base, but we have seen some good before,
  869     * otherwise _EINVAL would have been used */
  870    n_IDEC_STATE_EBASE = 2u<<8,
  871    n_IDEC_STATE_EOVERFLOW = 3u<<8,  /* Result too large */
  872    n_IDEC_STATE_EMASK = 3u<<8,      /* Any errors, that is */
  873    n_IDEC_STATE_SEEN_MINUS = 1u<<16, /* Seen - in input? */
  874    n_IDEC_STATE_CONSUMED = 1u<<17,  /* All the input buffer was consumed */
  875    n__IDEC_PRIVATE_SHIFT1 = 24u
  876 };
  877 n_MCTA(n__IDEC_MODE_MASK <= (1u<<8) - 1, "Shared bit range overlaps")
  878 
  879 /* Buffer size needed by n_ienc_buf() including NUL and base prefixes */
  880 #define n_IENC_BUFFER_SIZE 80
  881 
  882 enum n_ienc_mode{
  883    n_IENC_MODE_NONE,
  884    n_IENC_MODE_SIGNED_TYPE = 1u<<1, /* Signedness correction etc. necessary */
  885    n_IENC_MODE_SIGNED_PLUS = 1u<<2, /* Positive nubers shall have + prefix */
  886    n_IENC_MODE_SIGNED_SPACE = 1u<<3, /* Ditto, ASCII SPACE (lesser priority) */
  887    n_IENC_MODE_NO_PREFIX = 1u<<4,   /* No base prefixes shall be written */
  888    n_IENC_MODE_LOWERCASE = 1u<<5,   /* Use lowercase letters (not prefix) */
  889    n__IENC_MODE_SHIFT = 6u,
  890    n__IENC_MODE_MASK = (1u<<n__IENC_MODE_SHIFT) - 1
  891 };
  892 
  893 enum mimecontent {
  894    MIME_UNKNOWN,     /* unknown content */
  895    MIME_SUBHDR,      /* inside a multipart subheader */
  896    MIME_822,         /* message/rfc822 content */
  897    MIME_MESSAGE,     /* other message/ content */
  898    MIME_TEXT_PLAIN,  /* text/plain content */
  899    MIME_TEXT_HTML,   /* text/html content */
  900    MIME_TEXT,        /* other text/ content */
  901    MIME_ALTERNATIVE, /* multipart/alternative content */
  902    MIME_RELATED,     /* mime/related (RFC 2387) */
  903    MIME_DIGEST,      /* multipart/digest content */
  904    MIME_SIGNED,      /* multipart/signed */
  905    MIME_ENCRYPTED,   /* multipart/encrypted */
  906    MIME_MULTI,       /* other multipart/ content */
  907    MIME_PKCS7,       /* PKCS7 content */
  908    MIME_DISCARD      /* content is discarded */
  909 };
  910 
  911 enum mime_counter_evidence {
  912    MIMECE_NONE,
  913    MIMECE_SET        = 1<<0,  /* *mime-counter-evidence* was set */
  914    MIMECE_BIN_OVWR   = 1<<1,  /* appli../octet-stream: check, ovw if possible */
  915    MIMECE_ALL_OVWR   = 1<<2,  /* all: check, ovw if possible */
  916    MIMECE_BIN_PARSE  = 1<<3   /* appli../octet-stream: classify contents last */
  917 };
  918 
  919 /* Content-Transfer-Encodings as defined in RFC 2045:
  920  * - Quoted-Printable, section 6.7
  921  * - Base64, section 6.8 */
  922 #define QP_LINESIZE     (4 * 19)       /* Max. compliant QP linesize */
  923 
  924 #define B64_LINESIZE    (4 * 19)       /* Max. compliant Base64 linesize */
  925 #define B64_ENCODE_INPUT_PER_LINE ((B64_LINESIZE / 4) * 3)
  926 
  927 enum mime_enc {
  928    MIMEE_NONE,       /* message is not in MIME format */
  929    MIMEE_BIN,        /* message is in binary encoding */
  930    MIMEE_8B,         /* message is in 8bit encoding */
  931    MIMEE_7B,         /* message is in 7bit encoding */
  932    MIMEE_QP,         /* message is quoted-printable */
  933    MIMEE_B64         /* message is in base64 encoding */
  934 };
  935 
  936 /* xxx QP came later, maybe rewrite all to use mime_enc_flags directly? */
  937 enum mime_enc_flags {
  938    MIMEEF_NONE,
  939    MIMEEF_SALLOC     = 1<<0,  /* Use salloc(), not srealloc().. */
  940    /* ..result .s,.l point to user buffer of *_LINESIZE+[+[+]] bytes instead */
  941    MIMEEF_BUF        = 1<<1,
  942    MIMEEF_CRLF       = 1<<2,  /* (encode) Append "\r\n" to lines */
  943    MIMEEF_LF         = 1<<3,  /* (encode) Append "\n" to lines */
  944    /* (encode) If one of _CRLF/_LF is set, honour *_LINESIZE+[+[+]] and
  945     * inject the desired line-ending whenever a linewrap is desired */
  946    MIMEEF_MULTILINE  = 1<<4,
  947    /* (encode) Quote with header rules, do not generate soft NL breaks?
  948     * For mustquote(), specifies whether special RFC 2047 header rules
  949     * should be used instead */
  950    MIMEEF_ISHEAD     = 1<<5,
  951    /* (encode) Ditto; for mustquote() this furtherly fine-tunes behaviour in
  952     * that characters which would not be reported as "must-quote" when
  953     * detecting whether quoting is necessary at all will be reported as
  954     * "must-quote" if they have to be encoded in an encoded word */
  955    MIMEEF_ISENCWORD  = 1<<6,
  956    __MIMEEF_LAST     = 6
  957 };
  958 
  959 enum qpflags {
  960    QP_NONE        = MIMEEF_NONE,
  961    QP_SALLOC      = MIMEEF_SALLOC,
  962    QP_BUF         = MIMEEF_BUF,
  963    QP_ISHEAD      = MIMEEF_ISHEAD,
  964    QP_ISENCWORD   = MIMEEF_ISENCWORD
  965 };
  966 
  967 enum b64flags {
  968    B64_NONE       = MIMEEF_NONE,
  969    B64_SALLOC     = MIMEEF_SALLOC,
  970    B64_BUF        = MIMEEF_BUF,
  971    B64_CRLF       = MIMEEF_CRLF,
  972    B64_LF         = MIMEEF_LF,
  973    B64_MULTILINE  = MIMEEF_MULTILINE,
  974    /* Not used, but for clarity only */
  975    B64_ISHEAD     = MIMEEF_ISHEAD,
  976    B64_ISENCWORD  = MIMEEF_ISENCWORD,
  977    /* Special version of Base64, "Base64URL", according to RFC 4648.
  978     * Only supported for encoding! */
  979    B64_RFC4648URL = 1<<(__MIMEEF_LAST+1),
  980    /* Don't use any ("=") padding;
  981     * may NOT be used with any of _CRLF, _LF or _MULTILINE */
  982    B64_NOPAD      = 1<<(__MIMEEF_LAST+2)
  983 };
  984 
  985 enum mime_parse_flags {
  986    MIME_PARSE_NONE,
  987    MIME_PARSE_DECRYPT = 1u<<0,
  988    MIME_PARSE_PARTS = 1u<<1,
  989    MIME_PARSE_SHALLOW = 1u<<2,
  990    /* In effect we parse this message for user display or quoting purposes, so
  991     * relaxed rules regarding content inspection may be applicable */
  992    MIME_PARSE_FOR_USER_CONTEXT = 1u<<3
  993 };
  994 
  995 enum mime_handler_flags {
  996    MIME_HDL_NULL,                /* No pipe- mimetype handler, go away */
  997    MIME_HDL_CMD,                 /* Normal command */
  998    MIME_HDL_TEXT,                /* @ special cmd to force treatment as text */
  999    MIME_HDL_PTF,                 /* A special pointer-to-function handler */
 1000    MIME_HDL_MSG,                 /* Display msg (returned as command string) */
 1001    MIME_HDL_TYPE_MASK = 7u,
 1002    MIME_HDL_COPIOUSOUTPUT = 1u<<4, /* _CMD produces reintegratable text */
 1003    MIME_HDL_ISQUOTE = 1u<<5,     /* Is quote action (we have info, keep it!) */
 1004    MIME_HDL_NOQUOTE = 1u<<6,     /* No MIME for quoting */
 1005    MIME_HDL_ASYNC = 1u<<7,       /* Should run asynchronously */
 1006    MIME_HDL_NEEDSTERM = 1u<<8,   /* Takes over terminal */
 1007    MIME_HDL_TMPF = 1u<<9,        /* Create temporary file (zero-sized) */
 1008    MIME_HDL_TMPF_FILL = 1u<<10,  /* Fill in the msg body content */
 1009    MIME_HDL_TMPF_UNLINK = 1u<<11 /* Delete it later again */
 1010 };
 1011 
 1012 enum mlist_state {
 1013    MLIST_OTHER       = 0,     /* Normal address */
 1014    MLIST_KNOWN       = 1,     /* A known `mlist' */
 1015    MLIST_SUBSCRIBED  = -1     /* A `mlsubscribe'd list */
 1016 };
 1017 
 1018 enum oflags {
 1019    OF_RDONLY      = 1<<0,
 1020    OF_WRONLY      = 1<<1,
 1021    OF_RDWR        = 1<<2,
 1022    OF_APPEND      = 1<<3,
 1023    OF_CREATE      = 1<<4,
 1024    OF_TRUNC       = 1<<5,
 1025    OF_EXCL        = 1<<6,
 1026    OF_CLOEXEC     = 1<<7,     /* TODO not used, always implied!  CHANGE!! */
 1027    OF_UNLINK      = 1<<8,     /* Only for Ftmp(): unlink(2) after creation */
 1028    OF_HOLDSIGS    = 1<<9,     /* Mutual with OF_UNLINK - await Ftmp_free() */
 1029    OF_REGISTER    = 1<<10,    /* Register file in our file table */
 1030    OF_REGISTER_UNLINK = 1<<11, /* unlink(2) upon unreg.; _REGISTER asserted! */
 1031    OF_SUFFIX      = 1<<12     /* Ftmp() name hint is mandatory! extension! */
 1032 };
 1033 
 1034 enum okay {
 1035    STOP = 0,
 1036    OKAY = 1
 1037 };
 1038 
 1039 enum okey_xlook_mode {
 1040    OXM_PLAIN      = 1<<0,     /* Plain key always tested */
 1041    OXM_H_P        = 1<<1,     /* Check PLAIN-.url_h_p */
 1042    OXM_U_H_P      = 1<<2,     /* Check PLAIN-.url_u_h_p */
 1043    OXM_ALL        = 0x7
 1044 };
 1045 
 1046 /* <0 means "stop" unless *prompt* extensions are enabled. */
 1047 enum prompt_exp {
 1048    PROMPT_STOP    = -1,       /* \c */
 1049    /* *prompt* extensions: \$, \@ etc. */
 1050    PROMPT_DOLLAR  = -2,
 1051    PROMPT_AT      = -3
 1052 };
 1053 
 1054 enum protocol {
 1055    n_PROTO_NONE,
 1056    n_PROTO_FILE,        /* refers to a local file */
 1057 PROTO_FILE = n_PROTO_FILE,
 1058    n_PROTO_POP3,        /* is a pop3 server string */
 1059 PROTO_POP3 = n_PROTO_POP3,
 1060 n_PROTO_IMAP,
 1061 PROTO_IMAP = n_PROTO_IMAP,
 1062    n_PROTO_MAILDIR,     /* refers to a maildir folder */
 1063 PROTO_MAILDIR = n_PROTO_MAILDIR,
 1064    n_PROTO_UNKNOWN,     /* unknown protocol */
 1065 PROTO_UNKNOWN = n_PROTO_UNKNOWN,
 1066 
 1067    n__PROTO_SHIFT = n_PROTO_UNKNOWN,
 1068    n_PROTO_MASK = (1u << n__PROTO_SHIFT) - 1
 1069 };
 1070 n_MCTA(n__PROTO_SHIFT == 5, "enum n_fopen_state shift value must be adjusted!")
 1071 
 1072 enum sendaction {
 1073    SEND_MBOX,        /* no conversion to perform */
 1074    SEND_RFC822,      /* no conversion, no From_ line */
 1075    SEND_TODISP,      /* convert to displayable form */
 1076    SEND_TODISP_ALL,  /* same, include all MIME parts */
 1077    SEND_TODISP_PARTS, /* same, but only interactive, user-selected parts */
 1078    SEND_SHOW,        /* convert to 'show' command form */
 1079    SEND_TOSRCH,      /* convert for IMAP SEARCH */
 1080    SEND_TOFILE,      /* convert for saving body to a file */
 1081    SEND_TOPIPE,      /* convert for pipe-content/subc. */
 1082    SEND_QUOTE,       /* convert for quoting */
 1083    SEND_QUOTE_ALL,   /* same, include all MIME parts */
 1084    SEND_DECRYPT      /* decrypt */
 1085 };
 1086 
 1087 enum n_shexp_parse_flags{
 1088    n_SHEXP_PARSE_NONE,
 1089    /* Don't perform expansions or interpret reverse solidus escape sequences.
 1090     * Output may be NULL, otherwise the possibly trimmed non-expanded input is
 1091     * used as output (implies _PARSE_META_KEEP) */
 1092    n_SHEXP_PARSE_DRYRUN = 1u<<0,
 1093    n_SHEXP_PARSE_TRUNC = 1u<<1,        /* Truncate result storage on entry */
 1094    n_SHEXP_PARSE_TRIM_SPACE = 1u<<2,   /* ..surrounding tokens */
 1095    n_SHEXP_PARSE_TRIM_IFSSPACE = 1u<<3, /* " */
 1096    n_SHEXP_PARSE_LOG = 1u<<4,          /* Log errors */
 1097    n_SHEXP_PARSE_LOG_D_V = 1u<<5,      /* Log errors if n_PO_D_V */
 1098    n_SHEXP_PARSE_IFS_VAR = 1u<<6,      /* IFS is *ifs*, not blankchar() */
 1099    n_SHEXP_PARSE_IFS_ADD_COMMA = 1u<<7, /* Add comma , to normal "IFS" */
 1100    n_SHEXP_PARSE_IFS_IS_COMMA = 1u<<8, /* Let comma , be the sole "IFS" */
 1101    n_SHEXP_PARSE_IGNORE_EMPTY = 1u<<9, /* Ignore empty tokens, start over */
 1102 
 1103    /* Implicitly open quotes, and ditto closing.  _AUTO_FIXED may only be used
 1104     * if an auto-quote-mode is enabled, implies _AUTO_CLOSE and causes the
 1105     * quote mode to be permanently active (cannot be closed) */
 1106    n_SHEXP_PARSE_QUOTE_AUTO_FIXED = 1u<<16,
 1107    n_SHEXP_PARSE_QUOTE_AUTO_SQ = 1u<<17,
 1108    n_SHEXP_PARSE_QUOTE_AUTO_DQ = 1u<<18,
 1109    n_SHEXP_PARSE_QUOTE_AUTO_DSQ = 1u<<19,
 1110    n_SHEXP_PARSE_QUOTE_AUTO_CLOSE = 1u<<20, /* Ignore an open quote at EOS */
 1111    n__SHEXP_PARSE_QUOTE_AUTO_MASK = n_SHEXP_PARSE_QUOTE_AUTO_SQ |
 1112          n_SHEXP_PARSE_QUOTE_AUTO_DQ | n_SHEXP_PARSE_QUOTE_AUTO_DSQ,
 1113 
 1114    /* Recognize metacharacters to separate tokens */
 1115    n_SHEXP_PARSE_META_VERTBAR = 1u<<21,
 1116    n_SHEXP_PARSE_META_AMPERSAND = 1u<<22,
 1117    /* Interpret ; as a sequencing operator, go_input_inject() remainder */
 1118    n_SHEXP_PARSE_META_SEMICOLON = 1u<<23,
 1119    /* LPAREN, RPAREN, LESSTHAN, GREATERTHAN */
 1120 
 1121    n_SHEXP_PARSE_META_MASK = n_SHEXP_PARSE_META_VERTBAR |
 1122          n_SHEXP_PARSE_META_AMPERSAND | n_SHEXP_PARSE_META_SEMICOLON,
 1123 
 1124    /* Keep the metacharacter (or IFS character), do not skip over it */
 1125    n_SHEXP_PARSE_META_KEEP = 1u<<24,
 1126 
 1127    n__SHEXP_PARSE_LAST = 24
 1128 };
 1129 
 1130 enum n_shexp_state{
 1131    n_SHEXP_STATE_NONE,
 1132    /* We have produced some output (or would have, with _PARSE_DRYRUN).
 1133     * Note that empty quotes like '' produce no output but set this bit */
 1134    n_SHEXP_STATE_OUTPUT = 1u<<0,
 1135    /* Don't call the parser again (# comment seen; out of input).
 1136     * Not (necessarily) mutual with _OUTPUT) */
 1137    n_SHEXP_STATE_STOP = 1u<<1,
 1138    n_SHEXP_STATE_UNICODE = 1u<<2,         /* \[Uu] used */
 1139    n_SHEXP_STATE_CONTROL = 1u<<3,         /* Control characters seen */
 1140    n_SHEXP_STATE_QUOTE = 1u<<4,           /* Any quotes seen */
 1141    n_SHEXP_STATE_WS_LEAD = 1u<<5,         /* _TRIM_{IFS,}SPACE: seen.. */
 1142    n_SHEXP_STATE_WS_TRAIL = 1u<<6,        /* .. leading / trailing WS */
 1143    n_SHEXP_STATE_META_VERTBAR = 1u<<7,    /* Metacharacter | follows/ed */
 1144    n_SHEXP_STATE_META_AMPERSAND = 1u<<8,  /* Metacharacter & follows/ed */
 1145    n_SHEXP_STATE_META_SEMICOLON = 1u<<9,  /* Metacharacter ; follows/ed */
 1146 
 1147    n_SHEXP_STATE_META_MASK = n_SHEXP_STATE_META_VERTBAR |
 1148          n_SHEXP_STATE_META_AMPERSAND | n_SHEXP_STATE_META_SEMICOLON,
 1149 
 1150    n_SHEXP_STATE_ERR_CONTROL = 1u<<16,    /* \c notation with invalid arg. */
 1151    n_SHEXP_STATE_ERR_UNICODE = 1u<<17,    /* Valid \[Uu] and !n_PSO_UNICODE */
 1152    n_SHEXP_STATE_ERR_NUMBER = 1u<<18,     /* Bad number (\[UuXx]) */
 1153    n_SHEXP_STATE_ERR_IDENTIFIER = 1u<<19, /* Invalid identifier */
 1154    n_SHEXP_STATE_ERR_BADSUB = 1u<<20,     /* Empty/bad ${}/[] substitution */
 1155    n_SHEXP_STATE_ERR_GROUPOPEN = 1u<<21,  /* _QUOTEOPEN + no }/]/)/ 4 ${/[/( */
 1156    n_SHEXP_STATE_ERR_QUOTEOPEN = 1u<<22,  /* Quote remains open at EOS */
 1157 
 1158    n_SHEXP_STATE_ERR_MASK = n_BITENUM_MASK(16, 22)
 1159 };
 1160 
 1161 enum n_sigman_flags{
 1162    n_SIGMAN_NONE = 0,
 1163    n_SIGMAN_HUP = 1<<0,
 1164    n_SIGMAN_INT = 1<<1,
 1165    n_SIGMAN_QUIT = 1<<2,
 1166    n_SIGMAN_TERM = 1<<3,
 1167    n_SIGMAN_PIPE = 1<<4,
 1168 
 1169    n_SIGMAN_IGN_HUP = 1<<5,
 1170    n_SIGMAN_IGN_INT = 1<<6,
 1171    n_SIGMAN_IGN_QUIT = 1<<7,
 1172    n_SIGMAN_IGN_TERM = 1<<8,
 1173 
 1174    n_SIGMAN_ALL = 0xFF,
 1175    /* Mostly for _leave() reraise flags */
 1176    n_SIGMAN_VIPSIGS = n_SIGMAN_HUP | n_SIGMAN_INT | n_SIGMAN_QUIT |
 1177          n_SIGMAN_TERM,
 1178    n_SIGMAN_NTTYOUT_PIPE = 1<<16,
 1179    n_SIGMAN_VIPSIGS_NTTYOUT = n_SIGMAN_HUP | n_SIGMAN_INT | n_SIGMAN_QUIT |
 1180          n_SIGMAN_TERM | n_SIGMAN_NTTYOUT_PIPE,
 1181 
 1182    n__SIGMAN_PING = 1<<17
 1183 };
 1184 
 1185 #ifdef HAVE_SSL
 1186 enum ssl_verify_level {
 1187    SSL_VERIFY_IGNORE,
 1188    SSL_VERIFY_WARN,
 1189    SSL_VERIFY_ASK,
 1190    SSL_VERIFY_STRICT
 1191 };
 1192 #endif
 1193 
 1194 enum n_str_trim_flags{
 1195    n_STR_TRIM_FRONT = 1u<<0,
 1196    n_STR_TRIM_END = 1u<<1,
 1197    n_STR_TRIM_BOTH = n_STR_TRIM_FRONT | n_STR_TRIM_END
 1198 };
 1199 
 1200 enum tdflags {
 1201    TD_NONE,                   /* no display conversion */
 1202    TD_ISPR        = 1<<0,     /* use isprint() checks */
 1203    TD_ICONV       = 1<<1,     /* use iconv() */
 1204    TD_DELCTRL     = 1<<2,     /* delete control characters */
 1205 
 1206    /*
 1207     * NOTE: _TD_EOF and _TD_BUFCOPY may be ORd with enum conversion and
 1208     * enum sendaction, and may thus NOT clash with their bit range!
 1209     */
 1210    _TD_EOF        = 1<<14,    /* EOF seen, last round! */
 1211    _TD_BUFCOPY    = 1<<15     /* Buffer may be constant, copy it */
 1212 };
 1213 
 1214 #ifdef n_HAVE_TCAP
 1215 enum n_termcap_captype{
 1216    n_TERMCAP_CAPTYPE_NONE = 0,
 1217    /* Internally we share the bitspace, so ensure no value ends up as 0 */
 1218    n_TERMCAP_CAPTYPE_BOOL = 1,
 1219    n_TERMCAP_CAPTYPE_NUMERIC,
 1220    n_TERMCAP_CAPTYPE_STRING,
 1221    n__TERMCAP_CAPTYPE_MAX1
 1222 };
 1223 
 1224 /* Termcap commands; different to queries commands perform actions.
 1225  * Commands are resolved upon init time, and are all termcap(5)-compatible,
 1226  * therefore we use the short termcap(5) names.
 1227  * Note this is parsed by make-tcap-map.pl, which expects the syntax
 1228  * "CONSTANT, COMMENT" where COMMENT is "Capname/TCap-Code, TYPE[, FLAGS]",
 1229  * and one of Capname and TCap-Code may be the string "-" meaning ENOENT;
 1230  * a | vertical bar or end-of-comment ends processing; see termcap.c.
 1231  * We may use the free-form part after | for the "Variable String" and notes on
 1232  * necessary termcap_cmd() arguments; if those are in [] brackets they are not
 1233  * regular but are only used when the command, i.e., its effect, is somehow
 1234  * simulated / faked by a built-in fallback implementation.
 1235  * Availability of built-in fallback indicated by leading @ (at-sign) */
 1236 enum n_termcap_cmd{
 1237 # ifdef HAVE_TERMCAP
 1238    n_TERMCAP_CMD_te, /* rmcup/te, STRING | exit_ca_mode: -,- */
 1239    n_TERMCAP_CMD_ti, /* smcup/ti, STRING | enter_ca_mode: -,- */
 1240 
 1241    n_TERMCAP_CMD_ks, /* smkx/ks, STRING | keypad_xmit: -,- */
 1242    n_TERMCAP_CMD_ke, /* rmkx/ke, STRING | keypad_local: -,- */
 1243 
 1244    n_TERMCAP_CMD_cd, /* ed/cd, STRING | clr_eos: -,- */
 1245    n_TERMCAP_CMD_cl, /* clear/cl, STRING | clear_screen(+home): -,- */
 1246    n_TERMCAP_CMD_ho, /* home/ho, STRING | cursor_home: -,- */
 1247 # endif
 1248 
 1249 # ifdef HAVE_MLE
 1250    n_TERMCAP_CMD_ce, /* el/ce, STRING | @ clr_eol: [start-column],- */
 1251    n_TERMCAP_CMD_ch, /* hpa/ch, STRING, IDX1 | column_address: column,- */
 1252    n_TERMCAP_CMD_cr, /* cr/cr, STRING | @ carriage_return: -,- */
 1253    n_TERMCAP_CMD_le, /* cub1/le, STRING, CNT | @ cursor_left: count,- */
 1254    n_TERMCAP_CMD_nd, /* cuf1/nd, STRING, CNT | @ cursor_right: count,- */
 1255 # endif
 1256 
 1257    n__TERMCAP_CMD_MAX1,
 1258    n__TERMCAP_CMD_MASK = (1<<24) - 1,
 1259 
 1260    /* Only perform command if ca-mode is used */
 1261    n_TERMCAP_CMD_FLAG_CA_MODE = 1<<29,
 1262    /* I/O should be flushed after command completed */
 1263    n_TERMCAP_CMD_FLAG_FLUSH = 1<<30
 1264 };
 1265 
 1266 /* Termcap queries; a query is a command that returns a struct n_termcap_value.
 1267  * Queries are resolved once they are used first, and may not be termcap(5)-
 1268  * compatible, therefore we use terminfo(5) names.
 1269  * Note this is parsed by make-tcap-map.pl, which expects the syntax
 1270  * "CONSTANT, COMMENT" where COMMENT is "Capname/TCap-Code, TYPE[, FLAGS]",
 1271  * and one of Capname and TCap-Code may be the string "-" meaning ENOENT;
 1272  * a | vertical bar or end-of-comment ends processing; see termcap.c.
 1273  * We may use the free-form part after | for the "Variable String" and notes.
 1274  * The "xkey | X:" keys are Dickey's xterm extensions, see (our) manual */
 1275 enum n_termcap_query{
 1276 # ifdef HAVE_COLOUR
 1277    n_TERMCAP_QUERY_colors, /* colors/Co, NUMERIC | max_colors */
 1278 # endif
 1279 
 1280    /* --make-tcap-map--: only KEY_BINDINGS follow.  DON'T CHANGE THIS LINE! */
 1281    /* Update the `bind' manual on change! */
 1282 # ifdef HAVE_KEY_BINDINGS
 1283    n_TERMCAP_QUERY_key_backspace, /* kbs/kb, STRING */
 1284    n_TERMCAP_QUERY_key_dc,       /* kdch1/kD, STRING | delete-character */
 1285       n_TERMCAP_QUERY_key_sdc,      /* kDC / *4, STRING | ..shifted */
 1286    n_TERMCAP_QUERY_key_eol,      /* kel/kE, STRING | clear-to-end-of-line */
 1287    n_TERMCAP_QUERY_key_exit,     /* kext/@9, STRING */
 1288    n_TERMCAP_QUERY_key_ic,       /* kich1/kI, STRING | insert character */
 1289       n_TERMCAP_QUERY_key_sic,      /* kIC/#3, STRING | ..shifted */
 1290    n_TERMCAP_QUERY_key_home,     /* khome/kh, STRING */
 1291       n_TERMCAP_QUERY_key_shome,    /* kHOM/#2, STRING | ..shifted */
 1292    n_TERMCAP_QUERY_key_end,      /* kend/@7, STRING */
 1293       n_TERMCAP_QUERY_key_send,     /* kEND / *7, STRING | ..shifted */
 1294    n_TERMCAP_QUERY_key_npage,    /* knp/kN, STRING */
 1295    n_TERMCAP_QUERY_key_ppage,    /* kpp/kP, STRING */
 1296    n_TERMCAP_QUERY_key_left,     /* kcub1/kl, STRING */
 1297       n_TERMCAP_QUERY_key_sleft,    /* kLFT/#4, STRING | ..shifted */
 1298       n_TERMCAP_QUERY_xkey_aleft,   /* kLFT3/-, STRING | X: Alt+left */
 1299       n_TERMCAP_QUERY_xkey_cleft,   /* kLFT5/-, STRING | X: Control+left */
 1300    n_TERMCAP_QUERY_key_right,    /* kcuf1/kr, STRING */
 1301       n_TERMCAP_QUERY_key_sright,   /* kRIT/%i, STRING | ..shifted */
 1302       n_TERMCAP_QUERY_xkey_aright,  /* kRIT3/-, STRING | X: Alt+right */
 1303       n_TERMCAP_QUERY_xkey_cright,  /* kRIT5/-, STRING | X: Control+right */
 1304    n_TERMCAP_QUERY_key_down,     /* kcud1/kd, STRING */
 1305       n_TERMCAP_QUERY_xkey_sdown,   /* kDN/-, STRING | ..shifted */
 1306       n_TERMCAP_QUERY_xkey_adown,   /* kDN3/-, STRING | X: Alt+down */
 1307       n_TERMCAP_QUERY_xkey_cdown,   /* kDN5/-, STRING | X: Control+down */
 1308    n_TERMCAP_QUERY_key_up,       /* kcuu1/ku, STRING */
 1309       n_TERMCAP_QUERY_xkey_sup,     /* kUP/-, STRING | ..shifted */
 1310       n_TERMCAP_QUERY_xkey_aup,     /* kUP3/-, STRING | X: Alt+up */
 1311       n_TERMCAP_QUERY_xkey_cup,     /* kUP5/-, STRING | X: Control+up */
 1312    n_TERMCAP_QUERY_kf0,          /* kf0/k0, STRING */
 1313    n_TERMCAP_QUERY_kf1,          /* kf1/k1, STRING */
 1314    n_TERMCAP_QUERY_kf2,          /* kf2/k2, STRING */
 1315    n_TERMCAP_QUERY_kf3,          /* kf3/k3, STRING */
 1316    n_TERMCAP_QUERY_kf4,          /* kf4/k4, STRING */
 1317    n_TERMCAP_QUERY_kf5,          /* kf5/k5, STRING */
 1318    n_TERMCAP_QUERY_kf6,          /* kf6/k6, STRING */
 1319    n_TERMCAP_QUERY_kf7,          /* kf7/k7, STRING */
 1320    n_TERMCAP_QUERY_kf8,          /* kf8/k8, STRING */
 1321    n_TERMCAP_QUERY_kf9,          /* kf9/k9, STRING */
 1322    n_TERMCAP_QUERY_kf10,         /* kf10/k;, STRING */
 1323    n_TERMCAP_QUERY_kf11,         /* kf11/F1, STRING */
 1324    n_TERMCAP_QUERY_kf12,         /* kf12/F2, STRING */
 1325    n_TERMCAP_QUERY_kf13,         /* kf13/F3, STRING */
 1326    n_TERMCAP_QUERY_kf14,         /* kf14/F4, STRING */
 1327    n_TERMCAP_QUERY_kf15,         /* kf15/F5, STRING */
 1328    n_TERMCAP_QUERY_kf16,         /* kf16/F6, STRING */
 1329    n_TERMCAP_QUERY_kf17,         /* kf17/F7, STRING */
 1330    n_TERMCAP_QUERY_kf18,         /* kf18/F8, STRING */
 1331    n_TERMCAP_QUERY_kf19,         /* kf19/F9, STRING */
 1332 # endif /* HAVE_KEY_BINDINGS */
 1333 
 1334    n__TERMCAP_QUERY_MAX1
 1335 };
 1336 #endif /* n_HAVE_TCAP */
 1337 
 1338 enum n_url_flags{
 1339    n_URL_TLS_REQUIRED = 1<<0, /* Whether protocol always uses SSL/TLS.. */
 1340    n_URL_TLS_OPTIONAL = 1<<1, /* ..may later upgrade to SSL/TLS */
 1341    n_URL_TLS_MASK = n_URL_TLS_REQUIRED | n_URL_TLS_OPTIONAL,
 1342    n_URL_HAD_USER = 1<<2,     /* Whether .url_user was part of the URL */
 1343    n_URL_HOST_IS_NAME = 1<<3  /* .url_host not numeric address */
 1344 };
 1345 
 1346 enum n_visual_info_flags{
 1347    n_VISUAL_INFO_NONE,
 1348    n_VISUAL_INFO_ONE_CHAR = 1<<0,         /* Step only one char, then return */
 1349    n_VISUAL_INFO_SKIP_ERRORS = 1<<1,      /* Treat via replacement, step byte */
 1350    n_VISUAL_INFO_WIDTH_QUERY = 1<<2,      /* Detect visual character widths */
 1351 
 1352    /* Rest only with HAVE_C90AMEND1, mutual with _ONE_CHAR */
 1353    n_VISUAL_INFO_WOUT_CREATE = 1<<8,      /* Use/create .vic_woudat */
 1354    n_VISUAL_INFO_WOUT_SALLOC = 1<<9,      /* ..salloc() it first */
 1355    /* Only visuals into .vic_woudat - implies _WIDTH_QUERY */
 1356    n_VISUAL_INFO_WOUT_PRINTABLE = 1<<10,
 1357    n__VISUAL_INFO_FLAGS = n_VISUAL_INFO_WOUT_CREATE |
 1358          n_VISUAL_INFO_WOUT_SALLOC | n_VISUAL_INFO_WOUT_PRINTABLE
 1359 };
 1360 
 1361 enum n_program_option{
 1362    n_PO_DEBUG = 1u<<0,        /* -d / *debug* */
 1363    n_PO_VERB = 1u<<1,         /* -v / *verbose* */
 1364    n_PO_VERBVERB = 1u<<2,     /* .. even more verbosity */
 1365    n_PO_EXISTONLY = 1u<<3,    /* -e */
 1366    n_PO_HEADERSONLY = 1u<<4,  /* -H */
 1367    n_PO_HEADERLIST = 1u<<5,   /* -L */
 1368    n_PO_QUICKRUN_MASK = n_PO_EXISTONLY | n_PO_HEADERSONLY | n_PO_HEADERLIST,
 1369    n_PO_E_FLAG = 1u<<6,       /* -E / *skipemptybody* */
 1370    n_PO_F_FLAG = 1u<<7,       /* -F */
 1371    n_PO_Mm_FLAG = 1u<<8,      /* -M or -m (plus n_poption_arg_Mm) */
 1372    n_PO_R_FLAG = 1u<<9,       /* -R */
 1373    n_PO_r_FLAG = 1u<<10,      /* -r (plus n_poption_arg_r) */
 1374    n_PO_S_FLAG_TEMPORARY = 1u<<11, /* -S about to set a variable */
 1375    n_PO_t_FLAG = 1u<<12,      /* -t */
 1376    n_PO_TILDE_FLAG = 1u<<13,  /* -~ */
 1377    n_PO_BATCH_FLAG = 1u<<14,  /* -# */
 1378 
 1379    /*  */
 1380    n_PO_MEMDEBUG = 1<<24,     /* *memdebug* */
 1381 
 1382    /* Some easy-access shortcuts */
 1383    n_PO_D_V = n_PO_DEBUG | n_PO_VERB,
 1384    n_PO_D_VV = n_PO_DEBUG | n_PO_VERBVERB,
 1385    n_PO_D_V_VV = n_PO_DEBUG | n_PO_VERB | n_PO_VERBVERB
 1386 };
 1387 
 1388 #define n_OBSOLETE(X) \
 1389 do{\
 1390    if(n_poption & n_PO_D_V_VV)\
 1391       n_err("%s: %s\n", _("Obsoletion warning"), X);\
 1392 }while(0)
 1393 #define n_OBSOLETE2(X,Y) \
 1394 do{\
 1395    if(n_poption & n_PO_D_V_VV)\
 1396       n_err("%s: %s: %s\n", _("Obsoletion warning"), X, Y);\
 1397 }while(0)
 1398 
 1399 /* Program state bits which may regulary fluctuate */
 1400 enum n_program_state{
 1401    n_PS_ROOT = 1u<<30,                 /* Temporary "bypass any checks" bit */
 1402 #define n_PS_ROOT_BLOCK(ACT) \
 1403 do{\
 1404    bool_t a___reset___ = !(n_pstate & n_PS_ROOT);\
 1405    n_pstate |= n_PS_ROOT;\
 1406    ACT;\
 1407    if(a___reset___)\
 1408       n_pstate &= ~n_PS_ROOT;\
 1409 }while(0)
 1410 
 1411    /* XXX These are internal to the state machine and do not belong here,
 1412     * XXX yet this was the easiest (accessible) approach */
 1413    n_PS_ERR_XIT = 1u<<0,               /* Unless `ignerr' seen -> n_PSO_XIT */
 1414    n_PS_ERR_QUIT = 1u<<1,              /* ..ditto: -> n_PSO_QUIT */
 1415    n_PS_ERR_EXIT_MASK = n_PS_ERR_XIT | n_PS_ERR_QUIT,
 1416 
 1417    n_PS_SOURCING = 1u<<2,              /* During load() or `source' */
 1418    n_PS_ROBOT = 1u<<3,                 /* .. even more robotic */
 1419    n_PS_COMPOSE_MODE = 1u<<4,          /* State machine recursed */
 1420    n_PS_COMPOSE_FORKHOOK = 1u<<5,      /* A hook running in a subprocess */
 1421 
 1422    n_PS_HOOK_NEWMAIL = 1u<<7,
 1423    n_PS_HOOK = 1u<<8,
 1424    n_PS_HOOK_MASK = n_PS_HOOK_NEWMAIL | n_PS_HOOK,
 1425 
 1426    n_PS_EDIT = 1u<<9,                  /* Current mailbox no "system mailbox" */
 1427    n_PS_SETFILE_OPENED = 1u<<10,       /* (hack) setfile() opened a new box */
 1428    n_PS_SAW_COMMAND = 1u<<11,          /* ..after mailbox switch */
 1429    n_PS_DID_PRINT_DOT = 1u<<12,        /* Current message has been printed */
 1430 
 1431    n_PS_SIGWINCH_PEND = 1u<<13,        /* Need update of $COLUMNS/$LINES */
 1432    n_PS_PSTATE_PENDMASK = n_PS_SIGWINCH_PEND, /* pstate housekeeping needed */
 1433 
 1434    n_PS_ARGLIST_MASK = n_BITENUM_MASK(14, 16),
 1435    n_PS_ARGMOD_LOCAL = 1u<<14,         /* "local" modifier TODO struct CmdCtx */
 1436    n_PS_ARGMOD_VPUT = 1u<<16,          /* "vput" modifier TODO struct CmdCtx */
 1437    n_PS_MSGLIST_GABBY = 1u<<14,        /* getmsglist() saw something gabby */
 1438    n_PS_MSGLIST_DIRECT = 1u<<15,       /* A msg was directly chosen by number */
 1439    /* TODO HACK: until v15 PS_MSGLIST_SAW_NO is an indication whether an entry
 1440     * TODO may be placed in the history or not (grep this, see commands()),
 1441     * TODO so avoid reusing this bit */
 1442    n_PS_WYSHLIST_SAW_CONTROL = 1u<<15, /* ..saw C0+ control characters */
 1443 
 1444    n_PS_EXPAND_MULTIRESULT = 1u<<17,   /* Last fexpand() with MULTIOK had .. */
 1445    n_PS_ERRORS_PROMPT = 1u<<18,        /* New error to be reported in prompt */
 1446 
 1447    /* Bad hacks */
 1448    n_PS_HEADER_NEEDED_MIME = 1u<<24,   /* mime_write_tohdr() not ASCII clean */
 1449    n_PS_READLINE_NL = 1u<<25,          /* readline_input()+ saw a \n */
 1450    n_PS_BASE64_STRIP_CR = 1u<<26       /* Go for text output, strip CR's */
 1451 };
 1452 
 1453 /* Various states set once, and first time messages or initializers */
 1454 enum n_program_state_once{
 1455    /* We have four program states: (0) pre getopt() done, (_GETOPT) pre rcfile
 1456     * loaded etc., (_CONFIG) only -X evaluation missing still, followed by
 1457     * _STARTED when we are fully setup */
 1458    n_PSO_STARTED_GETOPT = 1u<<0,
 1459    n_PSO_STARTED_CONFIG = 1u<<1,
 1460    n_PSO_STARTED = 1u<<2,
 1461 
 1462    /* Exit request pending (quick) */
 1463    n_PSO_XIT = 1u<<3,
 1464    n_PSO_QUIT = 1u<<4,
 1465    n_PSO_EXIT_MASK = n_PSO_XIT | n_PSO_QUIT,
 1466 
 1467    /* Pre _STARTED */
 1468    n_PSO_BIG_ENDIAN = 1u<<5,
 1469    n_PSO_UNICODE = 1u<<6,
 1470    n_PSO_ENC_MBSTATE = 1u<<7,
 1471 
 1472    n_PSO_REPRODUCIBLE = 1u<<8,
 1473    n_PSO_SENDMODE = 1u<<9,
 1474    n_PSO_INTERACTIVE = 1u<<10,
 1475    n_PSO_TTYIN = 1u<<11,
 1476    n_PSO_TTYOUT = 1u<<12, /* TODO should be TTYERR! */
 1477 
 1478    /* "Later" */
 1479    n_PSO_ATTACH_QUOTE_NOTED = 1u<<16,
 1480    n_PSO_ERRORS_NOTED = 1u<<17,
 1481    n_PSO_LINE_EDITOR_INIT = 1u<<18,
 1482    n_PSO_RANDOM_INIT = 1u<<19,
 1483    n_PSO_TERMCAP_DISABLE = 1u<<20,
 1484    n_PSO_TERMCAP_CA_MODE = 1u<<21,
 1485 
 1486    /* TODO A subtile HACK which works in conjunction with n_OPT_t_FLAG so as
 1487     * to allow to have multiple states regarding the related header setup */
 1488    n_PSO_t_FLAG = 1u<<30
 1489 };
 1490 
 1491 /* {{{ A large enum with all the boolean and value options a.k.a their keys.
 1492  * Only the constant keys are in here, to be looked up via ok_[bv]look(),
 1493  * ok_[bv]set() and ok_[bv]clear().
 1494  * Variable properties are placed in {PROP=VALUE[:,PROP=VALUE:]} comments,
 1495  * a {\} comment causes the next line to be read for (overlong) properties.
 1496  * Notes:
 1497  * - see the comments in accmacvar.c before changing *anything* in here!
 1498  * - virt= implies rdonly,nodel
 1499  * - import= implies env
 1500  * - num and posnum are mutual exclusive
 1501  * - most default VAL_ues come from in from build system via ./make.rc
 1502  * (Keep in SYNC: ./nail.h:okeys, ./nail.rc, ./nail.1:"Initial settings") */
 1503 enum okeys {
 1504    /* This is used for all macro(-local) variables etc., i.e.,
 1505     * [*@#]|[1-9][0-9]*, in order to have something with correct properties.
 1506     * It is also used for the ${^.+} multiplexer */
 1507    ok_v___special_param,   /* {nolopts=1,rdonly=1,nodel=1} */
 1508    /*__qm/__em aka ?/! should be num=1 but that more expensive than what now */
 1509    ok_v___qm,              /* {name=?,nolopts=1,rdonly=1,nodel=1} */
 1510    ok_v___em,              /* {name=!,nolopts=1,rdonly=1,nodel=1} */
 1511 
 1512    ok_v_account,                       /* {nolopts=1,rdonly=1,nodel=1} */
 1513    ok_b_add_file_recipients,
 1514 ok_v_agent_shell_lookup, /* {obsolete=1} */
 1515    ok_b_allnet,
 1516    ok_b_append,
 1517    /* *ask* is auto-mapped to *asksub* as imposed by standard! */
 1518    ok_b_ask,                           /* {vip=1} */
 1519    ok_b_askatend,
 1520    ok_b_askattach,
 1521    ok_b_askbcc,
 1522    ok_b_askcc,
 1523    ok_b_asksign,
 1524    ok_b_asksend,                       /* {i3val=TRU1} */
 1525    ok_b_asksub,                        /* {i3val=TRU1} */
 1526    ok_v_attrlist,
 1527    ok_v_autobcc,
 1528    ok_v_autocc,
 1529    ok_b_autocollapse,
 1530    ok_b_autoprint,
 1531 ok_b_autothread, /* {obsolete=1} */
 1532    ok_v_autosort,
 1533 
 1534    ok_b_bang,
 1535 ok_b_batch_exit_on_error, /* {obsolete=1} */
 1536    ok_v_bind_timeout,                  /* {notempty=1,posnum=1} */
 1537 ok_b_bsdannounce, /* {obsolete=1} */
 1538    ok_b_bsdcompat,
 1539    ok_b_bsdflags,
 1540    ok_b_bsdheadline,
 1541    ok_b_bsdmsgs,
 1542    ok_b_bsdorder,
 1543    ok_v_build_os,                      /* {virt=VAL_BUILD_OS} */
 1544    ok_v_build_osenv,                   /* {virt=VAL_BUILD_OSENV} */
 1545 
 1546    ok_v_COLUMNS,                       /* {notempty=1,posnum=1,env=1} */
 1547    ok_v_charset_7bit,            /* {lower=1,notempty=1,defval=CHARSET_7BIT} */
 1548    /* But unused without HAVE_ICONV, we use ok_vlook(CHARSET_8BIT_OKEY)! */
 1549    ok_v_charset_8bit,            /* {lower=1,notempty=1,defval=CHARSET_8BIT} */
 1550    ok_v_charset_unknown_8bit,          /* {lower=1} */
 1551    ok_v_cmd,
 1552    ok_b_colour_disable,
 1553    ok_b_colour_pager,
 1554    ok_v_contact_mail,                  /* {virt=VAL_CONTACT_MAIL} */
 1555    ok_v_contact_web,                   /* {virt=VAL_CONTACT_WEB} */
 1556    ok_v_crt,                           /* {posnum=1} */
 1557    ok_v_customhdr,                     /* {vip=1} */
 1558 
 1559    ok_v_DEAD,                          /* {notempty=1,env=1,defval=VAL_DEAD} */
 1560    ok_v_datefield,                     /* {i3val="%Y-%m-%d %H:%M"} */
 1561    ok_v_datefield_markout_older,       /* {i3val="%Y-%m-%d"} */
 1562    ok_b_debug,                         /* {vip=1} */
 1563    ok_b_disposition_notification_send,
 1564    ok_b_dot,
 1565    ok_b_dotlock_ignore_error,
 1566 
 1567    ok_v_EDITOR,                     /* {env=1,notempty=1,defval=VAL_EDITOR} */
 1568    ok_b_editalong,
 1569    ok_b_editheaders,
 1570    ok_b_emptystart,
 1571 ok_v_encoding, /* {obsolete=1} */
 1572    ok_b_errexit,
 1573    ok_v_escape,                        /* {defval=n_ESCAPE} */
 1574    ok_v_expandaddr,
 1575    ok_v_expandargv,
 1576 
 1577    ok_v_features,                      /* {virt=VAL_FEATURES} */
 1578    ok_b_flipr,
 1579    ok_v_folder,                        /* {vip=1} */
 1580    ok_v_folder_resolved,               /* {rdonly=1,nodel=1} */
 1581    ok_v_folder_hook,
 1582    ok_b_followup_to,
 1583    ok_v_followup_to_honour,
 1584    ok_b_forward_as_attachment,
 1585    ok_v_forward_inject_head,
 1586    ok_v_from,                          /* {vip=1} */
 1587    ok_b_fullnames,
 1588 ok_v_fwdheading, /* {obsolete=1} */
 1589 
 1590    ok_v_HOME,                          /* {vip=1,nodel=1,notempty=1,import=1} */
 1591    ok_b_header,                        /* {i3val=TRU1} */
 1592    ok_v_headline,
 1593    ok_v_headline_bidi,
 1594    ok_v_history_file,
 1595    ok_b_history_gabby,
 1596    ok_b_history_gabby_persist,
 1597    ok_v_history_size,                  /* {notempty=1,posnum=1} */
 1598    ok_b_hold,
 1599    ok_v_hostname,                      /* {vip=1} */
 1600 
 1601    ok_b_idna_disable,
 1602    ok_v_ifs,                           /* {vip=1,defval=" \t\n"} */
 1603    ok_v_ifs_ws,                     /* {vip=1,rdonly=1,nodel=1,i3val=" \t\n"} */
 1604    ok_b_ignore,
 1605    ok_b_ignoreeof,
 1606    ok_v_inbox,
 1607    ok_v_indentprefix,                  /* {defval="\t"} */
 1608 
 1609    ok_b_keep,
 1610    ok_b_keep_content_length,
 1611    ok_b_keepsave,
 1612 
 1613    ok_v_LANG,                          /* {vip=1,env=1,notempty=1} */
 1614    ok_v_LC_ALL,                     /* {name=LC_ALL,vip=1,env=1,notempty=1} */
 1615    ok_v_LC_CTYPE,                   /* {name=LC_CTYPE,vip=1,env=1,notempty=1} */
 1616    ok_v_LINES,                         /* {notempty=1,posnum=1,env=1} */
 1617    ok_v_LISTER,                     /* {env=1,notempty=1,defval=VAL_LISTER} */
 1618    ok_v_LOGNAME,                       /* {rdonly=1,import=1} */
 1619    ok_b_line_editor_disable,
 1620    ok_b_line_editor_no_defaults,
 1621    ok_v_log_prefix,                    /* {nodel=1,i3val=VAL_UAGENT ": "} */
 1622 
 1623    ok_v_MAIL,                          /* {env=1} */
 1624    ok_v_MAILRC,                  /* {import=1,notempty=1,defval=VAL_MAILRC} */
 1625    ok_b_MAILX_NO_SYSTEM_RC,            /* {name=MAILX_NO_SYSTEM_RC,import=1} */
 1626    ok_v_MBOX,                          /* {env=1,notempty=1,defval=VAL_MBOX} */
 1627    ok_v_mailbox_resolved,              /* {nolopts=1,rdonly=1,nodel=1} */
 1628    ok_v_mailbox_display,               /* {nolopts=1,rdonly=1,nodel=1} */
 1629    ok_v_mailx_extra_rc,
 1630    ok_b_markanswered,
 1631    ok_b_mbox_rfc4155,
 1632    ok_b_memdebug,                      /* {vip=1} */
 1633    ok_b_message_id_disable,
 1634    ok_v_message_inject_head,
 1635    ok_v_message_inject_tail,
 1636    ok_b_metoo,
 1637    ok_b_mime_allow_text_controls,
 1638    ok_b_mime_alternative_favour_rich,
 1639    ok_v_mime_counter_evidence,         /* {posnum=1} */
 1640    ok_v_mime_encoding,
 1641    ok_v_mimetypes_load_control,
 1642    ok_v_mta,                           /* {notempty=1,defval=VAL_MTA} */
 1643    ok_v_mta_arguments,
 1644    ok_b_mta_no_default_arguments,
 1645    ok_b_mta_no_receiver_arguments,
 1646    ok_v_mta_argv0,                     /* {notempty=1,defval=VAL_MTA_ARGV0} */
 1647 
 1648    /* TODO likely temporary hook data, v15 drop */
 1649    ok_v_mailx_command,                 /* {rdonly=1,nodel=1} */
 1650    ok_v_mailx_subject,                 /* {rdonly=1,nodel=1} */
 1651    ok_v_mailx_from,                    /* {rdonly=1,nodel=1} */
 1652    ok_v_mailx_sender,                  /* {rdonly=1,nodel=1} */
 1653    ok_v_mailx_to,                      /* {rdonly=1,nodel=1} */
 1654    ok_v_mailx_cc,                      /* {rdonly=1,nodel=1} */
 1655    ok_v_mailx_bcc,                     /* {rdonly=1,nodel=1} */
 1656    ok_v_mailx_raw_to,                  /* {rdonly=1,nodel=1} */
 1657    ok_v_mailx_raw_cc,                  /* {rdonly=1,nodel=1} */
 1658    ok_v_mailx_raw_bcc,                 /* {rdonly=1,nodel=1} */
 1659    ok_v_mailx_orig_from,               /* {rdonly=1,nodel=1} */
 1660    ok_v_mailx_orig_to,                 /* {rdonly=1,nodel=1} */
 1661    ok_v_mailx_orig_cc,                 /* {rdonly=1,nodel=1} */
 1662    ok_v_mailx_orig_bcc,                /* {rdonly=1,nodel=1} */
 1663 
 1664 ok_v_NAIL_EXTRA_RC, /* {name=NAIL_EXTRA_RC,obsolete=1} */
 1665 ok_b_NAIL_NO_SYSTEM_RC, /* {name=NAIL_NO_SYSTEM_RC,import=1,obsolete=1} */
 1666 ok_v_NAIL_HEAD, /* {name=NAIL_HEAD,obsolete=1} */
 1667 ok_v_NAIL_HISTFILE, /* {name=NAIL_HISTFILE,obsolete=1} */
 1668 ok_v_NAIL_HISTSIZE, /* {name=NAIL_HISTSIZE,notempty=1,num=1,obsolete=1} */
 1669 ok_v_NAIL_TAIL, /* {name=NAIL_TAIL,obsolete=1} */
 1670    ok_v_NETRC,                         /* {env=1,notempty=1,defval=VAL_NETRC} */
 1671    ok_b_netrc_lookup,                  /* {chain=1} */
 1672    ok_v_netrc_pipe,
 1673    ok_v_newfolders,
 1674    ok_v_newmail,
 1675 
 1676    ok_v_on_account_cleanup,            /* {notempty=1} */
 1677    ok_v_on_compose_cleanup,            /* {notempty=1} */
 1678    ok_v_on_compose_enter,              /* {notempty=1} */
 1679    ok_v_on_compose_leave,              /* {notempty=1} */
 1680    ok_v_on_compose_splice,             /* {notempty=1} */
 1681    ok_v_on_compose_splice_shell,       /* {notempty=1} */
 1682    ok_v_on_resend_cleanup,             /* {notempty=1} */
 1683    ok_v_on_resend_enter,               /* {notempty=1} */
 1684    ok_b_outfolder,
 1685 
 1686    ok_v_PAGER,                         /* {env=1,notempty=1,defval=VAL_PAGER} */
 1687    ok_v_PATH,                          /* {nodel=1,import=1} */
 1688    ok_b_POSIXLY_CORRECT,            /* {vip=1,import=1,name=POSIXLY_CORRECT} */
 1689    ok_b_page,
 1690    ok_v_password,                      /* {chain=1} */
 1691    ok_b_piperaw,
 1692    ok_v_pop3_auth,                     /* {chain=1} */
 1693    ok_b_pop3_bulk_load,
 1694    ok_v_pop3_keepalive,                /* {notempty=1,posnum=1} */
 1695    ok_b_pop3_no_apop,                  /* {chain=1} */
 1696    ok_b_pop3_use_starttls,             /* {chain=1} */
 1697    ok_b_posix,                         /* {vip=1} */
 1698    ok_b_print_alternatives,
 1699    ok_v_prompt,                        /* {i3val="? "} */
 1700    ok_v_prompt2,                       /* {i3val=".. "} */
 1701 
 1702    ok_b_quiet,
 1703    ok_v_quote,
 1704    ok_b_quote_as_attachment,
 1705    ok_v_quote_chars,                   /* {vip=1,notempty=1,defval=">|}:"} */
 1706    ok_v_quote_fold,
 1707 
 1708    ok_b_r_option_implicit,
 1709    ok_b_recipients_in_cc,
 1710    ok_v_record,
 1711    ok_b_record_files,
 1712    ok_b_record_resent,
 1713    ok_b_reply_in_same_charset,
 1714    ok_v_reply_strings,
 1715 ok_v_replyto, /* {obsolete=1} */
 1716    ok_v_reply_to,                      /* {notempty=1} */
 1717    ok_v_reply_to_honour,
 1718    ok_b_rfc822_body_from_,             /* {name=rfc822-body-from_} */
 1719 
 1720    ok_v_SHELL,                      /* {import=1,notempty=1,defval=VAL_SHELL} */
 1721 ok_b_SYSV3, /* {env=1,obsolete=1} */
 1722    ok_b_save,                          /* {i3val=TRU1} */
 1723    ok_v_screen,                        /* {notempty=1,posnum=1} */
 1724    ok_b_searchheaders,
 1725    ok_v_sendcharsets,                  /* {lower=1} */
 1726    ok_b_sendcharsets_else_ttycharset,
 1727    ok_v_sender,                        /* {vip=1} */
 1728 ok_v_sendmail, /* {obsolete=1} */
 1729 ok_v_sendmail_arguments, /* {obsolete=1} */
 1730 ok_b_sendmail_no_default_arguments, /* {obsolete=1} */
 1731 ok_v_sendmail_progname, /* {obsolete=1} */
 1732    ok_b_sendwait,
 1733    ok_b_showlast,
 1734    ok_b_showname,
 1735    ok_b_showto,
 1736    ok_v_Sign,
 1737    ok_v_sign,
 1738 ok_v_signature, /* {obsolete=1} */
 1739    ok_b_skipemptybody,                 /* {vip=1} */
 1740    ok_v_smime_ca_dir,
 1741    ok_v_smime_ca_file,
 1742    ok_v_smime_ca_flags,
 1743    ok_b_smime_ca_no_defaults,
 1744    ok_v_smime_cipher,                  /* {chain=1} */
 1745    ok_v_smime_crl_dir,
 1746    ok_v_smime_crl_file,
 1747    ok_v_smime_encrypt,                 /* {chain=1} */
 1748    ok_b_smime_force_encryption,
 1749 ok_b_smime_no_default_ca, /* {obsolete=1} */
 1750    ok_b_smime_sign,
 1751    ok_v_smime_sign_cert,               /* {chain=1} */
 1752    ok_v_smime_sign_include_certs,      /* {chain=1} */
 1753    ok_v_smime_sign_message_digest,     /* {chain=1} */
 1754 ok_v_smtp, /* {obsolete=1} */
 1755    ok_v_smtp_auth,                     /* {chain=1} */
 1756 ok_v_smtp_auth_password, /* {obsolete=1} */
 1757 ok_v_smtp_auth_user, /* {obsolete=1} */
 1758    ok_v_smtp_hostname,                 /* {vip=1} */
 1759    ok_b_smtp_use_starttls,             /* {chain=1} */
 1760    ok_v_SOURCE_DATE_EPOCH,             /* {\} */
 1761       /* {name=SOURCE_DATE_EPOCH,rdonly=1,import=1,notempty=1,posnum=1} */
 1762    ok_v_socks_proxy,                   /* {chain=1,notempty=1} */
 1763    ok_v_spam_interface,
 1764    ok_v_spam_maxsize,                  /* {notempty=1,posnum=1} */
 1765    ok_v_spamc_command,
 1766    ok_v_spamc_arguments,
 1767    ok_v_spamc_user,
 1768 ok_v_spamd_socket, /* {obsolete=1} */
 1769 ok_v_spamd_user, /* {obsolete=1} */
 1770    ok_v_spamfilter_ham,
 1771    ok_v_spamfilter_noham,
 1772    ok_v_spamfilter_nospam,
 1773    ok_v_spamfilter_rate,
 1774    ok_v_spamfilter_rate_scanscore,
 1775    ok_v_spamfilter_spam,
 1776    ok_v_ssl_ca_dir,                    /* {chain=1} */
 1777    ok_v_ssl_ca_file,                   /* {chain=1} */
 1778    ok_v_ssl_ca_flags,                  /* {chain=1} */
 1779    ok_b_ssl_ca_no_defaults,            /* {chain=1} */
 1780 ok_v_ssl_cert, /* {chain=1,obsolete=1} */
 1781 ok_v_ssl_cipher_list, /* {chain=1,obsolete=1} */
 1782    ok_v_ssl_config_file,
 1783    ok_v_ssl_config_module,             /* {chain=1} */
 1784    ok_v_ssl_config_pairs,              /* {chain=1} */
 1785 ok_v_ssl_curves, /* {chain=1,obsolete=1} */
 1786    ok_v_ssl_crl_dir,
 1787    ok_v_ssl_crl_file,
 1788    ok_v_ssl_features,                  /* {virt=VAL_SSL_FEATURES} */
 1789 ok_v_ssl_key, /* {chain=1,obsolete=1} */
 1790 ok_v_ssl_method, /* {chain=1,obsolete=1} */
 1791 ok_b_ssl_no_default_ca,
 1792 ok_v_ssl_protocol, /* {chain=1,obsolete=1} */
 1793    ok_v_ssl_rand_egd,
 1794    ok_v_ssl_rand_file,
 1795    ok_v_ssl_verify,                    /* {chain=1} */
 1796    ok_v_stealthmua,
 1797 
 1798    ok_v_TERM,                          /* {env=1} */
 1799    ok_v_TMPDIR,            /* {import=1,vip=1,notempty=1,defval=VAL_TMPDIR} */
 1800    ok_v_termcap,
 1801    ok_b_termcap_ca_mode,
 1802    ok_b_termcap_disable,
 1803    ok_v_toplines,                      /* {notempty=1,num=1,defval="5"} */
 1804    ok_b_topsqueeze,
 1805    ok_v_ttycharset,              /* {lower=1,notempty=1,defval=CHARSET_8BIT} */
 1806    ok_b_typescript_mode,               /* {vip=1} */
 1807 
 1808    ok_v_USER,                          /* {rdonly=1,import=1} */
 1809    ok_v_umask,                      /* {vip=1,nodel=1,posnum=1,i3val="0077"} */
 1810    ok_v_user,                       /* {chain=1} */
 1811 
 1812    ok_v_VISUAL,                     /* {env=1,notempty=1,defval=VAL_VISUAL} */
 1813    ok_b_v15_compat,
 1814    ok_b_verbose,                       /* {vip=1} */
 1815    ok_v_version,                       /* {virt=n_VERSION} */
 1816    ok_v_version_date,                  /* {virt=n_VERSION_DATE} */
 1817    ok_v_version_hexnum,                /* {virt=n_VERSION_HEXNUM,posnum=1} */
 1818    ok_v_version_major,                 /* {virt=n_VERSION_MAJOR,posnum=1} */
 1819    ok_v_version_minor,                 /* {virt=n_VERSION_MINOR,posnum=1} */
 1820    ok_v_version_update,                /* {virt=n_VERSION_UPDATE,posnum=1} */
 1821 
 1822    ok_b_writebackedited
 1823 
 1824 ,  /* Obsolete IMAP related non-sorted */
 1825 ok_b_disconnected,               /* {chain=1} */
 1826 ok_v_imap_auth,                  /* {chain=1} */
 1827 ok_v_imap_cache,
 1828 ok_v_imap_delim,                 /* {chain=1} */
 1829 ok_v_imap_keepalive,             /* {chain=1} */
 1830 ok_v_imap_list_depth,
 1831 ok_b_imap_use_starttls           /* {chain=1} */
 1832 }; /* }}} */
 1833 
 1834 /* Locale-independent character classes */
 1835 enum {
 1836    C_CNTRL        = 1<<0,
 1837    C_BLANK        = 1<<1,
 1838    C_WHITE        = 1<<2,
 1839    C_SPACE        = 1<<3,
 1840    C_PUNCT        = 1<<4,
 1841    C_OCTAL        = 1<<5,
 1842    C_DIGIT        = 1<<6,
 1843    C_UPPER        = 1<<7,
 1844    C_LOWER        = 1<<8
 1845 };
 1846 
 1847 struct str {
 1848    char     *s;      /* the string's content */
 1849    size_t   l;       /* the stings's length */
 1850 };
 1851 
 1852 struct n_string{
 1853    char *s_dat;         /*@ May contain NULs, not automatically terminated */
 1854    ui32_t s_len;        /*@ gth of string */
 1855    ui32_t s_auto : 1;   /* Stored in auto-reclaimed storage? */
 1856    ui32_t s_size : 31;  /* of .s_dat, -1 */
 1857 };
 1858 
 1859 struct n_strlist{
 1860    struct n_strlist *sl_next;
 1861    size_t sl_len;
 1862    char sl_dat[n_VFIELD_SIZE(0)];
 1863 };
 1864 #define n_STRLIST_ALLOC(SZ) /* XXX -> nailfuns.h (and pimp interface) */\
 1865    n_alloc(n_VSTRUCT_SIZEOF(struct n_strlist, sl_dat) + (SZ) +1)
 1866 #define n_STRLIST_AUTOREC_ALLOC(SZ) \
 1867    n_autorec_alloc(n_VSTRUCT_SIZEOF(struct n_strlist, sl_dat) + (SZ) +1)
 1868 #define n_STRLIST_LOFI_ALLOC(SZ) \
 1869    n_lofi_alloc(n_VSTRUCT_SIZEOF(struct n_strlist, sl_dat) + (SZ) +1)
 1870 
 1871 struct bidi_info {
 1872    struct str  bi_start;      /* Start of (possibly) bidirectional text */
 1873    struct str  bi_end;        /* End of ... */
 1874    size_t      bi_pad;        /* No of visual columns to reserve for BIDI pad */
 1875 };
 1876 
 1877 struct n_cmd_arg_desc{
 1878    char cad_name[12];   /* Name of command */
 1879    ui32_t cad_no;       /* Number of entries in cad_ent_flags */
 1880    /* [enum n_cmd_arg_desc_flags,arg-dep] */
 1881    ui32_t cad_ent_flags[n_VFIELD_SIZE(0)][2];
 1882 };
 1883 /* ISO C(99) doesn't allow initialization of "flex array" */
 1884 #define n_CMD_ARG_DESC_SUBCLASS_DEF(CMD,NO,VAR) \
 1885    struct n_cmd_arg_desc_ ## CMD {\
 1886       char cad_name[12];\
 1887       ui32_t cad_no;\
 1888       ui32_t cad_ent_flags[NO][2];\
 1889    } const VAR = { #CMD "\0", NO,
 1890 #define n_CMD_ARG_DESC_SUBCLASS_DEF_END }
 1891 #define n_CMD_ARG_DESC_SUBCLASS_CAST(P) ((struct n_cmd_arg_desc const*)P)
 1892 
 1893 struct n_cmd_arg_ctx{
 1894    struct n_cmd_arg_desc const *cac_desc; /* Input: description of command */
 1895    char const *cac_indat;     /* Input that shall be parsed */
 1896    size_t cac_inlen;          /* Input length (UIZ_MAX: do a strlen()) */
 1897    size_t cac_no;             /* Output: number of parsed arguments */
 1898    struct n_cmd_arg *cac_arg; /* Output: parsed arguments */
 1899    char const *cac_vput;      /* "Output": vput prefix used: varname */
 1900 };
 1901 
 1902 struct n_cmd_arg{/* TODO incomplete, misses getmsglist() */
 1903    struct n_cmd_arg *ca_next;
 1904    char const *ca_indat;   /*[PRIV] Pointer into n_cmd_arg_ctx.cac_indat */
 1905    size_t ca_inlen;        /*[PRIV] of .ca_indat of this arg (not terminated) */
 1906    ui32_t ca_ent_flags[2]; /* Copy of n_cmd_arg_desc.cad_ent_flags[X] */
 1907    ui32_t ca_arg_flags;    /* [Output: _WYSH: copy of parse result flags] */
 1908    ui8_t ca__dummy[4];
 1909    union{
 1910       struct str ca_str;      /* _STRING, _WYSH */
 1911    } ca_arg;               /* Output: parsed result */
 1912 };
 1913 
 1914 struct n_cmd_desc{
 1915    char const *cd_name;    /* Name of command */
 1916    int (*cd_func)(void*);  /* Implementor of command */
 1917    enum n_cmd_arg_flags cd_caflags;
 1918    si16_t cd_msgflag;      /* Required flags of msgs */
 1919    si16_t cd_msgmask;      /* Relevant flags of msgs */
 1920    struct n_cmd_arg_desc const *cd_cadp;
 1921 #ifdef HAVE_DOCSTRINGS
 1922    char const *cd_doc;     /* One line doc for command */
 1923 #endif
 1924 };
 1925 /* Yechh, can't initialize unions */
 1926 #define cd_minargs cd_msgflag /* Minimum argcount for WYSH/WYRA/RAWLIST */
 1927 #define cd_maxargs cd_msgmask /* Max argcount for WYSH/WYRA/RAWLIST */
 1928 
 1929 #ifdef HAVE_COLOUR
 1930 struct n_colour_env{
 1931    struct n_colour_env *ce_last;
 1932    bool_t ce_enabled;   /* Colour enabled on this level */
 1933    ui8_t ce_ctx;        /* enum n_colour_ctx */
 1934    ui8_t ce_ispipe;     /* .ce_outfp known to be a pipe */
 1935    ui8_t ce__pad[5];
 1936    FILE *ce_outfp;
 1937    struct a_colour_map *ce_current; /* Active colour or NULL */
 1938 };
 1939 
 1940 struct n_colour_pen;
 1941 #endif
 1942 
 1943 struct url {
 1944    char const     *url_input;       /* Input as given (really) */
 1945    ui32_t         url_flags;
 1946    ui8_t          url_cproto;       /* enum cproto as given */
 1947    ui8_t          url__pad1[1];
 1948    ui16_t         url_portno;       /* atoi .url_port or default, host endian */
 1949    char const     *url_port;        /* Port (if given) or NULL */
 1950    char           url_proto[14];    /* Communication protocol as 'xy\0//' */
 1951    ui8_t          url_proto_len;    /* Length of .url_proto ('\0' index) */
 1952    ui8_t          url_proto_xlen;   /* .. if '\0' is replaced with ':' */
 1953    struct str     url_user;         /* User, exactly as given / looked up */
 1954    struct str     url_user_enc;     /* User, urlxenc()oded */
 1955    struct str     url_pass;         /* Pass (urlxdec()oded) or NULL */
 1956    /* TODO we don't know whether .url_host is a name or an address.  Us
 1957     * TODO Net::IPAddress::fromString() to check that, then set
 1958     * TODO n_URL_HOST_IS_NAME solely based on THAT!  Until then,
 1959     * TODO n_URL_HOST_IS_NAME ONLY set if n_URL_TLS_MASK and HAVE_GETADDRINFO */
 1960    struct str     url_host;         /* Service hostname TODO we don't know */
 1961    struct str     url_path;         /* Path suffix or NULL */
 1962    /* TODO: url_get_component(url *, enum COMPONENT, str *store) */
 1963    struct str     url_h_p;          /* .url_host[:.url_port] */
 1964    /* .url_user@.url_host
 1965     * Note: for CPROTO_SMTP this may resolve HOST via *smtp-hostname* (->
 1966     * *hostname*)!  (And may later be overwritten according to *from*!) */
 1967    struct str     url_u_h;
 1968    struct str     url_u_h_p;        /* .url_user@.url_host[:.url_port] */
 1969    struct str     url_eu_h_p;       /* .url_user_enc@.url_host[:.url_port] */
 1970    char const     *url_p_u_h_p;     /* .url_proto://.url_u_h_p */
 1971    char const     *url_p_eu_h_p;    /* .url_proto://.url_eu_h_p */
 1972    char const     *url_p_eu_h_p_p;  /* .url_proto://.url_eu_h_p[/.url_path] */
 1973 };
 1974 
 1975 struct ccred {
 1976    enum cproto    cc_cproto;     /* Communication protocol */
 1977    enum authtype  cc_authtype;   /* Desired authentication */
 1978    char const     *cc_auth;      /* Authentication type as string */
 1979    struct str     cc_user;       /* User (urlxdec()oded) or NULL */
 1980    struct str     cc_pass;       /* Password (urlxdec()oded) or NULL */
 1981 };
 1982 
 1983 #ifdef HAVE_DOTLOCK
 1984 struct n_dotlock_info{
 1985    char const *di_file_name;  /* Mailbox to lock */
 1986    char const *di_lock_name;  /* .di_file_name + .lock */
 1987    char const *di_hostname;   /* ..filled in parent (due resolver delays) */
 1988    char const *di_randstr;    /* ..ditto, random string */
 1989    size_t di_pollmsecs;       /* Delay in between locking attempts */
 1990    struct stat *di_stb;
 1991 };
 1992 #endif
 1993 
 1994 struct n_file_type{
 1995    char const *ft_ext_dat;    /* Extension this handles, without first period */
 1996    size_t ft_ext_len;
 1997    char const *ft_load_dat;   /* And the load and save command strings */
 1998    size_t ft_load_len;
 1999    char const *ft_save_dat;
 2000    size_t ft_save_len;
 2001 };
 2002 
 2003 struct n_go_data_ctx{
 2004    /* The memory pool may be inherited from outer context, so we
 2005     * .gdc_mempool may be NE .gdc__mempool_buf */
 2006    void *gdc_mempool;
 2007    void *gdc_ifcond; /* Saved state of conditional stack */
 2008 #ifdef HAVE_COLOUR
 2009    struct n_colour_env *gdc_colour;
 2010    bool_t gdc_colour_active;
 2011    ui8_t gdc__colour_pad[7];
 2012 # define n_COLOUR_IS_ACTIVE() \
 2013    (/*n_go_data->gc_data.gdc_colour != NULL &&*/\
 2014     /*n_go_data->gc_data.gdc_colour->ce_enabled*/ n_go_data->gdc_colour_active)
 2015 #endif
 2016    char gdc__mempool_buf[n_MEMORY_POOL_TYPE_SIZEOF];
 2017 };
 2018 n_MCTA(n_MEMORY_POOL_TYPE_SIZEOF % sizeof(void*) == 0,
 2019    "Inacceptible size of n_go_data_ctx.gdc_mempool")
 2020 
 2021 struct mime_handler {
 2022    enum mime_handler_flags mh_flags;
 2023    struct str  mh_msg;           /* Message describing this command */
 2024    /* XXX union{} the following? */
 2025    char const  *mh_shell_cmd;    /* For MIME_HDL_CMD */
 2026    int         (*mh_ptf)(void);  /* PTF main() for MIME_HDL_PTF */
 2027 };
 2028 
 2029 struct quoteflt {
 2030    FILE        *qf_os;        /* Output stream */
 2031    char const  *qf_pfix;
 2032    ui32_t      qf_pfix_len;   /* Length of prefix: 0: bypass */
 2033    ui32_t      qf_qfold_min;  /* Simple way: wrote prefix? */
 2034    /* TODO quoteflt.qf_nl_last is a hack that i have introduced so that we
 2035     * TODO finally can gracefully place a newline last in the visual display.
 2036     * TODO I.e., for cases where quoteflt shouldn't be used at all ;} */
 2037    bool_t      qf_nl_last;    /* Last thing written/seen was NL */
 2038 #ifndef HAVE_QUOTE_FOLD
 2039    ui8_t       __dummy[7];
 2040 #else
 2041    ui8_t       __dummy[1];
 2042    ui8_t       qf_state;      /* *quote-fold* state machine */
 2043    bool_t      qf_brk_isws;   /* Breakpoint is at WS */
 2044    ui32_t      qf_qfold_max;  /* Otherwise: line lengths */
 2045    ui32_t      qf_wscnt;      /* Whitespace count */
 2046    char const *qf_quote_chars; /* *quote-chars* */
 2047    ui32_t      qf_brkl;       /* Breakpoint */
 2048    ui32_t      qf_brkw;       /* Visual width, breakpoint */
 2049    ui32_t      qf_datw;       /* Current visual output line width */
 2050    struct str  qf_dat;        /* Current visual output line */
 2051    struct str  qf_currq;      /* Current quote, compressed */
 2052    mbstate_t   qf_mbps[2];
 2053 #endif
 2054 };
 2055 
 2056 #ifdef HAVE_FILTER_HTML_TAGSOUP
 2057 struct htmlflt {
 2058    FILE        *hf_os;        /* Output stream */
 2059    ui32_t      hf_flags;
 2060    ui32_t      hf_lmax;       /* Maximum byte +1 in .hf_line/4 */
 2061    ui32_t      hf_len;        /* Current bytes in .hf_line */
 2062    ui32_t      hf_last_ws;    /* Last whitespace on line (fold purposes) */
 2063    ui32_t      hf_mboff;      /* Last offset for "mbtowc" */
 2064    ui32_t      hf_mbwidth;    /* We count characters not bytes if possible */
 2065    char        *hf_line;      /* Output line buffer - MUST be last field! */
 2066    si32_t      hf_href_dist;  /* Count of lines since last HREF flush */
 2067    ui32_t      hf_href_no;    /* HREF sequence number */
 2068    struct htmlflt_href *hf_hrefs;
 2069    struct htmlflt_tag const *hf_ign_tag; /* Tag that will end ignore mode */
 2070    char        *hf_curr;      /* Current cursor into .hf_bdat */
 2071    char        *hf_bmax;      /* Maximum byte in .hf_bdat +1 */
 2072    char        *hf_bdat;      /* (Temporary) Tag content data storage */
 2073 };
 2074 #endif
 2075 
 2076 struct search_expr {
 2077    /* XXX Type of search should not be evaluated but be enum */
 2078    bool_t ss_field_exists; /* Only check whether field spec. exists */
 2079    bool_t ss_skin;         /* Shall work on (skin()ned) addresses */
 2080    ui8_t ss__pad[6];
 2081    char const *ss_field;   /* Field spec. where to search (not always used) */
 2082    char const *ss_body;    /* Field body search expression */
 2083 #ifdef HAVE_REGEX
 2084    regex_t *ss_fieldre;    /* Could be instead of .ss_field */
 2085    regex_t *ss_bodyre;     /* Ditto, .ss_body */
 2086    regex_t ss__fieldre_buf;
 2087    regex_t ss__bodyre_buf;
 2088 #endif
 2089 };
 2090 
 2091 /* This is somewhat temporary for pre v15 */
 2092 struct n_sigman{
 2093    ui32_t sm_flags;           /* enum n_sigman_flags */
 2094    int sm_signo;
 2095    struct n_sigman *sm_outer;
 2096    sighandler_type sm_ohup;
 2097    sighandler_type sm_oint;
 2098    sighandler_type sm_oquit;
 2099    sighandler_type sm_oterm;
 2100    sighandler_type sm_opipe;
 2101    sigjmp_buf sm_jump;
 2102 };
 2103 
 2104 struct n_timespec{
 2105    si64_t ts_sec;
 2106    siz_t ts_nsec;
 2107 };
 2108 
 2109 struct termios_state {
 2110    struct termios ts_tios;
 2111    char        *ts_linebuf;
 2112    size_t      ts_linesize;
 2113    bool_t      ts_needs_reset;
 2114 };
 2115 
 2116 #define termios_state_reset() \
 2117 do {\
 2118    if (termios_state.ts_needs_reset) {\
 2119       tcsetattr(STDIN_FILENO, TCSADRAIN, &termios_state.ts_tios);\
 2120       termios_state.ts_needs_reset = FAL0;\
 2121    }\
 2122 } while (0)
 2123 
 2124 #ifdef n_HAVE_TCAP
 2125 struct n_termcap_value{
 2126    enum n_termcap_captype tv_captype;
 2127    ui8_t tv__dummy[4];
 2128    union n_termcap_value_data{
 2129       bool_t tvd_bool;
 2130       ui32_t tvd_numeric;
 2131       char const *tvd_string;
 2132    } tv_data;
 2133 };
 2134 #endif
 2135 
 2136 struct n_visual_info_ctx{
 2137    char const *vic_indat;  /*I Input data */
 2138    size_t vic_inlen;       /*I If UIZ_MAX, strlen(.vic_indat) */
 2139    char const *vic_oudat;  /*O remains */
 2140    size_t vic_oulen;
 2141    size_t vic_chars_seen;  /*O number of characters processed */
 2142    size_t vic_bytes_seen;  /*O number of bytes passed */
 2143    size_t vic_vi_width;    /*[O] visual width of the entire range */
 2144    wc_t *vic_woudat;       /*[O] if so requested */
 2145    size_t vic_woulen;      /*[O] entries in .vic_woudat, if used */
 2146    wc_t vic_waccu;         /*O The last wchar_t/char processed (if any) */
 2147    enum n_visual_info_flags vic_flags; /*O Copy of parse flags */
 2148    /* TODO bidi */
 2149 #ifdef HAVE_C90AMEND1
 2150    mbstate_t *vic_mbstate; /*IO .vic_mbs_def used if NULL */
 2151    mbstate_t vic_mbs_def;
 2152 #endif
 2153 };
 2154 
 2155 struct time_current { /* TODO si64_t, etc. */
 2156    time_t      tc_time;
 2157    struct tm   tc_gm;
 2158    struct tm   tc_local;
 2159    char        tc_ctime[32];
 2160 };
 2161 
 2162 struct sock {                 /* data associated with a socket */
 2163    int         s_fd;          /* file descriptor */
 2164 #ifdef HAVE_SSL
 2165    int         s_use_ssl;     /* SSL is used */
 2166 # ifdef HAVE_XSSL
 2167    void        *s_ssl;        /* SSL object */
 2168 # endif
 2169 #endif
 2170    char        *s_wbuf;       /* for buffered writes */
 2171    int         s_wbufsize;    /* allocated size of s_buf */
 2172    int         s_wbufpos;     /* position of first empty data byte */
 2173    char        *s_rbufptr;    /* read pointer to s_rbuf */
 2174    int         s_rsz;         /* size of last read in s_rbuf */
 2175    char const  *s_desc;       /* description of error messages */
 2176    void        (*s_onclose)(void);     /* execute on close */
 2177    char        s_rbuf[LINESIZE + 1];   /* for buffered reads */
 2178 };
 2179 
 2180 struct sockconn {
 2181    struct url     sc_url;
 2182    struct ccred   sc_cred;
 2183    struct sock    sc_sock;
 2184 };
 2185 
 2186 struct mailbox {
 2187    enum {
 2188       MB_NONE     = 000,      /* no reply expected */
 2189       MB_COMD     = 001,      /* command reply expected */
 2190       MB_MULT     = 002,      /* multiline reply expected */
 2191       MB_PREAUTH  = 004,      /* not in authenticated state */
 2192       MB_BYE      = 010,      /* may accept a BYE state */
 2193       MB_FROM__WARNED = 1<<4  /* MBOX with invalid from seen & logged */
 2194    }           mb_active;
 2195    FILE        *mb_itf;       /* temp file with messages, read open */
 2196    FILE        *mb_otf;       /* same, write open */
 2197    char        *mb_sorted;    /* sort method */
 2198    enum {
 2199       MB_VOID,    /* no type (e. g. connection failed) */
 2200       MB_FILE,    /* local file */
 2201       MB_POP3,    /* POP3 mailbox */
 2202 MB_IMAP,          /* IMAP mailbox */
 2203 MB_CACHE,         /* IMAP cache */
 2204       MB_MAILDIR  /* maildir folder */
 2205    }           mb_type;       /* type of mailbox */
 2206    enum {
 2207       MB_DELE = 01,  /* may delete messages in mailbox */
 2208       MB_EDIT = 02   /* may edit messages in mailbox */
 2209    }           mb_perm;
 2210    int mb_threaded;           /* mailbox has been threaded */
 2211 #ifdef HAVE_IMAP
 2212    enum mbflags {
 2213       MB_NOFLAGS  = 000,
 2214       MB_UIDPLUS  = 001 /* supports IMAP UIDPLUS */
 2215    }           mb_flags;
 2216    unsigned long  mb_uidvalidity;   /* IMAP unique identifier validity */
 2217    char        *mb_imap_account;    /* name of current IMAP account */
 2218    char        *mb_imap_pass;       /* xxx v15-compat URL workaround */
 2219    char        *mb_imap_mailbox;    /* name of current IMAP mailbox */
 2220    char        *mb_cache_directory; /* name of cache directory */
 2221    char mb_imap_delim[8];     /* Directory separator(s), [0] += replacer */
 2222 #endif
 2223    struct sock mb_sock;       /* socket structure */
 2224 };
 2225 
 2226 enum needspec {
 2227    NEED_UNSPEC,      /* unspecified need, don't fetch */
 2228    NEED_HEADER,      /* need the header of a message */
 2229    NEED_BODY         /* need header and body of a message */
 2230 };
 2231 
 2232 enum content_info {
 2233    CI_NOTHING,                /* Nothing downloaded yet */
 2234    CI_HAVE_HEADER = 1u<<0,    /* Header is downloaded */
 2235    CI_HAVE_BODY = 1u<<1,      /* Entire message is downloaded */
 2236    CI_HAVE_MASK = CI_HAVE_HEADER | CI_HAVE_BODY,
 2237    CI_MIME_ERRORS = 1u<<2,    /* Defective MIME structure */
 2238    CI_EXPANDED = 1u<<3,       /* Container part (pk7m) exploded into X */
 2239    CI_SIGNED = 1u<<4,         /* Has a signature.. */
 2240    CI_SIGNED_OK = 1u<<5,      /* ..verified ok.. */
 2241    CI_SIGNED_BAD = 1u<<6,     /* ..verified bad (missing key).. */
 2242    CI_ENCRYPTED = 1u<<7,      /* Is encrypted.. */
 2243    CI_ENCRYPTED_OK = 1u<<8,   /* ..decryption possible/ok.. */
 2244    CI_ENCRYPTED_BAD = 1u<<9   /* ..not possible/ok */
 2245 };
 2246 
 2247 /* Note: flags that are used in obs-imap-cache.c may not change */
 2248 enum mflag {
 2249    MUSED = 1u<<0,       /* entry is used, but this bit isn't */
 2250    MDELETED = 1u<<1,    /* entry has been deleted */
 2251    MSAVED = 1u<<2,      /* entry has been saved */
 2252    MTOUCH = 1u<<3,      /* entry has been noticed */
 2253    MPRESERVE = 1u<<4,   /* keep entry in sys mailbox */
 2254    MMARK = 1u<<5,       /* message is marked! */
 2255    MODIFY = 1u<<6,      /* message has been modified */
 2256    MNEW = 1u<<7,        /* message has never been seen */
 2257    MREAD = 1u<<8,       /* message has been read sometime. */
 2258    MSTATUS = 1u<<9,     /* message status has changed */
 2259    MBOX = 1u<<10,       /* Send this to mbox, regardless */
 2260    MNOFROM = 1u<<11,    /* no From line */
 2261    MHIDDEN = 1u<<12,    /* message is hidden to user */
 2262 MFULLYCACHED = 1u<<13,  /* IMAP cached */
 2263    MBOXED = 1u<<14,     /* message has been sent to mbox */
 2264 MUNLINKED = 1u<<15,     /* Unlinked from IMAP cache */
 2265    MNEWEST = 1u<<16,    /* message is very new (newmail) */
 2266    MFLAG = 1u<<17,      /* message has been flagged recently */
 2267    MUNFLAG = 1u<<18,    /* message has been unflagged */
 2268    MFLAGGED = 1u<<19,   /* message is `flagged' */
 2269    MANSWER = 1u<<20,    /* message has been answered recently */
 2270    MUNANSWER = 1u<<21,  /* message has been unanswered */
 2271    MANSWERED = 1u<<22,  /* message is `answered' */
 2272    MDRAFT = 1u<<23,     /* message has been drafted recently */
 2273    MUNDRAFT = 1u<<24,   /* message has been undrafted */
 2274    MDRAFTED = 1u<<25,   /* message is marked as `draft' */
 2275    MOLDMARK = 1u<<26,   /* messages was marked previously */
 2276    MSPAM = 1u<<27,      /* message is classified as spam */
 2277    MSPAMUNSURE = 1u<<28  /* message may be spam, but it is unsure */
 2278 };
 2279 #define MMNORM          (MDELETED | MSAVED | MHIDDEN)
 2280 #define MMNDEL          (MDELETED | MHIDDEN)
 2281 
 2282 #define visible(mp)     (((mp)->m_flag & MMNDEL) == 0)
 2283 
 2284 struct mimepart {
 2285    enum mflag  m_flag;
 2286    enum content_info m_content_info;
 2287 #ifdef HAVE_SPAM
 2288    ui32_t      m_spamscore;   /* Spam score as int, 24:8 bits */
 2289 #endif
 2290    int         m_block;       /* block number of this part */
 2291    size_t      m_offset;      /* offset in block of part */
 2292    size_t      m_size;        /* Bytes in the part */
 2293    size_t      m_xsize;       /* Bytes in the full part */
 2294    long        m_lines;       /* Lines in the message: write format! */
 2295    long        m_xlines;      /* Lines in the full message; ditto */
 2296    time_t      m_time;        /* time the message was sent */
 2297    char const  *m_from;       /* message sender */
 2298    struct mimepart *m_nextpart;     /* next part at same level */
 2299    struct mimepart *m_multipart;    /* parts of multipart */
 2300    struct mimepart *m_parent;       /* enclosing multipart part */
 2301    char const  *m_ct_type;          /* content-type */
 2302    char const  *m_ct_type_plain;    /* content-type without specs */
 2303    char const  *m_ct_type_usr_ovwr; /* Forcefully overwritten one */
 2304    char const  *m_charset;
 2305    char const  *m_ct_enc;           /* Content-Transfer-Encoding */
 2306    enum mimecontent m_mimecontent;  /* ..in enum */
 2307    enum mime_enc m_mime_enc;        /* ..in enum */
 2308    char        *m_partstring;       /* Part level string */
 2309    char        *m_filename;         /* ..of attachment */
 2310    char const  *m_content_description;
 2311    char const *m_external_body_url; /* message/external-body: access-type=URL */
 2312    struct mime_handler *m_handler;  /* MIME handler if yet classified */
 2313 };
 2314 
 2315 struct message {
 2316    enum mflag  m_flag;        /* flags */
 2317    enum content_info m_content_info;
 2318 #ifdef HAVE_SPAM
 2319    ui32_t      m_spamscore;   /* Spam score as int, 24:8 bits */
 2320 #endif
 2321    int         m_block;       /* block number of this message */
 2322    size_t      m_offset;      /* offset in block of message */
 2323    size_t      m_size;        /* Bytes in the message */
 2324    size_t      m_xsize;       /* Bytes in the full message */
 2325    long        m_lines;       /* Lines in the message */
 2326    long        m_xlines;      /* Lines in the full message */
 2327    time_t      m_time;        /* time the message was sent */
 2328    time_t      m_date;        /* time in the 'Date' field */
 2329    unsigned    m_idhash;      /* hash on Message-ID for threads */
 2330    struct message *m_child;   /* first child of this message */
 2331    struct message *m_younger; /* younger brother of this message */
 2332    struct message *m_elder;   /* elder brother of this message */
 2333    struct message *m_parent;  /* parent of this message */
 2334    unsigned    m_level;       /* thread level of message */
 2335    long        m_threadpos;   /* position in threaded display */
 2336 #ifdef HAVE_IMAP
 2337    unsigned long m_uid;       /* IMAP unique identifier */
 2338 #endif
 2339    char const  *m_maildir_file;  /* original maildir file of msg */
 2340    ui32_t      m_maildir_hash;   /* hash of file name in maildir sub */
 2341    int         m_collapsed;      /* collapsed thread information */
 2342 };
 2343 
 2344 /* Given a file address, determine the block number it represents */
 2345 #define mailx_blockof(off)                ((int) ((off) / 4096))
 2346 #define mailx_offsetof(off)               ((int) ((off) % 4096))
 2347 #define mailx_positionof(block, offset)   ((off_t)(block) * 4096 + (offset))
 2348 
 2349 enum gfield{ /* TODO -> enum m_grab_head, m_GH_xy */
 2350    GNONE,
 2351    GTO = 1u<<0,         /* Grab To: line */
 2352    GSUBJECT = 1u<<1,    /* Likewise, Subject: line */
 2353    GCC = 1u<<2,         /* And the Cc: line */
 2354    GBCC = 1u<<3,        /* And also the Bcc: line */
 2355 
 2356    GNL = 1u<<4,         /* Print blank line after */
 2357    GDEL = 1u<<5,        /* Entity removed from list */
 2358    GCOMMA = 1u<<6,      /* detract() puts in commas */
 2359    GUA = 1u<<7,         /* User-Agent field */
 2360    GMIME = 1u<<8,       /* MIME 1.0 fields */
 2361    GMSGID = 1u<<9,      /* a Message-ID */
 2362    GNAMEONLY = 1u<<10,  /* detract() does NOT use fullnames */
 2363 
 2364    GIDENT = 1u<<11,     /* From:, Reply-To:, MFT: (user headers) */
 2365    GREF = 1u<<12,       /* References:, In-Reply-To:, (Message-ID:) */
 2366    GDATE = 1u<<13,      /* Date: field */
 2367    GFULL = 1u<<14,      /* Include full names, comments etc. */
 2368    GSKIN = 1u<<15,      /* Skin names */
 2369    GEXTRA = 1u<<16,     /* Extra fields (mostly like GIDENT XXX) */
 2370    GFILES = 1u<<17,     /* Include filename and pipe addresses */
 2371    GFULLEXTRA = 1u<<18  /* Only with GFULL: GFULL less address */
 2372 };
 2373 #define GMASK           (GTO | GSUBJECT | GCC | GBCC)
 2374 
 2375 enum header_flags {
 2376    HF_NONE        = 0,
 2377    HF_LIST_REPLY  = 1<< 0,
 2378    HF_MFT_SENDER  = 1<< 1,    /* Add ourselves to Mail-Followup-To: */
 2379    HF_RECIPIENT_RECORD = 1<<10, /* Save message in file named after rec. */
 2380    HF__NEXT_SHIFT = 11
 2381 };
 2382 
 2383 /* Structure used to pass about the current state of a message (header) */
 2384 struct n_header_field{
 2385    struct n_header_field *hf_next;
 2386    ui32_t hf_nl;              /* Field-name length */
 2387    ui32_t hf_bl;              /* Field-body length*/
 2388    char hf_dat[n_VFIELD_SIZE(0)];
 2389 };
 2390 
 2391 struct header {
 2392    ui32_t      h_flags;       /* enum header_flags bits */
 2393    ui32_t      h_dummy;
 2394    char        *h_subject;    /* Subject string */
 2395    char const  *h_charset;    /* preferred charset */
 2396    struct name *h_from;       /* overridden "From:" field */
 2397    struct name *h_sender;     /* overridden "Sender:" field */
 2398    struct name *h_to;         /* Dynamic "To:" string */
 2399    struct name *h_cc;         /* Carbon copies string */
 2400    struct name *h_bcc;        /* Blind carbon copies */
 2401    struct name *h_ref;        /* References (possibly overridden) */
 2402    struct attachment *h_attach; /* MIME attachments */
 2403    struct name *h_reply_to;   /* overridden "Reply-To:" field */
 2404    struct name *h_message_id; /* overridden "Message-ID:" field */
 2405    struct name *h_in_reply_to;/* overridden "In-Reply-To:" field */
 2406    struct name *h_mft;        /* Mail-Followup-To */
 2407    char const  *h_list_post;  /* Address from List-Post:, for `Lreply' */
 2408    struct n_header_field *h_user_headers;
 2409    struct n_header_field *h_custom_headers; /* (Cached result) */
 2410    /* Raw/original versions of the header(s). If any */
 2411    char const *h_mailx_command;
 2412    struct name *h_mailx_raw_to;
 2413    struct name *h_mailx_raw_cc;
 2414    struct name *h_mailx_raw_bcc;
 2415    struct name *h_mailx_orig_from;
 2416    struct name *h_mailx_orig_to;
 2417    struct name *h_mailx_orig_cc;
 2418    struct name *h_mailx_orig_bcc;
 2419 };
 2420 
 2421 /* Handling of namelist nodes used in processing the recipients of mail and
 2422  * aliases, inspection of mail-addresses and all that kind of stuff */
 2423 enum nameflags {
 2424    NAME_SKINNED = 1u<<0,            /* Is actually skin()ned */
 2425    NAME_IDNA = 1u<<1,               /* IDNA was applied */
 2426    NAME_NAME_SALLOC = 1u<<2,        /* .n_name is doped */
 2427 
 2428    NAME_ADDRSPEC_ISFILE = 1u<<3,    /* ..is a file path */
 2429    NAME_ADDRSPEC_ISPIPE = 1u<<4,    /* ..is a command for piping */
 2430    NAME_ADDRSPEC_ISFILEORPIPE = NAME_ADDRSPEC_ISFILE | NAME_ADDRSPEC_ISPIPE,
 2431    NAME_ADDRSPEC_ISNAME = 1u<<5,    /* ..is an alias name */
 2432    NAME_ADDRSPEC_ISADDR = 1u<<6,    /* ..is a mail network address.. */
 2433    NAME_ADDRSPEC_WITHOUT_DOMAIN = 1u<<7, /* ..but without domain name */
 2434 
 2435    NAME_ADDRSPEC_ERR_EMPTY = 1u<<9, /* An empty string (or NULL) */
 2436    NAME_ADDRSPEC_ERR_ATSEQ = 1u<<10, /* Weird @ sequence */
 2437    NAME_ADDRSPEC_ERR_CHAR = 1u<<11, /* Invalid character */
 2438    NAME_ADDRSPEC_ERR_IDNA = 1u<<12, /* IDNA convertion failed */
 2439    NAME_ADDRSPEC_ERR_NAME = 1u<<13, /* Alias with invalid content */
 2440    NAME_ADDRSPEC_INVALID = NAME_ADDRSPEC_ERR_EMPTY |
 2441          NAME_ADDRSPEC_ERR_ATSEQ | NAME_ADDRSPEC_ERR_CHAR |
 2442          NAME_ADDRSPEC_ERR_IDNA | NAME_ADDRSPEC_ERR_NAME,
 2443 
 2444    /* Error storage (we must fit in 31-bit) */
 2445    _NAME_SHIFTWC = 14,
 2446    _NAME_MAXWC = 0x1FFFF,
 2447    _NAME_MASKWC = _NAME_MAXWC << _NAME_SHIFTWC
 2448    /* Bit 31 (32) == SI32_MIN temporarily used */
 2449 };
 2450 
 2451 /* In the !_ERR_EMPTY case, the failing character can be queried */
 2452 #define NAME_ADDRSPEC_ERR_GETWC(F)  \
 2453    ((((unsigned int)(F) & _NAME_MASKWC) >> _NAME_SHIFTWC) & _NAME_MAXWC)
 2454 #define NAME_ADDRSPEC_ERR_SET(F, E, WC) \
 2455 do {\
 2456    (F) = ((F) & ~(NAME_ADDRSPEC_INVALID | _NAME_MASKWC)) |\
 2457          (E) | (((unsigned int)(WC) & _NAME_MAXWC) << _NAME_SHIFTWC);\
 2458 } while (0)
 2459 
 2460 struct name{
 2461    struct name *n_flink;   /* Forward link in list. */
 2462    struct name *n_blink;   /* Backward list link */
 2463    enum gfield n_type;     /* From which list it came */
 2464    ui32_t n_flags;         /* enum nameflags */
 2465    char *n_name;           /* This fella's address */
 2466    char *n_fullname;       /* Ditto, unless GFULL including comment */
 2467    char *n_fullextra;      /* GFULL, without address */
 2468 };
 2469 
 2470 struct n_addrguts{
 2471    /* Input string as given (maybe replaced with a fixed one!) */
 2472    char const *ag_input;
 2473    size_t ag_ilen;            /* strlen() of input */
 2474    size_t ag_iaddr_start;     /* Start of *addr-spec* in .ag_input */
 2475    size_t ag_iaddr_aend;      /* ..and one past its end */
 2476    char *ag_skinned;          /* Output (alloced if !=.ag_input) */
 2477    size_t ag_slen;            /* strlen() of .ag_skinned */
 2478    size_t ag_sdom_start;      /* Start of domain in .ag_skinned, */
 2479    enum nameflags ag_n_flags; /* enum nameflags of .ag_skinned */
 2480 };
 2481 
 2482 /* MIME attachments */
 2483 enum attach_conv {
 2484    AC_DEFAULT,       /* _get_lc() -> _iter_*() */
 2485    AC_FIX_INCS,      /* "charset=".a_input_charset (nocnv) */
 2486    AC_TMPFILE        /* attachment.a_tmpf is converted */
 2487 };
 2488 
 2489 enum n_attach_error{
 2490    n_ATTACH_ERR_NONE,
 2491    n_ATTACH_ERR_FILE_OPEN,
 2492    n_ATTACH_ERR_ICONV_FAILED,
 2493    n_ATTACH_ERR_ICONV_NAVAIL,
 2494    n_ATTACH_ERR_OTHER
 2495 };
 2496 
 2497 struct attachment {
 2498    struct attachment *a_flink; /* Forward link in list. */
 2499    struct attachment *a_blink; /* Backward list link */
 2500    char const  *a_path_user;  /* Path as given (maybe including iconv spec) */
 2501    char const  *a_path;       /* Path as opened */
 2502    char const  *a_path_bname; /* Basename of path as opened */
 2503    char const  *a_name;       /* File name to be stored (EQ a_path_bname) */
 2504    char const  *a_content_type;  /* content type */
 2505    char const  *a_content_disposition; /* content disposition */
 2506    struct name *a_content_id; /* content id */
 2507    char const  *a_content_description; /* content description */
 2508    char const  *a_input_charset; /* Interpretation depends on .a_conv */
 2509    char const  *a_charset;    /* ... */
 2510    FILE        *a_tmpf;       /* If AC_TMPFILE */
 2511    enum attach_conv a_conv;   /* User chosen conversion */
 2512    int         a_msgno;       /* message number */
 2513 };
 2514 
 2515 struct sendbundle {
 2516    struct header  *sb_hp;
 2517    struct name    *sb_to;
 2518    FILE           *sb_input;
 2519    struct str     sb_signer;  /* USER@HOST for signing+ */
 2520    struct url     sb_url;
 2521    struct ccred   sb_ccred;
 2522 };
 2523 
 2524 /* For saving the current directory and later returning */
 2525 struct cw {
 2526 #ifdef HAVE_FCHDIR
 2527    int         cw_fd;
 2528 #else
 2529    char        cw_wd[PATH_MAX];
 2530 #endif
 2531 };
 2532 
 2533 /*
 2534  * Global variable declarations
 2535  *
 2536  * These become instantiated in main.c.
 2537  */
 2538 
 2539 #undef VL
 2540 #ifdef n_MAIN_SOURCE
 2541 # ifndef HAVE_AMALGAMATION
 2542 #  define VL
 2543 # else
 2544 #  define VL static
 2545 # endif
 2546 #else
 2547 # define VL extern
 2548 #endif
 2549 
 2550 #ifndef HAVE_AMALGAMATION
 2551 VL char const n_month_names[12 + 1][4];
 2552 VL char const n_weekday_names[7 + 1][4];
 2553 
 2554 VL char const n_uagent[sizeof VAL_UAGENT];
 2555 VL char const n_error[sizeof n_ERROR];
 2556 VL char const n_path_devnull[sizeof n_PATH_DEVNULL];
 2557 VL char const n_reproducible_name[sizeof "reproducible_build"];
 2558 VL char const n_unirepl[sizeof n_UNIREPL];
 2559 VL char const n_empty[1];
 2560 VL char const n_0[2];
 2561 VL char const n_1[2];
 2562 VL char const n_m1[3];     /* -1 */
 2563 VL char const n_qm[2];     /* Question-mark ? */
 2564 VL char const n_em[2];     /* Exclamation-mark ! */
 2565 VL char const n_star[2];   /* Asterisk * */
 2566 VL char const n_at[2];     /* Commercial at @ */
 2567 VL char const n_ns[2];     /* Number sign # */
 2568 VL ui16_t const n_class_char[1 + 0x7F];
 2569 #endif
 2570 
 2571 VL FILE *n_stdin;
 2572 VL FILE *n_stdout;
 2573 VL FILE *n_stderr;
 2574 VL FILE *n_tty_fp;               /* Our terminal output TODO input channel */
 2575 VL void *n_readctl_overlay;      /* `readctl' overlay (see c_readctl()) */
 2576 
 2577 VL ui32_t n_mb_cur_max;          /* Value of MB_CUR_MAX */
 2578 VL ui32_t n_realscreenheight;    /* The real screen height */
 2579 VL ui32_t n_scrnwidth;           /* Screen width/guess; also n_SCRNWIDTH_LIST */
 2580 VL ui32_t n_scrnheight;          /* Screen height/guess (for header summary+) */
 2581 
 2582 VL char const *n_progname;       /* Our name */
 2583 
 2584 VL gid_t n_group_id;             /* getgid() and getuid() */
 2585 VL uid_t n_user_id;
 2586 VL pid_t n_pid;                  /* getpid() (lazy initialized) */
 2587 
 2588 VL int n_exit_status;            /* Program exit status TODO long term: ex_no */
 2589 VL ui32_t n_poption;             /* Bits of enum n_program_option */
 2590 VL struct n_header_field *n_poption_arg_C; /* -C custom header list */
 2591 VL char const *n_poption_arg_Mm; /* Argument for -[Mm] aka n_PO_[Mm]_FLAG */
 2592 VL struct name *n_poption_arg_r; /* Argument to -r option */
 2593 VL char const **n_smopts;        /* MTA options from command line */
 2594 VL size_t n_smopts_cnt;          /* Entries in n_smopts */
 2595 
 2596 /* The current execution data context */
 2597 VL struct n_go_data_ctx *n_go_data;
 2598 VL ui32_t n_psonce;              /* Bits of enum n_program_state_once */
 2599 VL ui32_t n_pstate;              /* Bits of enum n_program_state */
 2600 /* TODO "cmd_tab.h ARG_EM set"-storage (n_[01..]) as long as we don't have a
 2601  * TODO struct CmdCtx where each command has its own ARGC/ARGV, errno and exit
 2602  * TODO status and may-place-in-history bit, need to manage a global bypass.. */
 2603 VL si32_t n_pstate_err_no;       /* What backs $! n_ERR_* TODO ..HACK */
 2604 VL si32_t n_pstate_ex_no;        /* What backs $? n_EX_* TODO ..HACK ->64-bit */
 2605 #define n_err_no errno           /* Don't use errno directly, for later XXX */
 2606 VL si32_t n_iconv_err_no;        /* TODO HACK: part of CTX to not get lost */
 2607 
 2608 /* XXX stylish sorting */
 2609 VL int            msgCount;            /* Count of messages read in */
 2610 VL struct mailbox mb;                  /* Current mailbox */
 2611 VL char           mailname[PATH_MAX];  /* Name of current file TODO URL/object*/
 2612 VL char           displayname[80 - 16]; /* Prettyfied for display TODO URL/obj*/
 2613 VL char           prevfile[PATH_MAX];  /* Name of previous file TODO URL/obj */
 2614 VL off_t          mailsize;            /* Size of system mailbox */
 2615 VL struct message *dot;                /* Pointer to current message */
 2616 VL struct message *prevdot;            /* Previous current message */
 2617 VL struct message *message;            /* The actual message structure */
 2618 VL struct message *threadroot;         /* first threaded message */
 2619 VL int            *n_msgvec;           /* Folder setmsize(), list.c res. store*/
 2620 #ifdef HAVE_IMAP
 2621 VL int            imap_created_mailbox; /* hack to get feedback from imap */
 2622 #endif
 2623 
 2624 VL struct n_header_field *n_customhdr_list; /* *customhdr* list */
 2625 
 2626 VL struct time_current  time_current;  /* time(3); send: mail1() XXXcarrier */
 2627 VL struct termios_state termios_state; /* getpassword(); see commands().. */
 2628 
 2629 #ifdef HAVE_SSL
 2630 VL enum ssl_verify_level   ssl_verify_level; /* SSL verification level */
 2631 #endif
 2632 
 2633 #ifdef HAVE_ICONV
 2634 VL iconv_t     iconvd;
 2635 #endif
 2636 
 2637 VL volatile int interrupts; /* TODO rid! */
 2638 VL sighandler_type dflpipe;
 2639 
 2640 /*
 2641  * Finally, let's include the function prototypes XXX embed
 2642  */
 2643 
 2644 #ifndef n_PRIVSEP_SOURCE
 2645 # include "nailfuns.h"
 2646 #endif
 2647 
 2648 #endif /* n_NAIL_H */
 2649 /* s-it-mode */