1 /*********************************************************************** 2 * * 3 * This software is part of the BSD package * 4 *Copyright (c) 1978-2012 The Regents of the University of California an* 5 * * 6 * Redistribution and use in source and binary forms, with or * 7 * without modification, are permitted provided that the following * 8 * conditions are met: * 9 * * 10 * 1. Redistributions of source code must retain the above * 11 * copyright notice, this list of conditions and the * 12 * following disclaimer. * 13 * * 14 * 2. Redistributions in binary form must reproduce the above * 15 * copyright notice, this list of conditions and the * 16 * following disclaimer in the documentation and/or other * 17 * materials provided with the distribution. * 18 * * 19 * 3. Neither the name of The Regents of the University of California* 20 * names of its contributors may be used to endorse or * 21 * promote products derived from this software without * 22 * specific prior written permission. * 23 * * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 25 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 28 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * 30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * 31 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * 33 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * 34 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 36 * POSSIBILITY OF SUCH DAMAGE. * 37 * * 38 * Redistribution and use in source and binary forms, with or without * 39 * modification, are permitted provided that the following conditions * 40 * are met: * 41 * 1. Redistributions of source code must retain the above copyright * 42 * notice, this list of conditions and the following disclaimer. * 43 * 2. Redistributions in binary form must reproduce the above copyright * 44 * notice, this list of conditions and the following disclaimer in * 45 * the documentation and/or other materials provided with the * 46 * distribution. * 47 * 3. Neither the name of the University nor the names of its * 48 * contributors may be used to endorse or promote products derived * 49 * from this software without specific prior written permission. * 50 * * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" * 52 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * 53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * 54 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS * 55 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * 56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * 57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * 58 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * 59 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * 60 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * 61 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * 62 * SUCH DAMAGE. * 63 * * 64 * Kurt Shoens (UCB) * 65 * gsf * 66 * * 67 ***********************************************************************/ 68 #pragma prototyped 69 /* 70 * Mail -- a mail program 71 * 72 * Author: 73 * 74 * Kurt Shoens (UCB) March 25, 1978 75 * 76 * Contributors: 77 * 78 * Glenn Fowler (AT&T Research) 1996-09-11 79 */ 80 81 #if _PACKAGE_ast 82 83 #include <ast.h> 84 #include <error.h> 85 #include <getopt.h> 86 #include <ls.h> 87 #include <sig.h> 88 #include <times.h> 89 #include <wait.h> 90 91 #else /*_PACKAGE_ast*/ 92 93 #include <sys/param.h> 94 #include <sys/stat.h> 95 #include <sys/time.h> 96 #include <sys/wait.h> 97 98 #include <limits.h> 99 #include <signal.h> 100 #include <fcntl.h> 101 #include <unistd.h> 102 #include <stdlib.h> 103 #include <string.h> 104 #include <time.h> 105 106 #ifndef O_BINARY 107 #define O_BINARY 0 108 #endif 109 #ifndef O_CLOEXEC 110 #define O_CLOEXEC 0 111 #endif 112 113 extern char* optarg; 114 extern int optind; 115 extern int opterr; 116 117 #endif /*_PACKAGE_ast*/ 118 119 #include <cdt.h> 120 #include <ctype.h> 121 #include <errno.h> 122 #include <mime.h> 123 #include <setjmp.h> 124 #include <stdio.h> 125 126 #include "local.h" 127 128 #define APPEND_MAILBOX 1 /* New mail goes to end of mailbox */ 129 #if defined(SFIO_VERSION) && defined(SF_READ) && defined(SF_WRITE) 130 #define MORE_DISCIPLINE 1 /* Sfio more discipline on stdout */ 131 #endif 132 133 #define CALL(f) (*(state.folder==FIMAP?imap_##f:f)) 134 #define TRACE(c) (state.trace|=(1<<((c)-'a'))) 135 #define TRACING(c) (state.trace&(1<<((c)-'a'))) 136 137 #define sig_t Sig_handler_t 138 139 #define holdsigs() sigcritical(SIG_REG_EXEC) 140 #define relsesigs() sigcritical(SIG_REG_POP) 141 142 #define initargs(ap) ((ap)->argp=(ap)->argv) 143 #define endargs(ap) (*(ap)->argp=0,(ap)->argp-(ap)->argv) 144 145 #if MORE_DISCIPLINE 146 #define moretop() (state.more.match=0,state.more.row=state.more.col=1) 147 #else 148 #define moretop() 149 #endif 150 151 #define shquote shellquote /* netbsd has one in <stdlib.h>! */ 152 153 #define ESCAPE '~' /* Default escape for sending */ 154 #define NMLSIZE 1024 /* max names in a message list */ 155 #define PATHSIZE MAXPATHLEN /* Size of pathnames throughout */ 156 #define LINESIZE (32*STRINGLEN) /* max readable line width */ 157 #define HEADSIZE 128 /* maximum header line length */ 158 #define LASTSIZE 256 /* max saved cmd line size */ 159 #define STRINGSIZE ((unsigned)128) /* Dynamic allocation units */ 160 #define MAILMODE (S_IRUSR|S_IWUSR) /* private mail file mode */ 161 #define METAFILE "%#&+/" /* `Metafile' prefix */ 162 #define REGDEP 2 /* Maximum regret depth. */ 163 #define STRINGLEN 1024 /* Maximum length of string token */ 164 #define MARGIN 72 /* Right line margin */ 165 #define REFLEN (12*MARGIN) /* Maximum length or References: */ 166 167 typedef struct msg { 168 int m_index; /* command address vector index */ 169 short m_flag; /* flags, see below */ 170 short m_offset; /* offset in block of message */ 171 long m_block; /* block number of this message */ 172 off_t m_size; /* Bytes in the message */ 173 off_t m_lines; /* Lines in the message */ 174 void* m_info; /* Folder type specific info */ 175 } Msg_t; 176 177 /* 178 * Folder types. 179 */ 180 181 #define FFILE 1 /* File folder */ 182 #define FIMAP 2 /* IMAP folder */ 183 #define FMH 3 /* MH folder */ 184 185 /* 186 * Command flag bits. 187 */ 188 189 #define MBOX (1<<0) /* send this to mbox, regardless */ 190 #define MDELETE (1<<1) /* entry has been deleted */ 191 #define MINIT (1<<2) /* folder specific init mark */ 192 #define MMARK (1<<3) /* message is marked! */ 193 #define MNEW (1<<4) /* message has never been seen */ 194 #define MNONE (1<<5) /* never matches */ 195 #define MODIFY (1<<6) /* message has been modified */ 196 #define MPRESERVE (1<<7) /* keep entry in sys mailbox */ 197 #define MREAD (1<<8) /* message has been read sometime */ 198 #define MSAVE (1<<9) /* entry has been saved */ 199 #define MSCAN (1<<10) /* entry has been scanned */ 200 #define MSPAM (1<<11) /* message is probably spam */ 201 #define MSTATUS (1<<12) /* message status has changed */ 202 #define MTOUCH (1<<13) /* entry has been noticed */ 203 #define MUSED (1<<14) /* entry is used, but this bit isn't */ 204 #define MZOMBIE (1<<15) /* deleted but still there */ 205 206 /* 207 * Given a file address, determine the block number it represents. 208 */ 209 210 #define blocknumber(off) ((int) ((off) / 4096)) 211 #define blockoffset(off) ((int) ((off) % 4096)) 212 #define blockposition(block,offset) ((off_t)(block) * 4096 + (offset)) 213 214 /* 215 * Format of the command description table. 216 */ 217 218 typedef int (*Cmd_f)(void*); 219 220 struct cmd { 221 const char* c_name; /* Name of command */ 222 Cmd_f c_func; /* Implementor of the command */ 223 unsigned long c_argtype; /* Type of arglist (see below) */ 224 unsigned long c_msgflag; /* Required flags of messages */ 225 size_t c_msgmask; /* Relevant flags of messages */ 226 const char* c_help; /* Command help text */ 227 }; 228 229 /* 230 * Yechh, can't initialize unions. 231 */ 232 233 #define c_minargs c_msgflag /* Minimum argcount for RAWLIST */ 234 #define c_maxargs c_msgmask /* Max argcount for RAWLIST */ 235 236 struct esc { 237 const char* e_name; /* Name of command */ 238 const char* e_help; /* Command help text */ 239 }; 240 241 /* 242 * Common header labels. 243 */ 244 245 struct lab { 246 const char* name; /* Header label name */ 247 long type; /* G* type */ 248 }; 249 250 /* 251 * Header parse state. 252 */ 253 254 struct parse { 255 struct msg* mp; /* Parsing this message */ 256 struct header* hp; /* Matched headers here */ 257 Dt_t** ignore; /* Ignore these headers */ 258 FILE* fp; /* Message io */ 259 long count; /* Remaining message size */ 260 char* name; /* Header name */ 261 char* data; /* Header data */ 262 char* separator; /* Header name separator position */ 263 int length; /* Total header length */ 264 unsigned long flags; /* G* flags */ 265 unsigned long type; /* Matched header type */ 266 char buf[LINESIZE]; /* Work buffer */ 267 }; 268 269 /* 270 * Argument types. 271 */ 272 273 #define MSGLIST 0 /* Message list type */ 274 #define STRLIST 1 /* A pure string */ 275 #define RAWLIST 2 /* Shell string list */ 276 #define NOLIST 3 /* Just plain 0 */ 277 #define NDMLIST 4 /* Message list, no defaults */ 278 279 #define LISTMASK 07 /* Mask list type from argument type */ 280 281 #define A (1<<4) /* Var alias */ 282 #define C (1<<5) /* Is a conditional command, Cmd line var set */ 283 #define D (1<<6) /* Var unset default to initial value */ 284 #define E (1<<7) /* Var init from environ */ 285 #define I (1<<8) /* Interactive command, Var is integer */ 286 #define L (1<<9) /* Append line values */ 287 #define M (1<<10) /* Valid from send mode */ 288 #define N (1<<11) /* Var null value means off */ 289 #define P (1<<12) /* Autoprint dot after command */ 290 #define R (1<<13) /* Cannot call from collect, Readonly var */ 291 #define S (1<<14) /* Var cannot change while sourcing */ 292 #define W (1<<15) /* Invalid for readonly */ 293 #define Z (1L<<16) /* Is a transparent command */ 294 295 /* 296 * Oft-used mask values 297 */ 298 299 #define MMNORM (MDELETE|MSAVE)/* Look at both save and delete bits */ 300 #define MMNDEL MDELETE /* Look only at deleted bit */ 301 302 /* 303 * note() type bits. 304 */ 305 306 #define DEBUG (1<<0) /* debug trace */ 307 #define ERROR (1<<1) /* stderr message */ 308 #define FATAL (1<<2) /* message and exit(1) */ 309 #define IDENTIFY (1<<3) /* prefix with command name */ 310 #define PANIC (1<<4) /* message and abort() */ 311 #define PROMPT (1<<5) /* no trailing newline */ 312 #define SYSTEM (1<<6) /* append errno message */ 313 #define WARNING (1<<7) /* warning prefix */ 314 315 /* 316 * Structure used to return a break down of a head 317 * line (hats off to Bill Joy!) 318 */ 319 320 struct headline { 321 char* l_from; /* The name of the sender */ 322 char* l_info; /* Special info (tty or article number) */ 323 char* l_date; /* The entire date string */ 324 }; 325 326 /* 327 * Name extraction and name dictionary node flags. 328 */ 329 330 #define GALIAS (1<<0) /* Alias name */ 331 #define GALTERNATE (1<<1) /* Alternate name */ 332 #define GBCC (1<<2) /* Grab Bcc: line */ 333 #define GCC (1<<3) /* Grab Cc: line */ 334 #define GCOMMA (1<<4) /* Comma separated */ 335 #define GCOMPARE (1<<5) /* For comparison */ 336 #define GDISPLAY (1<<6) /* For display */ 337 #define GDONE (1<<7) /* Done with it */ 338 #define GFIRST (1<<8) /* First recipient */ 339 #define GFROM (1<<9) /* Don't skip initial `From ' */ 340 #define GINTERPOLATE (1<<10) /* Check headers for interpolate() */ 341 #define GLAST (1<<11) /* Get last instance */ 342 #define GMAP (1<<12) /* Already mapped */ 343 #define GMESSAGEID (1<<13) /* Grab Message-ID: line */ 344 #define GMETOO (1<<14) /* Send to state.var.user too */ 345 #define GMIME (1L<<15) /* Check MIME content headers */ 346 #define GMISC (1L<<16) /* Grab miscellaneous headers */ 347 #define GNEWS (1L<<17) /* For newsgroup article id */ 348 #define GNL (1L<<18) /* Print blank line after headers */ 349 #define GREFERENCES (1L<<19) /* Grab References: line */ 350 #define GREPLY (1L<<20) /* For reply to sender */ 351 #define GRULE (1L<<21) /* Ouput rule if GNL */ 352 #define GSEND (1L<<22) /* Get it ready to send */ 353 #define GSENDER (1L<<23) /* Get state.var.sender address only */ 354 #define GSTACK (1L<<24) /* savestr() unmapped names */ 355 #define GSTATUS (1L<<25) /* Grab Status: line */ 356 #define GSUB (1L<<26) /* Grab Subject: line */ 357 #define GTO (1L<<27) /* Grab To: line */ 358 #define GUSER (1L<<28) /* Stop if ${user}@ */ 359 360 #define GCOMPOSE (GEDIT|GSTATUS) /* Composable headers */ 361 #define GEDIT (GSTD|GMISC) /* Editable headers */ 362 #define GEXTERN (GEDIT&~GBCC) /* External headers */ 363 #define GMASK (GNAME|GDONE) /* Active mask */ 364 #define GNAME (GBCC|GCC|GTO) /* Name fields */ 365 #define GSTD (GNAME|GSUB) /* Standard headers */ 366 367 /* 368 * Structure of a variable node. 369 */ 370 371 struct var { 372 const char* name; 373 char** variable; 374 unsigned long flags; 375 const char* initialize; 376 void (*set)(struct var*, const char*); 377 const char* help; 378 }; 379 380 struct list { 381 struct list* next; 382 char name[1]; 383 }; 384 385 struct name { 386 Dtlink_t link; 387 void* value; 388 unsigned long flags; 389 char name[1]; 390 }; 391 392 struct argvec { 393 char* argv[64 * 1024]; 394 char** argp; 395 }; 396 397 struct child { 398 struct child* link; 399 int pid; 400 short done; 401 short free; 402 }; 403 404 struct file { 405 struct file* link; 406 FILE* fp; 407 int pid; 408 }; 409 410 struct mhcontext { 411 int type; 412 unsigned long dot; 413 unsigned long next; 414 struct { 415 unsigned long dot; 416 unsigned long next; 417 } old; 418 }; 419 420 typedef struct { 421 int type; 422 void* state; 423 } Imapcontext_t; 424 425 #define PART_application (1<<0) 426 #define PART_body (1<<1) 427 #define PART_disposition (1<<2) 428 #define PART_inline (1<<3) 429 #define PART_message (1<<4) 430 #define PART_text (1<<5) 431 432 typedef struct part { 433 struct part* next; 434 off_t offset; 435 off_t size; 436 off_t lines; 437 struct { 438 off_t offset; 439 off_t size; 440 } raw; 441 unsigned long flags; 442 int count; 443 char name[HEADSIZE]; 444 char type[HEADSIZE]; 445 char opts[HEADSIZE]; 446 char code[HEADSIZE]; 447 } Part_t; 448 449 struct bound { 450 struct bound* next; 451 int size; 452 char data[1]; 453 }; 454 455 /* 456 * Structure used to pass about the current 457 * state of the user-typed message header. 458 */ 459 460 struct header { 461 unsigned long h_flags; /* Active fields */ 462 Dt_t* h_names; /* Recipients */ 463 char** h_options; /* Mailer options */ 464 char* h_subject; /* Subject string */ 465 char* h_first; /* First recipient */ 466 char* h_messageid; /* Parent message-id */ 467 char* h_references; /* References */ 468 struct { 469 struct list* head; 470 struct list* tail; 471 } h_misc; /* Miscellaneous headers */ 472 unsigned long h_clear; /* Clear these on change */ 473 }; 474 475 struct dict { 476 Dtdisc_t disc; /* Object discipline */ 477 unsigned long flags; /* Member node flags */ 478 Dt_t* next; /* Next STACK dict */ 479 }; 480 481 struct match { 482 struct match* next; /* next in list */ 483 int length; /* string length */ 484 int beg; /* begin character match */ 485 int mid; /* mid character match */ 486 int end; /* end character match */ 487 char string[1]; /* match string */ 488 }; 489 490 struct linematch { 491 int minline; /* minimum line size */ 492 unsigned char beg[256]; /* begin character match */ 493 unsigned char mid[256]; /* mid character match */ 494 unsigned char end[256]; /* end character match */ 495 struct match* match; /* exact match list */ 496 struct match* last; /* last match list item */ 497 }; 498 499 struct sendand { 500 struct sendand* next; /* next in and list */ 501 char* head; /* head */ 502 char* pattern; /* match pattern */ 503 unsigned long flags; /* grab*() flags */ 504 }; 505 506 struct sendor { 507 struct sendor* next; /* next in or list */ 508 struct sendand sendand; /* and list */ 509 }; 510 511 struct sender { 512 struct sender* next; /* next in list */ 513 struct sendor sendor; /* or list */ 514 char address[1]; /* sender address override */ 515 }; 516 517 /* 518 * dictsearch() flag values 519 */ 520 521 #define LOOKUP 0 522 #define COPY (1<<0) 523 #define CREATE (1<<1) 524 #define DELETE (1<<2) 525 #define IGNORECASE (1<<3) 526 #define INSERT (1<<4) 527 #define OBJECT (1<<5) 528 #define STACK (1<<6) 529 530 /* 531 * ignore flags 532 */ 533 534 #define dictflags(p) (((struct dict*)(*(p))->disc)->flags) 535 536 #define HIT (1<<0) /* Global table flag */ 537 #define IGNORE (1<<1) /* Global table flag */ 538 #define RETAIN (1<<2) /* Global table flag */ 539 540 /* 541 * collect() and mail() flags 542 */ 543 544 #define FOLLOWUP (1<<0) 545 #define HEADERS (1<<1) 546 #define INTERPOLATE (1<<2) 547 #define MARK (1<<3) 548 #define REPLY (1<<4) 549 550 /* 551 * Token values returned by the scanner used for argument lists. 552 */ 553 554 #define TEOL 0 /* End of the command line */ 555 #define TNUMBER 1 /* A message number */ 556 #define TDASH 2 /* A simple dash */ 557 #define TSTRING 3 /* A string (possibly containing -) */ 558 #define TDOT 4 /* A "." */ 559 #define TUP 5 /* An "^" */ 560 #define TDOLLAR 6 /* A "$" */ 561 #define TSTAR 7 /* A "*" */ 562 #define TOPEN 8 /* An '(' */ 563 #define TCLOSE 9 /* A ')' */ 564 #define TPLUS 10 /* A '+' */ 565 #define TERROR 11 /* A lexical error */ 566 567 /* 568 * Constants for conditional commands. These describe whether 569 * we should be executing stuff or not. 570 */ 571 572 #define RECEIVE (-1) /* Execute in receive mode only */ 573 #define SEND (1) /* Execute in send mode only */ 574 575 /* 576 * Kludges to handle the change from setexit / reset to setjmp / longjmp 577 */ 578 579 #define setexit() do { \ 580 int x = setjmp(state.jump.sr); \ 581 if (x) sigunblock(x); \ 582 } while(0) 583 #define reset(x) longjmp(state.jump.sr, x) 584 585 /* 586 * <unistd.h> etc encroachment 587 * we asked for extentions -- and now pay for it ... 588 */ 589 590 #define undelete mail_undelete 591 592 /* 593 * The pointers for the string allocation routines, 594 * there are NSPACE independent areas. 595 * The first holds STRINGSIZE bytes, the next 596 * twice as much, and so on. 597 */ 598 599 #define NSPACE 25 /* Total number of string spaces */ 600 struct strings { 601 char* s_topfree; /* Beginning of this area */ 602 char* s_nextfree; /* Next alloctable place here */ 603 unsigned int s_nleft; /* Number of bytes left here */ 604 }; 605 606 typedef struct { 607 const char* version; /* Version string */ 608 const char* license; /* License text */ 609 char* on; /* Variable on value */ 610 const struct cmd* cmdtab; /* Command table */ 611 int cmdnum; /* Number of commands */ 612 const struct esc* esctab; /* Escape command table */ 613 int escnum; /* Number of escape commands */ 614 const struct var* vartab; /* Variable table */ 615 int varnum; /* Number of variables */ 616 const struct lab* hdrtab; /* Header label table */ 617 int hdrnum; /* Number of header labels */ 618 unsigned long askheaders; /* Ask for these headers */ 619 620 /* the rest are implicitly initialized */ 621 622 int clobber; /* Last command had ! */ 623 int cmdline; /* Currently reading cmd line options */ 624 int colmod; /* Mark bit */ 625 int cond; /* Current state of conditional exc. */ 626 int edit; /* Indicates editing a file */ 627 int incorporating; /* Executing incorporate command */ 628 int folder; /* Folder type */ 629 int hung; /* Op hung til alarm */ 630 int loading; /* Loading user definitions */ 631 int mode; /* SEND or RECEIVE */ 632 int noreset; /* String resets suspended */ 633 int onstack; /* salloc() != malloc() */ 634 int readonly; /* Will be unable to rewrite file */ 635 int realscreenheight; /* Real screen height */ 636 int sawcom; /* Set after first command */ 637 int screenheight; /* Screen height, or best guess */ 638 int screenwidth; /* Screen width, or best guess */ 639 int scroll; /* Current scroll size */ 640 int senderr; /* An error while checking */ 641 int sourcing; /* Currently reading variant file */ 642 int startup; /* Listing startup headers */ 643 int stopreset; /* Reset on stop */ 644 645 FILE* input; /* Current command input file */ 646 off_t mailsize; /* Size of system mailbox */ 647 int lexnumber; /* Number of TNUMBER from scan() */ 648 char lexstring[STRINGLEN]; /* String from TSTRING, scan() */ 649 int regretp; /* Pointer to TOS of regret tokens */ 650 int regretstack[REGDEP]; /* Stack of regretted tokens */ 651 char* string_stack[REGDEP]; /* Stack of regretted strings */ 652 int numberstack[REGDEP]; /* Stack of regretted numbers */ 653 char number[16]; /* Temp variable number string */ 654 char counts[32]; /* Temp counts number string */ 655 656 unsigned long trace; /* Trace bits */ 657 unsigned long editheaders; /* These headers in edit template */ 658 struct child* children; /* Child list */ 659 struct cmd* cmd; /* Current command table entry */ 660 struct file* files; /* fileopen() list */ 661 struct linematch* bodymatch; /* compiled state.var.spambody */ 662 struct sender* sender; /* compiled state.var.sender */ 663 struct stat openstat; /* fileopen stat */ 664 Dt_t* ignore; /* Ignored fields */ 665 Dt_t* saveignore; /* Ignored fields on save to folder */ 666 Dt_t* ignoreall; /* Special: ignore all headers */ 667 Dt_t* aliases; /* aliases */ 668 Dt_t* userid; /* User name -> id map */ 669 Dt_t* stacked; /* STACK dict list */ 670 671 struct strings stringdope[NSPACE]; 672 673 struct { 674 sig_t sigint; /* Previous SIGINT value */ 675 sig_t sighup; /* Previous SIGHUP value */ 676 sig_t sigtstp; /* Previous SIGTSTP value */ 677 sig_t sigttou; /* Previous SIGTTOU value */ 678 sig_t sigttin; /* Previous SIGTTIN value */ 679 FILE* fp; /* File for saving away */ 680 int hadintr; /* Have seen one SIGINT so far */ 681 jmp_buf work; /* To get back to work */ 682 int working; /* Whether to long jump */ 683 jmp_buf abort; /* To end collection with error */ 684 } collect; 685 686 struct { 687 jmp_buf header; /* Printing headers */ 688 jmp_buf sr; /* set/reset longjmp buffer */ 689 jmp_buf sigpipe; /* SIGPIPE longjmp buffer */ 690 } jump; 691 692 struct { 693 char bang[LASTSIZE]; /* Last ! command */ 694 char scan[LASTSIZE]; /* Last message search string */ 695 } last; 696 697 struct { 698 int count; /* Count of messages read in */ 699 int inbox; /* Current folder mh state.var.inbox */ 700 Imapcontext_t imap; /* imap message format */ 701 struct mhcontext mh; /* mh message format */ 702 int size; /* Max messages in vector */ 703 int* vec; /* Current message vector */ 704 FILE* ap; /* Actual file pointer */ 705 FILE* ip; /* Input temp file buffer */ 706 FILE* op; /* Output temp file buffer */ 707 struct msg* active; /* ip points to this message */ 708 struct msg* context; /* Folder read context */ 709 struct msg* dot; /* Pointer to current message */ 710 struct msg* list; /* The actual message structure */ 711 } msg; 712 713 struct { 714 char pwd[2][PATHSIZE]; /* pwd and oldpwd paths */ 715 char mail[PATHSIZE]; /* Name of current file */ 716 char path[PATHSIZE]; /* Very temporary fixed path buffer */ 717 char prev[PATHSIZE]; /* Name of previous file */ 718 Sfio_t* buf; /* Very temporary name buffer */ 719 Sfio_t* move; /* Very temporary name buffer */ 720 Sfio_t* part; /* Very temporary name buffer */ 721 Sfio_t* temp; /* Very temporary name buffer */ 722 } path; 723 724 struct { 725 int sp; /* Top of stack */ 726 struct { 727 FILE* input; /* Saved state.input */ 728 int cond; /* Saved state.cond */ 729 int loading; /* Saved state.loading */ 730 } stack[NOFILE]; 731 } source; 732 733 struct more { 734 #if MORE_DISCIPLINE 735 Sfdisc_t disc; 736 int row; 737 int col; 738 int match; 739 char pattern[HEADSIZE]; 740 char tmp[HEADSIZE]; 741 #endif 742 int discipline; 743 int init; 744 } more; 745 746 struct state_part { 747 748 Mimedisc_t disc; 749 Mime_t* mime; 750 Part_t* head; 751 Part_t global; 752 int init; 753 754 struct { 755 int multi; 756 int count; 757 Part_t* head; 758 Part_t* tail; 759 struct bound* boundary; 760 } in; 761 762 struct { 763 int multi; 764 int boundlen; 765 char boundary[HEADSIZE]; 766 } out; 767 768 } part; 769 770 struct { 771 char edit[256]; 772 char mail[256]; 773 char mesg[256]; 774 char more[256]; 775 char quit[256]; 776 char* dir; 777 } tmp; 778 779 struct 780 { 781 char* allnet; 782 char* append; 783 char* askbcc; 784 char* askcc; 785 char* askheaders; 786 char* asksub; 787 char* attachments; 788 char* autoinc; 789 char* autoprint; 790 char* bang; 791 char* cdpath; 792 char* cmd; 793 char* coprocess; 794 long crt; 795 char* dead; 796 char* debug; 797 char* domain; 798 char* dot; 799 char* editheaders; 800 char* editor; 801 char* escape; 802 char* fixedheaders; 803 char* flipr; 804 char* folder; 805 char* followup; 806 char* header; 807 char* headerbotch; 808 char* headfake; 809 char* hold; 810 char* home; 811 char* hostname; 812 char* ignore; 813 char* ignoreeof; 814 char* imap; 815 char* inbox; 816 char* indentprefix; 817 char* interactive; 818 char* justcheck; 819 long justfrom; 820 char* justheaders; 821 char* keep; 822 char* keepsave; 823 char* lister; 824 char* local; 825 char* lock; 826 char* log; 827 char* mail; 828 char* mailcap; 829 char* mailrc; 830 char* master; 831 char* mbox; 832 char* metoo; 833 char* more; 834 char* news; 835 char* oldpwd; 836 char* onehop; 837 char* outfolder; 838 char* page; 839 char* pager; 840 char* prompt; 841 char* pwd; 842 char* quiet; 843 char* receive; 844 char* recent; 845 char* rule; 846 char* save; 847 long screen; 848 char* searchheaders; 849 char* sender; 850 char* sendheaders; 851 char* sendmail; 852 char* sendwait; 853 char* shell; 854 char* showto; 855 char* Sign; 856 char* sign; 857 char* signature; 858 char* smtp; 859 char* spam; 860 char* spambody; 861 long spamdelay; 862 char* spamfrom; 863 char* spamfromok; 864 char* spamlog; 865 char* spamsub; 866 char* spamsubhead; 867 long spamtest; 868 char* spamto; 869 char* spamtook; 870 char* spamvia; 871 char* spamviaok; 872 long toplines; 873 char* trace; 874 char* user; 875 char* verbose; 876 char* visual; 877 } var; 878 879 } State_t; 880 881 extern State_t state; 882 883 extern int Blast(struct msg*); 884 extern int Copy(char*); 885 extern int Followup(struct msg*); 886 extern int From(struct msg*); 887 extern int Get(char**); 888 extern int Join(struct msg*); 889 extern int More(struct msg*); 890 extern int Reply(struct msg*); 891 extern int Save(char*); 892 extern int Split(char*); 893 extern int Type(struct msg*); 894 extern int addarg(struct argvec*, const char*); 895 extern int alias(char**); 896 extern void alter(char*); 897 extern int alternates(char**); 898 extern void announce(); 899 extern int anyof(char*, char*); 900 extern int blankline(char*); 901 extern int blast(struct msg*); 902 extern void boundary(void); 903 extern int capability(char**); 904 extern int cd(char**); 905 extern int check(int, int); 906 extern int cmdcopy(char*); 907 extern int cmddelete(struct msg*); 908 extern int cmdelse(void); 909 extern int cmdendif(void); 910 extern int cmdexit(int); 911 extern int cmdif(char**); 912 extern int cmdmkdir(char**); 913 extern int cmdpipe(char*); 914 extern int cmdquit(void); 915 extern int cmdrename(char**); 916 extern int cmdrmdir(char**); 917 extern int cmdtouch(char*); 918 extern int cmdwrite(char*); 919 extern FILE* collect(struct header*, unsigned long); 920 extern void commands(void); 921 extern int copy(struct msg*, FILE*, Dt_t**, char*, unsigned long); 922 extern char* counts(int, off_t, off_t); 923 extern void dictclear(Dt_t**); 924 extern void dictreset(void); 925 extern struct name* dictsearch(Dt_t**, const char*, int); 926 extern int dictwalk(Dt_t**, int(*)(Dt_t*, void*, void*), void*); 927 extern int deltype(struct msg*); 928 extern void demail(void); 929 extern char* detract(struct header*, unsigned long); 930 extern int dot(void); 931 extern int duplicate(char*); 932 extern int echo(char**); 933 extern int editor(struct msg*); 934 extern int execute(char*, int); 935 extern char* expand(char*, int); 936 extern void extract(struct header*, unsigned long, char*); 937 extern void fileclear(void); 938 extern int fileclose(FILE*); 939 extern FILE* filefd(int, char*); 940 extern int filecopy(const char*, FILE*, const char*, FILE*, FILE*, off_t, off_t*, off_t*, unsigned long); 941 extern int filelock(const char*, FILE*, int); 942 extern FILE* fileopen(char*, char*); 943 extern off_t filesize(FILE*); 944 extern FILE* filestd(char*, char*); 945 extern FILE* filetemp(char*, int, int, int); 946 extern int filetrunc(FILE*); 947 extern int first(int, int); 948 extern int folder(char**); 949 extern struct msg* folderinfo(int); 950 extern int folders(void); 951 extern int followup(struct msg*); 952 extern void free_command(int); 953 extern int from(struct msg*); 954 extern int get(char**); 955 extern void getargs(struct argvec*, char*); 956 extern int getfolder(char*, size_t); 957 extern int getmsglist(char*, unsigned long); 958 extern char* grab(struct msg*, unsigned long, char*); 959 extern void grabedit(struct header*, unsigned long); 960 extern void headclear(struct header*, unsigned long); 961 extern int headers(struct msg*); 962 extern int headget(struct parse*); 963 extern int headout(FILE*, struct header*, unsigned long); 964 extern int headset(struct parse*, struct msg*, FILE*, struct header*, Dt_t**, unsigned long); 965 extern int help(char**); 966 extern int ignore(char**); 967 extern int ignored(Dt_t**, const char*); 968 extern int incorporate(void); 969 extern int incfile(void); 970 extern int isall(const char*); 971 extern char* iscmd(char*); 972 extern int isdate(char*); 973 extern int isdir(char*); 974 extern int ishead(char*, int); 975 extern int isreg(char*); 976 extern int join(struct msg*); 977 extern int license(void*); 978 extern int list(void); 979 extern void load(char*); 980 extern char* localize(char*); 981 extern int lower(int); 982 extern int mail(char*); 983 extern char* mailbox(const char*, const char*); 984 extern int map(char*); 985 extern int mark(char*); 986 extern int mboxit(char*); 987 extern void mhgetcontext(struct mhcontext*, const char*, int); 988 extern void mhputcontext(struct mhcontext*, const char*); 989 extern int mime(int); 990 extern int more(struct msg*); 991 extern void msgflags(struct msg*, int, int); 992 extern struct msg* newmsg(off_t offset); 993 extern int next(struct msg*); 994 extern char* normalize(char*, unsigned long, char*, size_t); 995 extern void note(int, const char*, ...); 996 extern int notyet(char*); 997 extern int null(int); 998 extern void parse(struct msg*, char*, struct headline*, char*, size_t); 999 extern FILE* pipeopen(char*, char*); 1000 extern int preserve(char*); 1001 extern int puthead(FILE*, struct header*, int); 1002 extern int putline(FILE*, char*); 1003 extern int pwd(void); 1004 extern void quit(void); 1005 extern int readline(FILE*, char*, int); 1006 extern char* record(char*, unsigned long); 1007 extern int regular(FILE*); 1008 extern int reply(struct msg*); 1009 extern int replyall(struct msg*); 1010 extern int replysender(struct msg*); 1011 extern void resume(int); 1012 extern int retain(char**); 1013 extern int rm(char*); 1014 extern int run_command(char*, int, int, int, char*, char*, char*); 1015 extern FILE* run_editor(FILE*, off_t, struct header*, int, int); 1016 extern char* salloc(int); 1017 extern int save(char*); 1018 extern void savedeadletter(FILE*); 1019 extern int saveignore(char**); 1020 extern int saveretain(char**); 1021 extern char* savestr(char*); 1022 extern int scan(char**); 1023 extern int scroll(char*); 1024 extern int sender(char*, int); 1025 extern void sendmail(struct header*, unsigned long); 1026 extern int sendsmtp(FILE*, char*, char**, off_t); 1027 extern int set(char**); 1028 extern void set_askbcc(struct var*, const char*); 1029 extern void set_askcc(struct var*, const char*); 1030 extern void set_askheaders(struct var*, const char*); 1031 extern void set_asksub(struct var*, const char*); 1032 extern void set_coprocess(struct var*, const char*); 1033 extern void set_crt(struct var*, const char*); 1034 extern void set_editheaders(struct var*, const char*); 1035 extern void set_justfrom(struct var*, const char*); 1036 extern void set_list(struct var*, const char*); 1037 extern void set_mail(struct var*, const char*); 1038 extern void set_mailcap(struct var*, const char*); 1039 extern void set_more(struct var*, const char*); 1040 extern void set_news(struct var*, const char*); 1041 extern void set_notyet(struct var*, const char*); 1042 extern void set_pwd(struct var*, const char*); 1043 extern void set_screen(struct var*, const char*); 1044 extern void set_sender(struct var*, const char*); 1045 extern void set_sendmail(struct var*, const char*); 1046 extern void set_shell(struct var*, const char*); 1047 extern void set_spambody(struct var*, const char*); 1048 extern void set_spamtest(struct var*, const char*); 1049 extern void set_toplines(struct var*, const char*); 1050 extern void set_trace(struct var*, const char*); 1051 extern void set_user(struct var*, const char*); 1052 extern int setfolder(char*); 1053 extern FILE* setinput(struct msg*); 1054 extern void setptr(FILE*, off_t); 1055 extern void setscreensize(void); 1056 extern void settmp(const char*, int); 1057 extern int shell(char*); 1058 extern void shquote(Sfio_t*, char*); 1059 extern int size(struct msg*); 1060 extern char* skin(char*, unsigned long); 1061 extern char* snarf(char*, int*); 1062 extern int source(char**); 1063 extern int spammed(struct msg*); 1064 extern int split(char*); 1065 extern void sreset(void); 1066 extern int start_command(char*, int, int, int, char*, char*, char*); 1067 extern char* strlower(char*); 1068 extern char* strncopy(char*, const char*, size_t); 1069 extern char* struse(Sfio_t*); 1070 extern void tempinit(void); 1071 extern int top(struct msg*); 1072 extern void touchmsg(struct msg*); 1073 extern int ttyedit(int, int, const char*, char*, size_t); 1074 extern int ttyquery(int, int, const char*); 1075 extern int type(struct msg*); 1076 extern int unalias(char**); 1077 extern int undelete(struct msg*); 1078 extern int unread(char*); 1079 extern int unset(char**); 1080 extern int unstack(void); 1081 extern int upper(int); 1082 extern int userid(char*); 1083 extern int usermap(struct header*, int); 1084 extern char* username(void); 1085 extern char* varget(const char*); 1086 extern void varinit(void); 1087 extern char* varkeep(const char*); 1088 extern int varlist(int); 1089 extern int varset(const char*, const char*); 1090 extern int version(void*); 1091 extern int visual(struct msg*); 1092 extern int wait_command(int); 1093 extern char* wordnext(char**, char*); 1094 extern char* yankword(char*, char*); 1095 1096 /* 1097 * IMAP support 1098 */ 1099 1100 #define imap_name(p) ((p)[0]=='@'||strneq(p,"imap://",7)) 1101 1102 extern int imap_command(char*); 1103 extern int imap_copy(struct msg*, FILE*, Dt_t**, char*, unsigned long); 1104 extern void imap_exit(int); 1105 extern int imap_folders(void); 1106 extern int imap_get1(char**, unsigned long); 1107 extern int imap_mkdir(char*); 1108 extern void imap_msgflags(struct msg*, int, int); 1109 extern int imap_msglist(char*); 1110 extern void imap_printhead(int, int); 1111 extern void imap_quit(void); 1112 extern int imap_rename(char*, char*); 1113 extern int imap_rmdir(char*); 1114 extern int imap_save(struct msg*, char*); 1115 extern FILE* imap_setinput(struct msg*); 1116 extern int imap_setptr(char*, int); 1117 1118 #if _PACKAGE_ast 1119 1120 #define T(s) ERROR_translate(0,0,0,s) 1121 #define X(s) ERROR_catalog(s) 1122 1123 #else 1124 1125 #define T(s) (s) /* Dynamic translation string */ 1126 #define X(s) (s) /* Static translation string */ 1127 1128 #define imap_command(a) (-1) 1129 #define imap_copy(a,b,c,d,e) (-1) 1130 #define imap_exit(a) 1131 #define imap_folders() (-1) 1132 #define imap_get1(a,b) (-1) 1133 #define imap_mkdir(a) (-1) 1134 #define imap_msgflags(a,b,c) (-1) 1135 #define imap_msglist(a) (-1) 1136 #define imap_printhead(a) 1137 #define imap_quit() 1138 #define imap_rename(a,b) (-1) 1139 #define imap_rmdir(a) (-1) 1140 #define imap_save(a) (-1) 1141 #define imap_setinput(a) ((FILE*)0) 1142 1143 #endif 1144 1145 /* 1146 * MH support 1147 */ 1148 1149 extern int mh_setptr(char*, int); 1150