"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.11/nail.h" (8 Aug 2018, 108757 Bytes) of package /linux/misc/s-nail-14.9.11.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.10_vs_14.9.11.

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