2 * S-nail - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 Steffen "Daode" Nurpmeso.
8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * Mail -- a mail program
43 * Author: Kurt Shoens (UCB) March 25, 1978
46 #if !defined (NI_MAXHOST) || (NI_MAXHOST) < 1025
48 #define NI_MAXHOST 1025
51 #define APPEND /* New mail goes to end of mailbox */
53 /* Is *C* a quoting character (for *quote-fold* compression) */
54 #define ISQUOTE(C) ((C) == '>' || (C) == '|')
56 #define ESCAPE '~' /* Default escape for sending */
59 #define MAXPATHLEN PATH_MAX
61 #define MAXPATHLEN 1024
65 #define PATHSIZE MAXPATHLEN /* Size of pathnames throughout */
67 #define HSHSIZE 59 /* Hash size for aliases and vars */
68 #if BUFSIZ > 2560 /* TODO simply use BUFSIZ? */
69 # define LINESIZE BUFSIZ /* max readable line width */
71 # define LINESIZE 2560
73 #define STRINGSIZE ((unsigned) 128)/* Dynamic allocation units */
74 #define MAXARGC 1024 /* Maximum list of raw strings */
75 #define MAXEXP 25 /* Maximum expansion of aliases */
80 # define tr(c, d) catgets(catd, CATSET, c, d)
82 # define catgets(a, b, c, d) (d)
86 typedef void (*sighandler_type
)(int);
94 MIME_NONE
, /* message is not in MIME format */
95 MIME_BIN
, /* message is in binary encoding */
96 MIME_8B
, /* message is in 8bit encoding */
97 MIME_7B
, /* message is in 7bit encoding */
98 MIME_QP
, /* message is quoted-printable */
99 MIME_B64
/* message is in base64 encoding */
103 CONV_NONE
, /* no conversion */
104 CONV_7BIT
, /* no conversion, is 7bit */
105 CONV_FROMQP
, /* convert from quoted-printable */
106 CONV_TOQP
, /* convert to quoted-printable */
107 CONV_8BIT
, /* convert to 8bit (iconv) */
108 CONV_FROMB64
, /* convert from base64 */
109 CONV_FROMB64_T
, /* convert from base64/text */
110 CONV_TOB64
, /* convert to base64 */
111 CONV_FROMHDR
, /* convert from RFC1522 format */
112 CONV_TOHDR
, /* convert to RFC1522 format */
113 CONV_TOHDR_A
/* convert addresses for header */
117 SEND_MBOX
, /* no conversion to perform */
118 SEND_RFC822
, /* no conversion, no From_ line */
119 SEND_TODISP
, /* convert to displayable form */
120 SEND_TODISP_ALL
, /* same, include all MIME parts */
121 SEND_SHOW
, /* convert to 'show' command form */
122 SEND_TOSRCH
, /* convert for IMAP SEARCH */
123 SEND_TOFLTR
, /* convert for junk mail filtering */
124 SEND_TOFILE
, /* convert for saving body to a file */
125 SEND_TOPIPE
, /* convert for pipe-content/subc. */
126 SEND_QUOTE
, /* convert for quoting */
127 SEND_QUOTE_ALL
, /* same, include all MIME parts */
128 SEND_DECRYPT
/* decrypt */
132 MIME_UNKNOWN
, /* unknown content */
133 MIME_SUBHDR
, /* inside a multipart subheader */
134 MIME_822
, /* message/rfc822 content */
135 MIME_MESSAGE
, /* other message/ content */
136 MIME_TEXT_PLAIN
, /* text/plain content */
137 MIME_TEXT_HTML
, /* text/html content */
138 MIME_TEXT
, /* other text/ content */
139 MIME_ALTERNATIVE
, /* multipart/alternative content */
140 MIME_DIGEST
, /* multipart/digest content */
141 MIME_MULTI
, /* other multipart/ content */
142 MIME_PKCS7
, /* PKCS7 content */
143 MIME_DISCARD
/* content is discarded */
147 MIME_CLEAN
= 000, /* plain RFC 2822 message */
148 MIME_HIGHBIT
= 001, /* characters >= 0200 */
149 MIME_LONGLINES
= 002, /* has lines too long for RFC 2822 */
150 MIME_CTRLCHAR
= 004, /* contains control characters */
151 MIME_HASNUL
= 010, /* contains \0 characters */
152 MIME_NOTERMNL
= 020 /* lacks a terminating newline */
156 TD_NONE
= 0, /* no display conversion */
157 TD_ISPR
= 01, /* use isprint() checks */
158 TD_ICONV
= 02, /* use iconv() */
159 TD_DELCTRL
= 04 /* delete control characters */
163 char *s
; /* the string's content */
164 size_t l
; /* the stings's length */
168 PROTO_FILE
, /* refers to a local file */
169 PROTO_POP3
, /* is a pop3 server string */
170 PROTO_IMAP
, /* is an imap server string */
171 PROTO_MAILDIR
, /* refers to a maildir folder */
172 PROTO_UNKNOWN
/* unknown protocol */
175 struct sock
{ /* data associated with a socket */
176 int s_fd
; /* file descriptor */
178 int s_use_ssl
; /* SSL is used */
179 #if defined (USE_NSS)
180 void *s_prfd
; /* NSPR file descriptor */
181 #elif defined (USE_OPENSSL)
182 void *s_ssl
; /* SSL object */
183 void *s_ctx
; /* SSL context object */
184 #endif /* SSL library specific */
186 char *s_wbuf
; /* for buffered writes */
187 int s_wbufsize
; /* allocated size of s_buf */
188 int s_wbufpos
; /* position of first empty data byte */
189 char s_rbuf
[LINESIZE
+1]; /* for buffered reads */
190 char *s_rbufptr
; /* read pointer to s_rbuf */
191 int s_rsz
; /* size of last read in s_rbuf */
192 char *s_desc
; /* description of error messages */
193 void (*s_onclose
)(void); /* execute on close */
197 struct sock mb_sock
; /* socket structure */
199 MB_NONE
= 000, /* no reply expected */
200 MB_COMD
= 001, /* command reply expected */
201 MB_MULT
= 002, /* multiline reply expected */
202 MB_PREAUTH
= 004, /* not in authenticated state */
203 MB_BYE
= 010 /* may accept a BYE state */
205 FILE *mb_itf
; /* temp file with messages, read open */
206 FILE *mb_otf
; /* same, write open */
207 char *mb_sorted
; /* sort method */
209 MB_VOID
, /* no type (e. g. connection failed) */
210 MB_FILE
, /* local file */
211 MB_POP3
, /* POP3 mailbox */
212 MB_IMAP
, /* IMAP mailbox */
213 MB_MAILDIR
, /* maildir folder */
214 MB_CACHE
/* cached mailbox */
215 } mb_type
; /* type of mailbox */
217 MB_DELE
= 01, /* may delete messages in mailbox */
218 MB_EDIT
= 02 /* may edit messages in mailbox */
220 int mb_compressed
; /* is a compressed mbox file */
221 int mb_threaded
; /* mailbox has been threaded */
224 MB_UIDPLUS
= 001 /* supports IMAP UIDPLUS */
226 unsigned long mb_uidvalidity
; /* IMAP unique identifier validity */
227 char *mb_imap_account
; /* name of current IMAP account */
228 char *mb_imap_mailbox
; /* name of current IMAP mailbox */
229 char *mb_cache_directory
; /* name of cache directory */
233 NEED_UNSPEC
, /* unspecified need, don't fetch */
234 NEED_HEADER
, /* need the header of a message */
235 NEED_BODY
/* need header and body of a message */
239 HAVE_NOTHING
= 0, /* nothing downloaded yet */
240 HAVE_HEADER
= 01, /* header is downloaded */
241 HAVE_BODY
= 02 /* entire message is downloaded */
245 * flag bits. Attention: Flags that are used in cache.c may not change.
248 MUSED
= (1<<0), /* entry is used, but this bit isn't */
249 MDELETED
= (1<<1), /* entry has been deleted */
250 MSAVED
= (1<<2), /* entry has been saved */
251 MTOUCH
= (1<<3), /* entry has been noticed */
252 MPRESERVE
= (1<<4), /* keep entry in sys mailbox */
253 MMARK
= (1<<5), /* message is marked! */
254 MODIFY
= (1<<6), /* message has been modified */
255 MNEW
= (1<<7), /* message has never been seen */
256 MREAD
= (1<<8), /* message has been read sometime. */
257 MSTATUS
= (1<<9), /* message status has changed */
258 MBOX
= (1<<10), /* Send this to mbox, regardless */
259 MNOFROM
= (1<<11), /* no From line */
260 MHIDDEN
= (1<<12), /* message is hidden to user */
261 MFULLYCACHED
= (1<<13), /* message is completely cached */
262 MBOXED
= (1<<14), /* message has been sent to mbox */
263 MUNLINKED
= (1<<15), /* message was unlinked from cache */
264 MNEWEST
= (1<<16), /* message is very new (newmail) */
265 MFLAG
= (1<<17), /* message has been flagged recently */
266 MUNFLAG
= (1<<18), /* message has been unflagged */
267 MFLAGGED
= (1<<19), /* message is `flagged' */
268 MANSWER
= (1<<20), /* message has been answered recently */
269 MUNANSWER
= (1<<21), /* message has been unanswered */
270 MANSWERED
= (1<<22), /* message is `answered' */
271 MDRAFT
= (1<<23), /* message has been drafted recently */
272 MUNDRAFT
= (1<<24), /* message has been undrafted */
273 MDRAFTED
= (1<<25), /* message is marked as `draft' */
274 MKILL
= (1<<26), /* message has been killed */
275 MOLDMARK
= (1<<27), /* messages was marked previously */
276 MJUNK
= (1<<28) /* message is classified as junk */
280 enum mflag m_flag
; /* flags */
281 enum havespec m_have
; /* downloaded parts of the part */
282 int m_block
; /* block number of this part */
283 size_t m_offset
; /* offset in block of part */
284 size_t m_size
; /* Bytes in the part */
285 size_t m_xsize
; /* Bytes in the full part */
286 long m_lines
; /* Lines in the message */
287 long m_xlines
; /* Lines in the full message */
288 time_t m_time
; /* time the message was sent */
289 char *m_from
; /* message sender */
290 struct mimepart
*m_nextpart
; /* next part at same level */
291 struct mimepart
*m_multipart
; /* parts of multipart */
292 struct mimepart
*m_parent
; /* enclosing multipart part */
293 char *m_ct_type
; /* content-type */
294 char *m_ct_type_plain
; /* content-type without specs */
295 enum mimecontent m_mimecontent
; /* same in enum */
296 char *m_charset
; /* charset */
297 char *m_ct_transfer_enc
; /* content-transfer-encoding */
298 enum mimeenc m_mimeenc
; /* same in enum */
299 char *m_partstring
; /* part level string */
300 char *m_filename
; /* attachment filename */
304 enum mflag m_flag
; /* flags */
305 enum havespec m_have
; /* downloaded parts of the message */
306 int m_block
; /* block number of this message */
307 size_t m_offset
; /* offset in block of message */
308 size_t m_size
; /* Bytes in the message */
309 size_t m_xsize
; /* Bytes in the full message */
310 long m_lines
; /* Lines in the message */
311 long m_xlines
; /* Lines in the full message */
312 time_t m_time
; /* time the message was sent */
313 time_t m_date
; /* time in the 'Date' field */
314 unsigned m_idhash
; /* hash on Message-ID for threads */
315 unsigned long m_uid
; /* IMAP unique identifier */
316 struct message
*m_child
; /* first child of this message */
317 struct message
*m_younger
; /* younger brother of this message */
318 struct message
*m_elder
; /* elder brother of this message */
319 struct message
*m_parent
; /* parent of this message */
320 unsigned m_level
; /* thread level of message */
321 long m_threadpos
; /* position in threaded display */
322 float m_score
; /* score of message */
323 char *m_maildir_file
; /* original maildir file of msg */
324 unsigned m_maildir_hash
; /* hash of file name in maildir sub */
325 int m_collapsed
; /* collapsed thread information */
329 * Given a file address, determine the block number it represents.
331 #define mailx_blockof(off) ((int) ((off) / 4096))
332 #define mailx_offsetof(off) ((int) ((off) % 4096))
333 #define mailx_positionof(block, offset) ((off_t)(block) * 4096 + (offset))
339 MSGLIST
= 0, /* Message list type */
340 STRLIST
= 1, /* A pure string */
341 RAWLIST
= 2, /* Shell string list */
342 NOLIST
= 3, /* Just plain 0 */
343 NDMLIST
= 4, /* Message list, no defaults */
344 ECHOLIST
= 5, /* Like raw list, but keep quote chars */
345 P
= 040, /* Autoprint dot after command */
346 I
= 0100, /* Interactive command bit */
347 M
= 0200, /* Legal from send mode bit */
348 W
= 0400, /* Illegal when read only bit */
349 F
= 01000, /* Is a conditional command */
350 T
= 02000, /* Is a transparent command */
351 R
= 04000, /* Cannot be called from collect */
352 A
= 010000 /* Needs an active mailbox */
356 * Oft-used mask values
359 #define MMNORM (MDELETED|MSAVED|MHIDDEN)/* Look at both save and delete bits */
360 #define MMNDEL (MDELETED|MHIDDEN) /* Look only at deleted bit */
363 * Format of the command description table.
364 * The actual table is declared and initialized
368 char *c_name
; /* Name of command */
369 int (*c_func
)(void *); /* Implementor of the command */
370 enum argtype c_argtype
; /* Type of arglist (see below) */
371 short c_msgflag
; /* Required flags of messages */
372 short c_msgmask
; /* Relevant flags of messages */
375 /* Yechh, can't initialize unions */
377 #define c_minargs c_msgflag /* Minimum argcount for RAWLIST */
378 #define c_maxargs c_msgmask /* Max argcount for RAWLIST */
381 * Structure used to return a break down of a head
382 * line (hats off to Bill Joy!)
386 char *l_from
; /* The name of the sender */
387 char *l_tty
; /* His tty string (if any) */
388 char *l_date
; /* The entire date string */
392 GTO
= 1, /* Grab To: line */
393 GSUBJECT
= 2, /* Likewise, Subject: line */
394 GCC
= 4, /* And the Cc: line */
395 GBCC
= 8, /* And also the Bcc: line */
397 GNL
= 16, /* Print blank line after */
398 GDEL
= 32, /* Entity removed from list */
399 GCOMMA
= 64, /* detract puts in commas */
400 GUA
= 128, /* User-Agent field */
401 GMIME
= 256, /* MIME 1.0 fields */
402 GMSGID
= 512, /* a Message-ID */
403 /* 1024 */ /* unused */
404 GIDENT
= 2048, /* From:, Reply-To: and Organization: field */
405 GREF
= 4096, /* References: field */
406 GDATE
= 8192, /* Date: field */
407 GFULL
= 16384, /* include full names */
408 GSKIN
= 32768, /* skin names */
409 GEXTRA
= 65536, /* extra fields */
410 GFILES
= 131072 /* include filename addresses */
413 #define GMASK (GTO|GSUBJECT|GCC|GBCC) /* Mask of places from whence */
415 #define visible(mp) (((mp)->m_flag & (MDELETED|MHIDDEN|MKILL)) == 0 || \
416 (dot == (mp) && (mp)->m_flag & MKILL))
419 * Structure used to pass about the current
420 * state of the user-typed message header.
424 struct name
*h_to
; /* Dynamic "To:" string */
425 char *h_subject
; /* Subject string */
426 struct name
*h_cc
; /* Carbon copies string */
427 struct name
*h_bcc
; /* Blind carbon copies */
428 struct name
*h_ref
; /* References */
429 struct name
*h_smopts
; /* Sendmail options */
430 struct attachment
*h_attach
; /* MIME attachments */
431 char *h_charset
; /* preferred charset */
432 struct name
*h_from
; /* overridden "From:" field */
433 struct name
*h_replyto
; /* overridden "Reply-To:" field */
434 struct name
*h_sender
; /* overridden "Sender:" field */
435 char *h_organization
; /* overridden "Organization:" field */
439 * Structure of namelist nodes used in processing
440 * the recipients of mail and aliases and all that
445 NAME_NAME_SALLOC
= 1<<0, /* .n_name is doped */
446 NAME_FULLNAME_SALLOC
= 1<<1, /* .n_fullname is doped */
447 NAME_SKINNED
= 1<<2, /* Is actually skin()ned */
448 NAME_ADDRSPEC_CHECKED
= 1<<3,
449 NAME_ADDRSPEC_ISFILE
= 1<<4, /* is a file path */
450 NAME_ADDRSPEC_ISPIPE
= 1<<5, /* is a command for pipeing */
451 NAME_ADDRSPEC_ISFILEORPIPE
= NAME_ADDRSPEC_ISFILE
|
452 NAME_ADDRSPEC_ISPIPE
,
453 NAME_ADDRSPEC_INVALID
= 1<<6, /* An invalid addr-spec */
454 NAME_ADDRSPEC_ERR_EMPTY
= 1<<7, /* An empty string (or NULL) */
455 NAME_ADDRSPEC_ERR_ATSEQ
= 1<<8, /* Weird @ sequence */
456 /* More on _ERR_ below */
457 NAME_IDNA
= 1<<9, /* IDNA convertion needed/applied */
458 /* Bit range for storing a faulty character */
459 _NAME_ADDRSPEC_ERR_MASKC
= 0xFF << 16
462 #define NAME_ADDRSPEC_ERR_GETC(F) (((F) & 0x00FF0000) >> 16)
463 #define NAME_ADDRSPEC_ERR_SETC(C) (((unsigned char)(C) & 0xFF) << 16)
466 struct name
*n_flink
; /* Forward link in list. */
467 struct name
*n_blink
; /* Backward list link */
468 enum gfield n_type
; /* From which list it came */
469 enum nameflags n_flags
; /* enum nameflags */
470 char *n_name
; /* This fella's name */
471 char *n_fullname
; /* Sometimes, name including comment */
475 const char *ag_input
; /* Input string as given */
476 size_t ag_ilen
; /* strlen() of input */
477 size_t ag_iaddr_start
; /* Start of address in .ag_input, */
478 size_t ag_iaddr_end
; /* its end (only if ! _FILEADDR) */
479 char *ag_skinned
; /* Output (alloced if !=.ag_input) */
480 size_t ag_slen
; /* strlen() of .ag_skinned */
481 size_t ag_sdom_start
; /* Start of domain in .ag_skinned, */
482 size_t ag_sdom_end
; /* its end */
483 enum nameflags ag_n_flags
; /* enum nameflags of .ag_skinned */
487 * Structure of a MIME attachment.
491 struct attachment
*a_flink
; /* Forward link in list. */
492 struct attachment
*a_blink
; /* Backward list link */
493 char *a_name
; /* file name */
494 char *a_content_type
; /* content type */
495 char *a_content_disposition
; /* content disposition */
496 char *a_content_id
; /* content id */
497 char *a_content_description
; /* content description */
498 char *a_charset
; /* character set */
499 int a_msgno
; /* message number */
503 * Structure of a variable node. All variables are
504 * kept on a singly-linked list of these, rooted by
509 struct var
*v_link
; /* Forward link to next variable */
510 char *v_name
; /* The variable's name */
511 char *v_value
; /* And it's current value */
515 struct group
*ge_link
; /* Next person in this group */
516 char *ge_name
; /* This person's user name */
520 struct grouphead
*g_link
; /* Next grouphead in list */
521 char *g_name
; /* Name of this group */
522 struct group
*g_list
; /* Users in group. */
526 * Structure of the hash table of ignored header fields
529 int i_count
; /* Number of entries */
531 struct ignore
*i_link
; /* Next ignored field in bucket */
532 char *i_field
; /* This ignored field */
537 * Token values returned by the scanner used for argument lists.
538 * Also, sizes of scanner-related things.
541 TEOL
= 0, /* End of the command line */
542 TNUMBER
= 1, /* A message number */
543 TDASH
= 2, /* A simple dash */
544 TSTRING
= 3, /* A string (possibly containing -) */
545 TDOT
= 4, /* A "." */
546 TUP
= 5, /* An "^" */
547 TDOLLAR
= 6, /* A "$" */
548 TSTAR
= 7, /* A "*" */
549 TOPEN
= 8, /* An '(' */
550 TCLOSE
= 9, /* A ')' */
551 TPLUS
= 10, /* A '+' */
552 TERROR
= 11, /* A lexical error */
553 TCOMMA
= 12, /* A ',' */
554 TSEMI
= 13, /* A ';' */
555 TBACK
= 14 /* A '`' */
558 #define REGDEP 2 /* Maximum regret depth. */
561 * Constants for conditional commands. These describe whether
562 * we should be executing stuff or not.
565 CANY
= 0, /* Execute in send or receive mode */
566 CRCV
= 1, /* Execute in receive mode only */
567 CSEND
= 2, /* Execute in send mode only */
568 CTERM
= 3, /* Execute only if stdin is a tty */
569 CNONTERM
= 4 /* Execute only if stdin not tty */
573 * For the 'shortcut' and 'unshortcut' functionality.
576 struct shortcut
*sh_next
; /* next shortcut in list */
577 char *sh_short
; /* shortcut string */
578 char *sh_long
; /* expanded form */
582 * Kludges to handle the change from setexit / reset to setjmp / longjmp
585 #define setexit() sigsetjmp(srbuf, 1)
586 #define reset(x) siglongjmp(srbuf, x)
589 * Locale-independent character classes.
603 extern const unsigned char class_char
[];
605 #define __ischarof(C, FLAGS) \
606 (asciichar(C) && class_char[(unsigned char)(C)] & (FLAGS))
607 #define __ischareq(C, FLAGS) \
608 (asciichar(C) && class_char[(unsigned char)(C)] == (FLAGS))
610 #define asciichar(c) ((unsigned char)(c) <= 0177)
611 #define alnumchar(c) __ischarof(c, C_DIGIT|C_OCTAL|C_UPPER|C_LOWER)
612 #define alphachar(c) __ischarof(c, C_UPPER|C_LOWER)
613 #define blankchar(c) __ischarof(c, C_BLANK)
614 #define blankspacechar(c) __ischarof(c, C_BLANK|C_SPACE)
615 #define cntrlchar(c) __ischareq(c, C_CNTRL)
616 #define digitchar(c) __ischarof(c, C_DIGIT|C_OCTAL)
617 #define lowerchar(c) __ischarof(c, C_LOWER)
618 #define punctchar(c) __ischarof(c, C_PUNCT)
619 #define spacechar(c) __ischarof(c, C_BLANK|C_SPACE|C_WHITE)
620 #define upperchar(c) __ischarof(c, C_UPPER)
621 #define whitechar(c) __ischarof(c, C_BLANK|C_WHITE)
622 #define octalchar(c) __ischarof(c, C_OCTAL)
624 #define upperconv(c) (lowerchar(c) ? (c)-'a'+'A' : (c))
625 #define lowerconv(c) (upperchar(c) ? (c)-'A'+'a' : (c))
627 #define fieldnamechar(c) (asciichar(c)&&(c)>040&&(c)!=0177&&(c)!=':')
630 * Truncate a file to the last character written. This is
631 * useful just before closing an old file that was opened
634 #define trunc(stream) { \
636 ftruncate(fileno(stream), (off_t)ftell(stream)); \
640 * Use either alloca() or smalloc()/free(). ac_alloc can be used to
641 * allocate space within a function. ac_free must be called when the
642 * space is no longer needed, but expands to nothing if using alloca().
645 #define ac_alloc(n) alloca(n)
646 #define ac_free(n) do {} while (0)
647 #else /* !HAVE_ALLOCA */
648 #define ac_alloc(n) smalloc(n)
649 #define ac_free(n) free(n)
650 #endif /* !HAVE_ALLOCA */
653 * Single-threaded, use unlocked I/O.
655 #ifdef HAVE_PUTC_UNLOCKED
657 # define getc(c) getc_unlocked(c)
659 # define putc(c, f) putc_unlocked(c, f)
661 # define putchar(c) putc_unlocked((c), stdout)
664 #define CBAD (-15555)
666 #define smin(a, b) ((a) < (b) ? (a) : (b))
667 #define smax(a, b) ((a) < (b) ? (b) : (a))
670 * For saving the current directory and later returning.
676 #else /* !HAVE_FCHDIR */
678 char cw_wd
[PATHSIZE
];
680 #endif /* !HAVE_FCHDIR */
683 enum ssl_vrfy_level
{