1 /*********************************************************************** 2 * * 3 * This software is part of the BSD package * 4 *Copyright (c) 1978-2013 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 #define SIGN (1<<5) 550 551 /* 552 * Token values returned by the scanner used for argument lists. 553 */ 554 555 #define TEOL 0 /* End of the command line */ 556 #define TNUMBER 1 /* A message number */ 557 #define TDASH 2 /* A simple dash */ 558 #define TSTRING 3 /* A string (possibly containing -) */ 559 #define TDOT 4 /* A "." */ 560 #define TUP 5 /* An "^" */ 561 #define TDOLLAR 6 /* A "$" */ 562 #define TSTAR 7 /* A "*" */ 563 #define TOPEN 8 /* An '(' */ 564 #define TCLOSE 9 /* A ')' */ 565 #define TPLUS 10 /* A '+' */ 566 #define TERROR 11 /* A lexical error */ 567 568 /* 569 * Constants for conditional commands. These describe whether 570 * we should be executing stuff or not. 571 */ 572 573 #define RECEIVE (-1) /* Execute in receive mode only */ 574 #define SEND (1) /* Execute in send mode only */ 575 576 /* 577 * Kludges to handle the change from setexit / reset to setjmp / longjmp 578 */ 579 580 #define setexit() do { \ 581 int x = setjmp(state.jump.sr); \ 582 if (x) sigunblock(x); \ 583 } while(0) 584 #define reset(x) longjmp(state.jump.sr, x) 585 586 /* 587 * <unistd.h> etc encroachment 588 * we asked for extentions -- and now pay for it ... 589 */ 590 591 #define undelete mail_undelete 592 593 /* 594 * The pointers for the string allocation routines, 595 * there are NSPACE independent areas. 596 * The first holds STRINGSIZE bytes, the next 597 * twice as much, and so on. 598 */ 599 600 #define NSPACE 25 /* Total number of string spaces */ 601 struct strings { 602 char* s_topfree; /* Beginning of this area */ 603 char* s_nextfree; /* Next alloctable place here */ 604 unsigned int s_nleft; /* Number of bytes left here */ 605 }; 606 607 typedef struct { 608 const char* version; /* Version string */ 609 const char* license; /* License text */ 610 char* on; /* Variable on value */ 611 const struct cmd* cmdtab; /* Command table */ 612 int cmdnum; /* Number of commands */ 613 const struct esc* esctab; /* Escape command table */ 614 int escnum; /* Number of escape commands */ 615 const struct var* vartab; /* Variable table */ 616 int varnum; /* Number of variables */ 617 const struct lab* hdrtab; /* Header label table */ 618 int hdrnum; /* Number of header labels */ 619 unsigned long askheaders; /* Ask for these headers */ 620 621 /* the rest are implicitly initialized */ 622 623 int clobber; /* Last command had ! */ 624 int cmdline; /* Currently reading cmd line options */ 625 int colmod; /* Mark bit */ 626 int cond; /* Current state of conditional exc. */ 627 int edit; /* Indicates editing a file */ 628 int incorporating; /* Executing incorporate command */ 629 int folder; /* Folder type */ 630 int hung; /* Op hung til alarm */ 631 int loading; /* Loading user definitions */ 632 int mode; /* SEND or RECEIVE */ 633 int noreset; /* String resets suspended */ 634 int onstack; /* salloc() != malloc() */ 635 int readonly; /* Will be unable to rewrite file */ 636 int realscreenheight; /* Real screen height */ 637 int sawcom; /* Set after first command */ 638 int screenheight; /* Screen height, or best guess */ 639 int screenwidth; /* Screen width, or best guess */ 640 int scroll; /* Current scroll size */ 641 int senderr; /* An error while checking */ 642 int sourcing; /* Currently reading variant file */ 643 int startup; /* Listing startup headers */ 644 int stopreset; /* Reset on stop */ 645 646 FILE* input; /* Current command input file */ 647 off_t mailsize; /* Size of system mailbox */ 648 int lexnumber; /* Number of TNUMBER from scan() */ 649 char lexstring[STRINGLEN]; /* String from TSTRING, scan() */ 650 int regretp; /* Pointer to TOS of regret tokens */ 651 int regretstack[REGDEP]; /* Stack of regretted tokens */ 652 char* string_stack[REGDEP]; /* Stack of regretted strings */ 653 int numberstack[REGDEP]; /* Stack of regretted numbers */ 654 char number[16]; /* Temp variable number string */ 655 char counts[32]; /* Temp counts number string */ 656 657 unsigned long trace; /* Trace bits */ 658 unsigned long editheaders; /* These headers in edit template */ 659 struct child* children; /* Child list */ 660 struct cmd* cmd; /* Current command table entry */ 661 struct file* files; /* fileopen() list */ 662 struct linematch* bodymatch; /* compiled state.var.spambody */ 663 struct sender* sender; /* compiled state.var.sender */ 664 struct stat openstat; /* fileopen stat */ 665 Dt_t* ignore; /* Ignored fields */ 666 Dt_t* saveignore; /* Ignored fields on save to folder */ 667 Dt_t* ignoreall; /* Special: ignore all headers */ 668 Dt_t* aliases; /* aliases */ 669 Dt_t* userid; /* User name -> id map */ 670 Dt_t* stacked; /* STACK dict list */ 671 672 struct strings stringdope[NSPACE]; 673 674 struct { 675 sig_t sigint; /* Previous SIGINT value */ 676 sig_t sighup; /* Previous SIGHUP value */ 677 sig_t sigtstp; /* Previous SIGTSTP value */ 678 sig_t sigttou; /* Previous SIGTTOU value */ 679 sig_t sigttin; /* Previous SIGTTIN value */ 680 FILE* fp; /* File for saving away */ 681 int hadintr; /* Have seen one SIGINT so far */ 682 jmp_buf work; /* To get back to work */ 683 int working; /* Whether to long jump */ 684 jmp_buf abort; /* To end collection with error */ 685 } collect; 686 687 struct { 688 jmp_buf header; /* Printing headers */ 689 jmp_buf sr; /* set/reset longjmp buffer */ 690 jmp_buf sigpipe; /* SIGPIPE longjmp buffer */ 691 } jump; 692 693 struct { 694 char bang[LASTSIZE]; /* Last ! command */ 695 char scan[LASTSIZE]; /* Last message search string */ 696 } last; 697 698 struct { 699 int count; /* Count of messages read in */ 700 int inbox; /* Current folder mh state.var.inbox */ 701 Imapcontext_t imap; /* imap message format */ 702 struct mhcontext mh; /* mh message format */ 703 int size; /* Max messages in vector */ 704 int* vec; /* Current message vector */ 705 FILE* ap; /* Actual file pointer */ 706 FILE* ip; /* Input temp file buffer */ 707 FILE* op; /* Output temp file buffer */ 708 struct msg* active; /* ip points to this message */ 709 struct msg* context; /* Folder read context */ 710 struct msg* dot; /* Pointer to current message */ 711 struct msg* list; /* The actual message structure */ 712 } msg; 713 714 struct { 715 char pwd[2][PATHSIZE]; /* pwd and oldpwd paths */ 716 char mail[PATHSIZE]; /* Name of current file */ 717 char path[PATHSIZE]; /* Very temporary fixed path buffer */ 718 char prev[PATHSIZE]; /* Name of previous file */ 719 Sfio_t* buf; /* Very temporary name buffer */ 720 Sfio_t* move; /* Very temporary name buffer */ 721 Sfio_t* part; /* Very temporary name buffer */ 722 Sfio_t* temp; /* Very temporary name buffer */ 723 } path; 724 725 struct { 726 int sp; /* Top of stack */ 727 struct { 728 FILE* input; /* Saved state.input */ 729 int cond; /* Saved state.cond */ 730 int loading; /* Saved state.loading */ 731 } stack[NOFILE]; 732 } source; 733 734 struct more { 735 #if MORE_DISCIPLINE 736 Sfdisc_t disc; 737 int row; 738 int col; 739 int match; 740 char pattern[HEADSIZE]; 741 char tmp[HEADSIZE]; 742 #endif 743 int discipline; 744 int init; 745 } more; 746 747 struct state_part { 748 749 Mimedisc_t disc; 750 Mime_t* mime; 751 Part_t* head; 752 Part_t global; 753 int init; 754 755 struct { 756 int multi; 757 int count; 758 Part_t* head; 759 Part_t* tail; 760 struct bound* boundary; 761 } in; 762 763 struct { 764 int multi; 765 int boundlen; 766 char boundary[HEADSIZE]; 767 } out; 768 769 } part; 770 771 struct { 772 char conv[256]; 773 char edit[256]; 774 char head[8*1024]; 775 char mail[256]; 776 char mesg[256]; 777 char more[256]; 778 char quit[256]; 779 char* dir; 780 } tmp; 781 782 struct 783 { 784 char* allnet; 785 char* append; 786 char* askbcc; 787 char* askcc; 788 char* askheaders; 789 char* asksub; 790 char* attachments; 791 char* autoinc; 792 char* autoprint; 793 char* autosign; 794 char* bang; 795 char* cdpath; 796 char* cmd; 797 char* convertheaders; 798 char* coprocess; 799 long crt; 800 char* dead; 801 char* debug; 802 char* domain; 803 char* dot; 804 char* editheaders; 805 char* editor; 806 char* escape; 807 char* fixedheaders; 808 char* flipr; 809 char* folder; 810 char* followup; 811 char* header; 812 char* headerbotch; 813 char* headfake; 814 char* hold; 815 char* home; 816 char* hostname; 817 char* ignore; 818 char* ignoreeof; 819 char* imap; 820 char* inbox; 821 char* indentprefix; 822 char* interactive; 823 char* justcheck; 824 long justfrom; 825 char* justheaders; 826 char* keep; 827 char* keepsave; 828 char* lister; 829 char* local; 830 char* lock; 831 char* log; 832 char* mail; 833 char* mailcap; 834 char* mailrc; 835 char* master; 836 char* mbox; 837 char* metoo; 838 char* more; 839 char* news; 840 char* oldpwd; 841 char* onehop; 842 char* outfolder; 843 char* page; 844 char* pager; 845 char* prompt; 846 char* pwd; 847 char* quiet; 848 char* receive; 849 char* recent; 850 char* rule; 851 char* save; 852 long screen; 853 char* searchheaders; 854 char* sender; 855 char* sendheaders; 856 char* sendmail; 857 char* sendwait; 858 char* shell; 859 char* showto; 860 char* Sign; 861 char* sign; 862 char* signature; 863 char* smtp; 864 char* spam; 865 char* spambody; 866 long spamdelay; 867 char* spamfrom; 868 char* spamfromok; 869 char* spamlog; 870 char* spamsub; 871 char* spamsubhead; 872 long spamtest; 873 char* spamto; 874 char* spamtook; 875 char* spamvia; 876 char* spamviaok; 877 long toplines; 878 char* trace; 879 char* user; 880 char* verbose; 881 char* visual; 882 } var; 883 884 } State_t; 885 886 extern State_t state; 887 888 extern int Blast(struct msg*); 889 extern int Copy(char*); 890 extern int Followup(struct msg*); 891 extern int From(struct msg*); 892 extern int Get(char**); 893 extern int Join(struct msg*); 894 extern int More(struct msg*); 895 extern int Reply(struct msg*); 896 extern int Save(char*); 897 extern int Split(char*); 898 extern int Type(struct msg*); 899 extern int addarg(struct argvec*, const char*); 900 extern int alias(char**); 901 extern void alter(char*); 902 extern int alternates(char**); 903 extern void announce(); 904 extern int anyof(char*, char*); 905 extern int blankline(char*); 906 extern int blast(struct msg*); 907 extern void boundary(void); 908 extern int capability(char**); 909 extern int cd(char**); 910 extern int check(int, int); 911 extern int cmdcopy(char*); 912 extern int cmddelete(struct msg*); 913 extern int cmdelse(void); 914 extern int cmdendif(void); 915 extern int cmdexit(int); 916 extern int cmdif(char**); 917 extern int cmdmkdir(char**); 918 extern int cmdpipe(char*); 919 extern int cmdquit(void); 920 extern int cmdrename(char**); 921 extern int cmdrmdir(char**); 922 extern int cmdtouch(char*); 923 extern int cmdwrite(char*); 924 extern FILE* collect(struct header*, unsigned long); 925 extern void commands(void); 926 extern int copy(struct msg*, FILE*, Dt_t**, char*, unsigned long); 927 extern char* counts(int, off_t, off_t); 928 extern void dictclear(Dt_t**); 929 extern void dictreset(void); 930 extern struct name* dictsearch(Dt_t**, const char*, int); 931 extern int dictwalk(Dt_t**, int(*)(Dt_t*, void*, void*), void*); 932 extern int deltype(struct msg*); 933 extern void demail(void); 934 extern char* detract(struct header*, unsigned long); 935 extern int dot(void); 936 extern int duplicate(char*); 937 extern int echo(char**); 938 extern int editor(struct msg*); 939 extern int execute(char*, int); 940 extern char* expand(char*, int); 941 extern void extract(struct header*, unsigned long, char*); 942 extern void fileclear(void); 943 extern int fileclose(FILE*); 944 extern FILE* filefd(int, char*); 945 extern int filecopy(const char*, FILE*, const char*, FILE*, FILE*, off_t, off_t*, off_t*, unsigned long); 946 extern int filelock(const char*, FILE*, int); 947 extern FILE* fileopen(char*, char*); 948 extern off_t filesize(FILE*); 949 extern FILE* filestd(char*, char*); 950 extern FILE* filetemp(char*, int, int, int); 951 extern int filetrunc(FILE*); 952 extern int first(int, int); 953 extern int folder(char**); 954 extern struct msg* folderinfo(int); 955 extern int folders(void); 956 extern int followup(struct msg*); 957 extern void free_command(int); 958 extern int from(struct msg*); 959 extern int get(char**); 960 extern void getargs(struct argvec*, char*); 961 extern int getfolder(char*, size_t); 962 extern int getmsglist(char*, unsigned long); 963 extern char* grab(struct msg*, unsigned long, char*); 964 extern void grabedit(struct header*, unsigned long); 965 extern void headclear(struct header*, unsigned long); 966 extern int headers(struct msg*); 967 extern int headget(struct parse*); 968 extern int headout(FILE*, struct header*, unsigned long); 969 extern int headset(struct parse*, struct msg*, FILE*, struct header*, Dt_t**, unsigned long); 970 extern int help(char**); 971 extern int ignore(char**); 972 extern int ignored(Dt_t**, const char*); 973 extern int incorporate(void); 974 extern int incfile(void); 975 extern int isall(const char*); 976 extern char* iscmd(char*); 977 extern int isdate(char*); 978 extern int isdir(char*); 979 extern int ishead(char*, int); 980 extern int isreg(char*); 981 extern int join(struct msg*); 982 extern int license(void*); 983 extern int list(void); 984 extern void load(char*); 985 extern char* localize(char*); 986 extern int lower(int); 987 extern int mail(char*); 988 extern char* mailbox(const char*, const char*); 989 extern int map(char*); 990 extern int mark(char*); 991 extern int mboxit(char*); 992 extern void mhgetcontext(struct mhcontext*, const char*, int); 993 extern void mhputcontext(struct mhcontext*, const char*); 994 extern int mime(int); 995 extern int more(struct msg*); 996 extern void msgflags(struct msg*, int, int); 997 extern struct msg* newmsg(off_t offset); 998 extern int next(struct msg*); 999 extern char* normalize(char*, unsigned long, char*, size_t); 1000 extern void note(int, const char*, ...); 1001 extern int notyet(char*); 1002 extern int null(int); 1003 extern void parse(struct msg*, char*, struct headline*, char*, size_t); 1004 extern FILE* pipeopen(char*, char*); 1005 extern int preserve(char*); 1006 extern int puthead(FILE*, struct header*, int); 1007 extern int putline(FILE*, char*); 1008 extern int pwd(void); 1009 extern void quit(void); 1010 extern int readline(FILE*, char*, int); 1011 extern char* record(char*, unsigned long); 1012 extern int regular(FILE*); 1013 extern int reply(struct msg*); 1014 extern int replyall(struct msg*); 1015 extern int replysender(struct msg*); 1016 extern void resume(int); 1017 extern int retain(char**); 1018 extern int rm(char*); 1019 extern int run_command(char*, int, int, int, char*, char*, char*); 1020 extern FILE* run_editor(FILE*, off_t, struct header*, int, int); 1021 extern char* salloc(int); 1022 extern int save(char*); 1023 extern void savedeadletter(FILE*); 1024 extern int saveignore(char**); 1025 extern int saveretain(char**); 1026 extern char* savestr(char*); 1027 extern int scan(char**); 1028 extern int scroll(char*); 1029 extern int sender(char*, int); 1030 extern void sendmail(struct header*, unsigned long); 1031 extern int sendsmtp(FILE*, char*, char**, off_t); 1032 extern int set(char**); 1033 extern void set_askbcc(struct var*, const char*); 1034 extern void set_askcc(struct var*, const char*); 1035 extern void set_askheaders(struct var*, const char*); 1036 extern void set_asksub(struct var*, const char*); 1037 extern void set_coprocess(struct var*, const char*); 1038 extern void set_crt(struct var*, const char*); 1039 extern void set_editheaders(struct var*, const char*); 1040 extern void set_justfrom(struct var*, const char*); 1041 extern void set_list(struct var*, const char*); 1042 extern void set_mail(struct var*, const char*); 1043 extern void set_mailcap(struct var*, const char*); 1044 extern void set_more(struct var*, const char*); 1045 extern void set_news(struct var*, const char*); 1046 extern void set_notyet(struct var*, const char*); 1047 extern void set_pwd(struct var*, const char*); 1048 extern void set_screen(struct var*, const char*); 1049 extern void set_sender(struct var*, const char*); 1050 extern void set_sendmail(struct var*, const char*); 1051 extern void set_shell(struct var*, const char*); 1052 extern void set_spambody(struct var*, const char*); 1053 extern void set_spamtest(struct var*, const char*); 1054 extern void set_toplines(struct var*, const char*); 1055 extern void set_trace(struct var*, const char*); 1056 extern void set_user(struct var*, const char*); 1057 extern int setfolder(char*); 1058 extern FILE* setinput(struct msg*); 1059 extern void setptr(FILE*, off_t); 1060 extern void setscreensize(void); 1061 extern void settmp(const char*, int); 1062 extern int shell(char*); 1063 extern void shquote(Sfio_t*, char*); 1064 extern int size(struct msg*); 1065 extern char* skin(char*, unsigned long); 1066 extern char* snarf(char*, int*); 1067 extern int source(char**); 1068 extern int spammed(struct msg*); 1069 extern int split(char*); 1070 extern void sreset(void); 1071 extern int start_command(char*, int, int, int, char*, char*, char*); 1072 extern char* strlower(char*); 1073 extern char* strncopy(char*, const char*, size_t); 1074 extern char* struse(Sfio_t*); 1075 extern void tempinit(void); 1076 extern int top(struct msg*); 1077 extern void touchmsg(struct msg*); 1078 extern int ttyedit(int, int, const char*, char*, size_t); 1079 extern int ttyquery(int, int, const char*); 1080 extern int type(struct msg*); 1081 extern int unalias(char**); 1082 extern int undelete(struct msg*); 1083 extern int unread(char*); 1084 extern int unset(char**); 1085 extern int unstack(void); 1086 extern int upper(int); 1087 extern int userid(char*); 1088 extern int usermap(struct header*, int); 1089 extern char* username(void); 1090 extern char* varget(const char*); 1091 extern void varinit(void); 1092 extern char* varkeep(const char*); 1093 extern int varlist(int); 1094 extern int varset(const char*, const char*); 1095 extern int version(void*); 1096 extern int visual(struct msg*); 1097 extern int wait_command(int); 1098 extern char* wordnext(char**, char*); 1099 extern char* yankword(char*, char*); 1100 1101 /* 1102 * IMAP support 1103 */ 1104 1105 #define imap_name(p) ((p)[0]=='@'||strneq(p,"imap://",7)) 1106 1107 extern int imap_command(char*); 1108 extern int imap_copy(struct msg*, FILE*, Dt_t**, char*, unsigned long); 1109 extern void imap_exit(int); 1110 extern int imap_folders(void); 1111 extern int imap_get1(char**, unsigned long); 1112 extern int imap_mkdir(char*); 1113 extern void imap_msgflags(struct msg*, int, int); 1114 extern int imap_msglist(char*); 1115 extern void imap_printhead(int, int); 1116 extern void imap_quit(void); 1117 extern int imap_rename(char*, char*); 1118 extern int imap_rmdir(char*); 1119 extern int imap_save(struct msg*, char*); 1120 extern FILE* imap_setinput(struct msg*); 1121 extern int imap_setptr(char*, int); 1122 1123 #if _PACKAGE_ast 1124 1125 #define T(s) ERROR_translate(0,0,0,s) 1126 #define X(s) ERROR_catalog(s) 1127 1128 #else 1129 1130 #define T(s) (s) /* Dynamic translation string */ 1131 #define X(s) (s) /* Static translation string */ 1132 1133 #define imap_command(a) (-1) 1134 #define imap_copy(a,b,c,d,e) (-1) 1135 #define imap_exit(a) 1136 #define imap_folders() (-1) 1137 #define imap_get1(a,b) (-1) 1138 #define imap_mkdir(a) (-1) 1139 #define imap_msgflags(a,b,c) (-1) 1140 #define imap_msglist(a) (-1) 1141 #define imap_printhead(a) 1142 #define imap_quit() 1143 #define imap_rename(a,b) (-1) 1144 #define imap_rmdir(a) (-1) 1145 #define imap_save(a) (-1) 1146 #define imap_setinput(a) ((FILE*)0) 1147 1148 #endif 1149 1150 /* 1151 * MH support 1152 */ 1153 1154 extern int mh_setptr(char*, int); 1155