#pragma prototyped
#if _PACKAGE_ast
#include <ast.h>
#include <error.h>
#include <getopt.h>
#include <ls.h>
#include <sig.h>
#include <times.h>
#include <wait.h>
#else
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <limits.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
extern char* optarg;
extern int optind;
extern int opterr;
#endif
#include <cdt.h>
#include <ctype.h>
#include <errno.h>
#include <mime.h>
#include <setjmp.h>
#include <stdio.h>
#include "local.h"
#define APPEND_MAILBOX 1
#if defined(SFIO_VERSION) && defined(SF_READ) && defined(SF_WRITE)
#define MORE_DISCIPLINE 1
#endif
#define CALL(f) (*(state.folder==FIMAP?imap_##f:f))
#define TRACE(c) (state.trace|=(1<<((c)-'a')))
#define TRACING(c) (state.trace&(1<<((c)-'a')))
#define sig_t Sig_handler_t
#define holdsigs() sigcritical(SIG_REG_EXEC)
#define relsesigs() sigcritical(SIG_REG_POP)
#define initargs(ap) ((ap)->argp=(ap)->argv)
#define endargs(ap) (*(ap)->argp=0,(ap)->argp-(ap)->argv)
#if MORE_DISCIPLINE
#define moretop() (state.more.match=0,state.more.row=state.more.col=1)
#else
#define moretop()
#endif
#define shquote shellquote
#define ESCAPE '~'
#define NMLSIZE 1024
#define PATHSIZE MAXPATHLEN
#define LINESIZE (32*STRINGLEN)
#define HEADSIZE 128
#define LASTSIZE 256
#define STRINGSIZE ((unsigned)128)
#define MAILMODE (S_IRUSR|S_IWUSR)
#define METAFILE "%#&+/"
#define REGDEP 2
#define STRINGLEN 1024
#define MARGIN 72
#define REFLEN (12*MARGIN)
typedef struct msg {
int m_index;
short m_flag;
short m_offset;
long m_block;
off_t m_size;
off_t m_lines;
void* m_info;
} Msg_t;
#define FFILE 1
#define FIMAP 2
#define FMH 3
#define MBOX (1<<0)
#define MDELETE (1<<1)
#define MINIT (1<<2)
#define MMARK (1<<3)
#define MNEW (1<<4)
#define MNONE (1<<5)
#define MODIFY (1<<6)
#define MPRESERVE (1<<7)
#define MREAD (1<<8)
#define MSAVE (1<<9)
#define MSCAN (1<<10)
#define MSPAM (1<<11)
#define MSTATUS (1<<12)
#define MTOUCH (1<<13)
#define MUSED (1<<14)
#define MZOMBIE (1<<15)
#define blocknumber(off) ((int) ((off) / 4096))
#define blockoffset(off) ((int) ((off) % 4096))
#define blockposition(block,offset) ((off_t)(block) * 4096 + (offset))
typedef int (*Cmd_f)(void*);
struct cmd {
const char* c_name;
Cmd_f c_func;
unsigned long c_argtype;
unsigned long c_msgflag;
size_t c_msgmask;
const char* c_help;
};
#define c_minargs c_msgflag
#define c_maxargs c_msgmask
struct esc {
const char* e_name;
const char* e_help;
};
struct lab {
const char* name;
long type;
};
struct parse {
struct msg* mp;
struct header* hp;
Dt_t** ignore;
FILE* fp;
long count;
char* name;
char* data;
char* separator;
int length;
unsigned long flags;
unsigned long type;
char buf[LINESIZE];
};
#define MSGLIST 0
#define STRLIST 1
#define RAWLIST 2
#define NOLIST 3
#define NDMLIST 4
#define LISTMASK 07
#define A (1<<4)
#define C (1<<5)
#define D (1<<6)
#define E (1<<7)
#define I (1<<8)
#define L (1<<9)
#define M (1<<10)
#define N (1<<11)
#define P (1<<12)
#define R (1<<13)
#define S (1<<14)
#define W (1<<15)
#define Z (1L<<16)
#define MMNORM (MDELETE|MSAVE)
#define MMNDEL MDELETE
#define DEBUG (1<<0)
#define ERROR (1<<1)
#define FATAL (1<<2)
#define IDENTIFY (1<<3)
#define PANIC (1<<4)
#define PROMPT (1<<5)
#define SYSTEM (1<<6)
#define WARNING (1<<7)
struct headline {
char* l_from;
char* l_info;
char* l_date;
};
#define GALIAS (1<<0)
#define GALTERNATE (1<<1)
#define GBCC (1<<2)
#define GCC (1<<3)
#define GCOMMA (1<<4)
#define GCOMPARE (1<<5)
#define GDISPLAY (1<<6)
#define GDONE (1<<7)
#define GFIRST (1<<8)
#define GFROM (1<<9)
#define GINTERPOLATE (1<<10)
#define GLAST (1<<11)
#define GMAP (1<<12)
#define GMESSAGEID (1<<13)
#define GMETOO (1<<14)
#define GMIME (1L<<15)
#define GMISC (1L<<16)
#define GNEWS (1L<<17)
#define GNL (1L<<18)
#define GREFERENCES (1L<<19)
#define GREPLY (1L<<20)
#define GRULE (1L<<21)
#define GSEND (1L<<22)
#define GSENDER (1L<<23)
#define GSTACK (1L<<24)
#define GSTATUS (1L<<25)
#define GSUB (1L<<26)
#define GTO (1L<<27)
#define GUSER (1L<<28)
#define GCOMPOSE (GEDIT|GSTATUS)
#define GEDIT (GSTD|GMISC)
#define GEXTERN (GEDIT&~GBCC)
#define GMASK (GNAME|GDONE)
#define GNAME (GBCC|GCC|GTO)
#define GSTD (GNAME|GSUB)
struct var {
const char* name;
char** variable;
unsigned long flags;
const char* initialize;
void (*set)(struct var*, const char*);
const char* help;
};
struct list {
struct list* next;
char name[1];
};
struct name {
Dtlink_t link;
void* value;
unsigned long flags;
char name[1];
};
struct argvec {
char* argv[64 * 1024];
char** argp;
};
struct child {
struct child* link;
int pid;
short done;
short free;
};
struct file {
struct file* link;
FILE* fp;
int pid;
};
struct mhcontext {
int type;
unsigned long dot;
unsigned long next;
struct {
unsigned long dot;
unsigned long next;
} old;
};
typedef struct {
int type;
void* state;
} Imapcontext_t;
#define PART_application (1<<0)
#define PART_body (1<<1)
#define PART_disposition (1<<2)
#define PART_inline (1<<3)
#define PART_message (1<<4)
#define PART_text (1<<5)
typedef struct part {
struct part* next;
off_t offset;
off_t size;
off_t lines;
struct {
off_t offset;
off_t size;
} raw;
unsigned long flags;
int count;
char name[HEADSIZE];
char type[HEADSIZE];
char opts[HEADSIZE];
char code[HEADSIZE];
} Part_t;
struct bound {
struct bound* next;
int size;
char data[1];
};
struct header {
unsigned long h_flags;
Dt_t* h_names;
char** h_options;
char* h_subject;
char* h_first;
char* h_messageid;
char* h_references;
struct {
struct list* head;
struct list* tail;
} h_misc;
unsigned long h_clear;
};
struct dict {
Dtdisc_t disc;
unsigned long flags;
Dt_t* next;
};
struct match {
struct match* next;
int length;
int beg;
int mid;
int end;
char string[1];
};
struct linematch {
int minline;
unsigned char beg[256];
unsigned char mid[256];
unsigned char end[256];
struct match* match;
struct match* last;
};
struct sendand {
struct sendand* next;
char* head;
char* pattern;
unsigned long flags;
};
struct sendor {
struct sendor* next;
struct sendand sendand;
};
struct sender {
struct sender* next;
struct sendor sendor;
char address[1];
};
#define LOOKUP 0
#define COPY (1<<0)
#define CREATE (1<<1)
#define DELETE (1<<2)
#define IGNORECASE (1<<3)
#define INSERT (1<<4)
#define OBJECT (1<<5)
#define STACK (1<<6)
#define dictflags(p) (((struct dict*)(*(p))->disc)->flags)
#define HIT (1<<0)
#define IGNORE (1<<1)
#define RETAIN (1<<2)
#define FOLLOWUP (1<<0)
#define HEADERS (1<<1)
#define INTERPOLATE (1<<2)
#define MARK (1<<3)
#define REPLY (1<<4)
#define TEOL 0
#define TNUMBER 1
#define TDASH 2
#define TSTRING 3
#define TDOT 4
#define TUP 5
#define TDOLLAR 6
#define TSTAR 7
#define TOPEN 8
#define TCLOSE 9
#define TPLUS 10
#define TERROR 11
#define RECEIVE (-1)
#define SEND (1)
#define setexit() do { \
int x = setjmp(state.jump.sr); \
if (x) sigunblock(x); \
} while(0)
#define reset(x) longjmp(state.jump.sr, x)
#define undelete mail_undelete
#define NSPACE 25
struct strings {
char* s_topfree;
char* s_nextfree;
unsigned int s_nleft;
};
typedef struct {
const char* version;
const char* license;
char* on;
const struct cmd* cmdtab;
int cmdnum;
const struct esc* esctab;
int escnum;
const struct var* vartab;
int varnum;
const struct lab* hdrtab;
int hdrnum;
unsigned long askheaders;
int clobber;
int cmdline;
int colmod;
int cond;
int edit;
int incorporating;
int folder;
int hung;
int loading;
int mode;
int noreset;
int onstack;
int readonly;
int realscreenheight;
int sawcom;
int screenheight;
int screenwidth;
int scroll;
int senderr;
int sourcing;
int startup;
int stopreset;
FILE* input;
off_t mailsize;
int lexnumber;
char lexstring[STRINGLEN];
int regretp;
int regretstack[REGDEP];
char* string_stack[REGDEP];
int numberstack[REGDEP];
char number[16];
char counts[32];
unsigned long trace;
unsigned long editheaders;
struct child* children;
struct cmd* cmd;
struct file* files;
struct linematch* bodymatch;
struct sender* sender;
struct stat openstat;
Dt_t* ignore;
Dt_t* saveignore;
Dt_t* ignoreall;
Dt_t* aliases;
Dt_t* userid;
Dt_t* stacked;
struct strings stringdope[NSPACE];
struct {
sig_t sigint;
sig_t sighup;
sig_t sigtstp;
sig_t sigttou;
sig_t sigttin;
FILE* fp;
int hadintr;
jmp_buf work;
int working;
jmp_buf abort;
} collect;
struct {
jmp_buf header;
jmp_buf sr;
jmp_buf sigpipe;
} jump;
struct {
char bang[LASTSIZE];
char scan[LASTSIZE];
} last;
struct {
int count;
int inbox;
Imapcontext_t imap;
struct mhcontext mh;
int size;
int* vec;
FILE* ap;
FILE* ip;
FILE* op;
struct msg* active;
struct msg* context;
struct msg* dot;
struct msg* list;
} msg;
struct {
char pwd[2][PATHSIZE];
char mail[PATHSIZE];
char path[PATHSIZE];
char prev[PATHSIZE];
Sfio_t* buf;
Sfio_t* move;
Sfio_t* part;
Sfio_t* temp;
} path;
struct {
int sp;
struct {
FILE* input;
int cond;
int loading;
} stack[NOFILE];
} source;
struct more {
#if MORE_DISCIPLINE
Sfdisc_t disc;
int row;
int col;
int match;
char pattern[HEADSIZE];
char tmp[HEADSIZE];
#endif
int discipline;
int init;
} more;
struct state_part {
Mimedisc_t disc;
Mime_t* mime;
Part_t* head;
Part_t global;
int init;
struct {
int multi;
int count;
Part_t* head;
Part_t* tail;
struct bound* boundary;
} in;
struct {
int multi;
int boundlen;
char boundary[HEADSIZE];
} out;
} part;
struct {
char edit[256];
char mail[256];
char mesg[256];
char more[256];
char quit[256];
char* dir;
} tmp;
struct
{
char* allnet;
char* append;
char* askbcc;
char* askcc;
char* askheaders;
char* asksub;
char* attachments;
char* autoinc;
char* autoprint;
char* bang;
char* cdpath;
char* cmd;
char* coprocess;
long crt;
char* dead;
char* debug;
char* domain;
char* dot;
char* editheaders;
char* editor;
char* escape;
char* fixedheaders;
char* flipr;
char* folder;
char* followup;
char* header;
char* headerbotch;
char* headfake;
char* hold;
char* home;
char* hostname;
char* ignore;
char* ignoreeof;
char* imap;
char* inbox;
char* indentprefix;
char* interactive;
char* justcheck;
long justfrom;
char* justheaders;
char* keep;
char* keepsave;
char* lister;
char* local;
char* lock;
char* log;
char* mail;
char* mailcap;
char* mailrc;
char* master;
char* mbox;
char* metoo;
char* more;
char* news;
char* oldpwd;
char* onehop;
char* outfolder;
char* page;
char* pager;
char* prompt;
char* pwd;
char* quiet;
char* receive;
char* recent;
char* rule;
char* save;
long screen;
char* searchheaders;
char* sender;
char* sendheaders;
char* sendmail;
char* sendwait;
char* shell;
char* showto;
char* Sign;
char* sign;
char* signature;
char* smtp;
char* spam;
char* spambody;
long spamdelay;
char* spamfrom;
char* spamfromok;
char* spamlog;
char* spamsub;
char* spamsubhead;
long spamtest;
char* spamto;
char* spamtook;
char* spamvia;
char* spamviaok;
long toplines;
char* trace;
char* user;
char* verbose;
char* visual;
} var;
} State_t;
extern State_t state;
extern int Blast(struct msg*);
extern int Copy(char*);
extern int Followup(struct msg*);
extern int From(struct msg*);
extern int Get(char**);
extern int Join(struct msg*);
extern int More(struct msg*);
extern int Reply(struct msg*);
extern int Save(char*);
extern int Split(char*);
extern int Type(struct msg*);
extern int addarg(struct argvec*, const char*);
extern int alias(char**);
extern void alter(char*);
extern int alternates(char**);
extern void announce();
extern int anyof(char*, char*);
extern int blankline(char*);
extern int blast(struct msg*);
extern void boundary(void);
extern int capability(char**);
extern int cd(char**);
extern int check(int, int);
extern int cmdcopy(char*);
extern int cmddelete(struct msg*);
extern int cmdelse(void);
extern int cmdendif(void);
extern int cmdexit(int);
extern int cmdif(char**);
extern int cmdmkdir(char**);
extern int cmdpipe(char*);
extern int cmdquit(void);
extern int cmdrename(char**);
extern int cmdrmdir(char**);
extern int cmdtouch(char*);
extern int cmdwrite(char*);
extern FILE* collect(struct header*, unsigned long);
extern void commands(void);
extern int copy(struct msg*, FILE*, Dt_t**, char*, unsigned long);
extern char* counts(int, off_t, off_t);
extern void dictclear(Dt_t**);
extern void dictreset(void);
extern struct name* dictsearch(Dt_t**, const char*, int);
extern int dictwalk(Dt_t**, int(*)(Dt_t*, void*, void*), void*);
extern int deltype(struct msg*);
extern void demail(void);
extern char* detract(struct header*, unsigned long);
extern int dot(void);
extern int duplicate(char*);
extern int echo(char**);
extern int editor(struct msg*);
extern int execute(char*, int);
extern char* expand(char*, int);
extern void extract(struct header*, unsigned long, char*);
extern void fileclear(void);
extern int fileclose(FILE*);
extern FILE* filefd(int, char*);
extern int filecopy(const char*, FILE*, const char*, FILE*, FILE*, off_t, off_t*, off_t*, unsigned long);
extern int filelock(const char*, FILE*, int);
extern FILE* fileopen(char*, char*);
extern off_t filesize(FILE*);
extern FILE* filestd(char*, char*);
extern FILE* filetemp(char*, int, int, int);
extern int filetrunc(FILE*);
extern int first(int, int);
extern int folder(char**);
extern struct msg* folderinfo(int);
extern int folders(void);
extern int followup(struct msg*);
extern void free_command(int);
extern int from(struct msg*);
extern int get(char**);
extern void getargs(struct argvec*, char*);
extern int getfolder(char*, size_t);
extern int getmsglist(char*, unsigned long);
extern char* grab(struct msg*, unsigned long, char*);
extern void grabedit(struct header*, unsigned long);
extern void headclear(struct header*, unsigned long);
extern int headers(struct msg*);
extern int headget(struct parse*);
extern int headout(FILE*, struct header*, unsigned long);
extern int headset(struct parse*, struct msg*, FILE*, struct header*, Dt_t**, unsigned long);
extern int help(char**);
extern int ignore(char**);
extern int ignored(Dt_t**, const char*);
extern int incorporate(void);
extern int incfile(void);
extern int isall(const char*);
extern char* iscmd(char*);
extern int isdate(char*);
extern int isdir(char*);
extern int ishead(char*, int);
extern int isreg(char*);
extern int join(struct msg*);
extern int license(void*);
extern int list(void);
extern void load(char*);
extern char* localize(char*);
extern int lower(int);
extern int mail(char*);
extern char* mailbox(const char*, const char*);
extern int map(char*);
extern int mark(char*);
extern int mboxit(char*);
extern void mhgetcontext(struct mhcontext*, const char*, int);
extern void mhputcontext(struct mhcontext*, const char*);
extern int mime(int);
extern int more(struct msg*);
extern void msgflags(struct msg*, int, int);
extern struct msg* newmsg(off_t offset);
extern int next(struct msg*);
extern char* normalize(char*, unsigned long, char*, size_t);
extern void note(int, const char*, ...);
extern int notyet(char*);
extern int null(int);
extern void parse(struct msg*, char*, struct headline*, char*, size_t);
extern FILE* pipeopen(char*, char*);
extern int preserve(char*);
extern int puthead(FILE*, struct header*, int);
extern int putline(FILE*, char*);
extern int pwd(void);
extern void quit(void);
extern int readline(FILE*, char*, int);
extern char* record(char*, unsigned long);
extern int regular(FILE*);
extern int reply(struct msg*);
extern int replyall(struct msg*);
extern int replysender(struct msg*);
extern void resume(int);
extern int retain(char**);
extern int rm(char*);
extern int run_command(char*, int, int, int, char*, char*, char*);
extern FILE* run_editor(FILE*, off_t, struct header*, int, int);
extern char* salloc(int);
extern int save(char*);
extern void savedeadletter(FILE*);
extern int saveignore(char**);
extern int saveretain(char**);
extern char* savestr(char*);
extern int scan(char**);
extern int scroll(char*);
extern int sender(char*, int);
extern void sendmail(struct header*, unsigned long);
extern int sendsmtp(FILE*, char*, char**, off_t);
extern int set(char**);
extern void set_askbcc(struct var*, const char*);
extern void set_askcc(struct var*, const char*);
extern void set_askheaders(struct var*, const char*);
extern void set_asksub(struct var*, const char*);
extern void set_coprocess(struct var*, const char*);
extern void set_crt(struct var*, const char*);
extern void set_editheaders(struct var*, const char*);
extern void set_justfrom(struct var*, const char*);
extern void set_list(struct var*, const char*);
extern void set_mail(struct var*, const char*);
extern void set_mailcap(struct var*, const char*);
extern void set_more(struct var*, const char*);
extern void set_news(struct var*, const char*);
extern void set_notyet(struct var*, const char*);
extern void set_pwd(struct var*, const char*);
extern void set_screen(struct var*, const char*);
extern void set_sender(struct var*, const char*);
extern void set_sendmail(struct var*, const char*);
extern void set_shell(struct var*, const char*);
extern void set_spambody(struct var*, const char*);
extern void set_spamtest(struct var*, const char*);
extern void set_toplines(struct var*, const char*);
extern void set_trace(struct var*, const char*);
extern void set_user(struct var*, const char*);
extern int setfolder(char*);
extern FILE* setinput(struct msg*);
extern void setptr(FILE*, off_t);
extern void setscreensize(void);
extern void settmp(const char*, int);
extern int shell(char*);
extern void shquote(Sfio_t*, char*);
extern int size(struct msg*);
extern char* skin(char*, unsigned long);
extern char* snarf(char*, int*);
extern int source(char**);
extern int spammed(struct msg*);
extern int split(char*);
extern void sreset(void);
extern int start_command(char*, int, int, int, char*, char*, char*);
extern char* strlower(char*);
extern char* strncopy(char*, const char*, size_t);
extern char* struse(Sfio_t*);
extern void tempinit(void);
extern int top(struct msg*);
extern void touchmsg(struct msg*);
extern int ttyedit(int, int, const char*, char*, size_t);
extern int ttyquery(int, int, const char*);
extern int type(struct msg*);
extern int unalias(char**);
extern int undelete(struct msg*);
extern int unread(char*);
extern int unset(char**);
extern int unstack(void);
extern int upper(int);
extern int userid(char*);
extern int usermap(struct header*, int);
extern char* username(void);
extern char* varget(const char*);
extern void varinit(void);
extern char* varkeep(const char*);
extern int varlist(int);
extern int varset(const char*, const char*);
extern int version(void*);
extern int visual(struct msg*);
extern int wait_command(int);
extern char* wordnext(char**, char*);
extern char* yankword(char*, char*);
#define imap_name(p) ((p)[0]=='@'||strneq(p,"imap:
extern int imap_command(char*);
extern int imap_copy(struct msg*, FILE*, Dt_t**, char*, unsigned long);
extern void imap_exit(int);
extern int imap_folders(void);
extern int imap_get1(char**, unsigned long);
extern int imap_mkdir(char*);
extern void imap_msgflags(struct msg*, int, int);
extern int imap_msglist(char*);
extern void imap_printhead(int, int);
extern void imap_quit(void);
extern int imap_rename(char*, char*);
extern int imap_rmdir(char*);
extern int imap_save(struct msg*, char*);
extern FILE* imap_setinput(struct msg*);
extern int imap_setptr(char*, int);
#if _PACKAGE_ast
#define T(s) ERROR_translate(0,0,0,s)
#define X(s) ERROR_catalog(s)
#else
#define T(s) (s)
#define X(s) (s)
#define imap_command(a) (-1)
#define imap_copy(a,b,c,d,e) (-1)
#define imap_exit(a)
#define imap_folders() (-1)
#define imap_get1(a,b) (-1)
#define imap_mkdir(a) (-1)
#define imap_msgflags(a,b,c) (-1)
#define imap_msglist(a) (-1)
#define imap_printhead(a)
#define imap_quit()
#define imap_rename(a,b) (-1)
#define imap_rmdir(a) (-1)
#define imap_save(a) (-1)
#define imap_setinput(a) ((FILE*)0)
#endif
extern int mh_setptr(char*, int);