"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.10/nail.h" (25 Mar 2018, 103440 Bytes) of package /linux/misc/s-nail-14.9.10.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.9_vs_14.9.10.

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