⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mailutil.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ======================================================================== * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  * ======================================================================== *//* * Program:	Mail utility * * Author:	Mark Crispin *		UW Technology *		University of Washington *		Seattle, WA  98195 *		Internet: MRC@Washington.EDU * * Date:	2 February 1994 * Last Edited:	19 February 2008 */#include <stdio.h>#include <errno.h>extern int errno;		/* just in case */#include "c-client.h"#ifdef SYSCONFIG		/* defined in env_unix.h */#include <pwd.h>#endif/* Globals */char *version = "13";		/* edit number */int debugp = NIL;		/* flag saying debug */int verbosep = NIL;		/* flag saying verbose */int rwcopyp = NIL;		/* flag saying readwrite copy (for POP) */int kwcopyp = NIL;		/* flag saying keyword copy */int ignorep = NIL;		/* flag saying ignore keywords */int critical = NIL;		/* flag saying in critical code */int trycreate = NIL;		/* [TRYCREATE] seen */char *suffix = NIL;		/* suffer merge mode suffix text */int ddelim = -1;		/* destination delimiter */FILE *f = NIL;/* Usage strings */char *usage2 = "usage: %s %s\n\n%s\n";char *usage3 = "usage: %s %s %s\n\n%s\n";char *usgchk = "check [MAILBOX]";char *usgcre = "create MAILBOX";char *usgdel = "delete MAILBOX";char *usgren = "rename SOURCE DESTINATION";char *usgcpymov = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";char *usgappdel = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";char *usgprn = "prune mailbox SEARCH_CRITERIA";char *usgxfr = "transfer [-rw[copy]] [-kw[copy]] [-ig[nore]] [-m[erge] m] SOURCE DEST";#ifdef SYSCONFIGchar *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]] [-u[ser] userid] [--]";#elsechar *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]]";#endif/* Merge modes */#define mPROMPT 1#define mAPPEND 2#define mSUFFIX 3/* Function prototypes */void ms_init (STRING *s,void *data,unsigned long size);char ms_next (STRING *s);void ms_setpos (STRING *s,unsigned long i);int main (int argc,char *argv[]);SEARCHPGM *prune_criteria (char *criteria);int prune_criteria_number (unsigned long *number,char **r);int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del,	     int mode);long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date,		STRING **message);/* Append package */typedef struct append_package {  MAILSTREAM *stream;		/* source stream */  unsigned long msgno;		/* current message number */  unsigned long msgmax;		/* maximum message number */  char *flags;			/* current flags */  char *date;			/* message internal date */  STRING *message;		/* stringstruct of message */} APPENDPACKAGE;/* Message string driver for message stringstructs */STRINGDRIVER mstring = {  ms_init,			/* initialize string structure */  ms_next,			/* get next byte in string structure */  ms_setpos			/* set position in string structure */};/* Initialize file string structure for file stringstruct * Accepts: string structure *	    pointer to message data structure *	    size of string */void ms_init (STRING *s,void *data,unsigned long size){  APPENDPACKAGE *md = (APPENDPACKAGE *) data;  s->data = data;		/* note stream/msgno and header length */  mail_fetch_header (md->stream,md->msgno,NIL,NIL,&s->data1,		     FT_PREFETCHTEXT|FT_PEEK);#if 0  s->size = size;		/* message size */#else	/* This kludge is necessary because of broken IMAP servers (sigh!) */  mail_fetch_text (md->stream,md->msgno,NIL,&s->size,FT_PEEK);  s->size += s->data1;		/* header + body size */#endif  SETPOS (s,0);}/* Get next character from file stringstruct * Accepts: string structure * Returns: character, string structure chunk refreshed */char ms_next (STRING *s){  char c = *s->curpos++;	/* get next byte */  SETPOS (s,GETPOS (s));	/* move to next chunk */  return c;			/* return the byte */}/* Set string pointer position for file stringstruct * Accepts: string structure *	    new position */void ms_setpos (STRING *s,unsigned long i){  APPENDPACKAGE *md = (APPENDPACKAGE *) s->data;  if (i < s->data1) {		/* want header? */    s->chunk = mail_fetch_header (md->stream,md->msgno,NIL,NIL,NIL,FT_PEEK);    s->chunksize = s->data1;	/* header length */    s->offset = 0;		/* offset is start of message */  }  else if (i < s->size) {	/* want body */    s->chunk = mail_fetch_text (md->stream,md->msgno,NIL,NIL,FT_PEEK);    s->chunksize = s->size - s->data1;    s->offset = s->data1;	/* offset is end of header */  }  else {			/* off end of message */    s->chunk = NIL;		/* make sure that we crack on this then */    s->chunksize = 1;		/* make sure SNX cracks the right way... */    s->offset = i;  }				/* initial position and size */  s->curpos = s->chunk + (i -= s->offset);  s->cursize = s->chunksize - i;}/* Main program */int main (int argc,char *argv[]){  MAILSTREAM *source = NIL;  MAILSTREAM *dest = NIL;  SEARCHPGM *criteria;  char c,*s,*dp,*t,*t1,tmp[MAILTMPLEN],mbx[MAILTMPLEN];  unsigned long m,len,curlen,start,last;  int i;  int merge = NIL;  int retcode = 1;  int moreswitchp = T;  char *cmd = NIL;  char *src = NIL;  char *dst = NIL;  char *pgm = argc ? argv[0] : "mailutil";#include "linkage.c"  for (i = 1; i < argc; i++) {    s = argv[i];		/* pick up argument */				/* parse switches */    if (moreswitchp && (*s == '-')) {      if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T;      else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T;      else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T;      else if (!strcmp (s,"-kwcopy") || !strcmp (s,"-kw")) kwcopyp = T;      else if (!strcmp (s,"-ignore") || !strcmp (s,"-ig")) ignorep = T;      else if ((!strcmp (s,"-merge") || !strcmp (s,"-m")) && (++i < argc)) {	if (!strcmp (s = argv[i],"prompt")) merge = mPROMPT;	else if (!strcmp (s,"append")) merge = mAPPEND;	else if (!strncmp (s,"suffix=",7) && s[7]) {	  merge = mSUFFIX;	  suffix = cpystr (s+7);	}	else {	  printf ("unknown merge option: %s\n",s);	  exit (retcode);	}      }#ifdef SYSCONFIG      else if ((!strcmp (s,"-user") || !strcmp (s,"-u")) && (++i < argc)) {	struct passwd *pw = getpwnam (s = argv[i]);	if (!pw) {	  printf ("unknown user id: %s\n",argv[i]);	  exit (retcode);	}	else if (setuid (pw->pw_uid)) {	  perror ("unable to change user id");	  exit (retcode);	}      }#endif				/* -- means no more switches, so mailbox				   name can start with "-" */      else if ((s[1] == '-') && !s[2]) moreswitchp = NIL;      else {	printf ("unknown switch: %s\n",s);	exit (retcode);      }    }    else if (!cmd) cmd = s;	/* first non-switch is command */    else if (!src) src = s;	/* second non-switch is source */    else if (!dst) dst = s;	/* third non-switch is destination */    else {      printf ("unknown argument: %s\n",s);      exit (retcode);    }  }  if (kwcopyp && ignorep) {    puts ("-kwcopy and -ignore are mutually exclusive");    exit (retcode);  }  if (!cmd) cmd = "";		/* prevent SEGV */  if (!strcmp (cmd,"check")) {	/* check for new messages */    if (!src) src = "INBOX";    if (dst || merge || rwcopyp || kwcopyp || ignorep)      printf (usage2,pgm,usgchk,stdsw);    else if (mail_status (source = (*src == '{') ?			  mail_open (NIL,src,OP_HALFOPEN |				     (debugp ? OP_DEBUG : NIL)) : NIL,			  src,SA_MESSAGES | SA_RECENT | SA_UNSEEN))      retcode = 0;  }  else if (!strcmp (cmd,"create")) {    if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)      printf (usage2,pgm,usgcre,stdsw);    else if (mail_create (source = (*src == '{') ?			  mail_open (NIL,src,OP_HALFOPEN |				     (debugp ? OP_DEBUG : NIL)) : NIL,src))      retcode = 0;  }  else if (!strcmp (cmd,"delete")) {    if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)      printf (usage2,pgm,usgdel,stdsw);    else if (mail_delete (source = (*src == '{') ?			  mail_open (NIL,src,OP_HALFOPEN |				     (debugp ? OP_DEBUG : NIL)) : NIL,src))      retcode = 0;  }  else if (!strcmp (cmd,"rename")) {    if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep)      printf (usage2,pgm,usgren,stdsw);    else if (mail_rename (source = (*src == '{') ?			  mail_open (NIL,src,OP_HALFOPEN |				     (debugp ? OP_DEBUG : NIL)) : NIL,src,dst))      retcode = 0;  }  else if ((i = !strcmp (cmd,"move")) || !strcmp (cmd,"copy")) {    if (!src || !dst || merge) printf (usage3,pgm,cmd,usgcpymov,stdsw);    else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |				 (debugp ? OP_DEBUG : NIL))) {      dest = NIL;		/* open destination stream if network */      if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |					      (debugp ? OP_DEBUG : NIL)))) {	if (mbxcopy (source,dest,dst,T,i,merge)) retcode = 0;      }    }  }  else if ((i = !strcmp (cmd,"appenddelete")) || !strcmp (cmd,"append")) {    if (!src || !dst || merge) printf (usage3,pgm,cmd,usgappdel,stdsw);    else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |				 (debugp ? OP_DEBUG : NIL))) {      dest = NIL;		/* open destination stream if network */      if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |					      (debugp ? OP_DEBUG : NIL)))) {	if (mbxcopy (source,dest,dst,NIL,i,merge)) retcode = 0;      }    }  }  else if (!strcmp (cmd,"prune")) {    if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep ||	!(criteria = prune_criteria (dst))) printf (usage2,pgm,usgprn,stdsw);    else if ((source = mail_open (NIL,src,(debugp ? OP_DEBUG : NIL))) &&	     mail_search_full (source,NIL,criteria,SE_FREE)) {      for (m = 1, s = t = NIL, len = start = last = 0; m <= source->nmsgs; m++)	if (mail_elt (source,m)->searched) {	  if (s) {		/* continuing a range? */	    if (m == last + 1) last = m;	    else {		/* no, end of previous range? */	      if (last != start) sprintf (t,":%lu,%lu",last,m);				/* no, just this message */	      else sprintf (t,",%lu",m);	      start = last = m;	/* either way, start new range */				/* running out of space? */	      if ((len - (curlen = (t += strlen (t)) - s)) < 20) {		fs_resize ((void **) &s,len += MAILTMPLEN);		t = s + curlen;	/* relocate current pointer */	      }	    }	  }	  else {		/* first time, start new buffer */	    s = (char *) fs_get (len = MAILTMPLEN);	    sprintf (s,"%lu",start = last = m);	    t = s + strlen (s);	/* end of buffer */	  }	}				/* finish last range if necessary */      if (last != start) sprintf (t,":%lu",last);      if (s) {			/* delete/expunge any matching messages */	mail_flag (source,s,"\\Deleted",ST_SET);	m = source->nmsgs;	/* get number of messages before purge */	mail_expunge (source);	printf ("%lu message(s) purged\n",m - source->nmsgs);	fs_give ((void **) &s);	/* flush buffer */      }      else puts ("No matching messages, so nothing purged");      source = mail_close (source);    }  }  else if (!strcmp (cmd,"transfer")) {    if (!src || !dst) printf (usage2,pgm,usgxfr,stdsw);    else if ((*src == '{') &&	/* open source mailbox */	     !(source = mail_open (NIL,src,OP_HALFOPEN |				   (debugp ? OP_DEBUG : NIL))));    else if ((*dst == '{') &&	/* open destination server */	     !(dest = mail_open (NIL,dst,OP_HALFOPEN |				 (debugp ? OP_DEBUG : NIL))));    else if (!(f = tmpfile ())) puts ("can't open temporary file");    else {      if (verbosep) puts ("Listing mailboxes...");      if (dest) strcpy (strchr (strcpy (tmp,dest->mailbox),'}') + 1,			dp = strchr (dst,'}') + 1);      else {	dp = dst;	tmp[0] = '\0';      }      mail_list (dest,tmp,"");      rewind (f);		/* list all mailboxes matching prefix */      if (ddelim < 0) {		/* if server failed to give delimiter */	puts ("warning: unable to get destination hierarchy delimiter!");	ddelim = 0;		/* default to none */      }      if (source) strcpy (strchr (strcpy (tmp,source->mailbox),'}') + 1,			  strchr (src,'}') + 1);      else strcpy (tmp,src);      mail_list (source,tmp,"*");      rewind (f);				/* read back mailbox names */      for (retcode = 0; !retcode && (fgets (tmp,MAILTMPLEN-1,f)); ) {	if (t = strchr (tmp+1,'\n')) *t = '\0';	for (t = mbx,t1 = dest ? dest->mailbox : "",c = NIL; (c != '}') && *t1;	     *t++ = c= *t1++);	for (t1 = dp; *t1; *t++ = *t1++);				/* point to name without delim or netspec */	t1 = source ? (strchr (tmp+1,'}') + 1) : tmp + 1;				/* src and mbx have different delimiters? */	if (ddelim && (ddelim != tmp[0]))	  while (c = *t1++) {	/* swap delimiters then */	    if (c == ddelim) c = tmp[0] ? tmp[0] : 'x';	    else if (c == tmp[0]) c = ddelim;	    *t++ = c;	  }				/* easy case */	else while (*t1) *t++ = *t1++;	*t++ = '\0';	if (verbosep) {	  printf ("Copying %s\n  => %s\n",tmp+1,mbx);	  fflush (stdout);	}	if (source = mail_open (source,tmp+1,(debugp ? OP_DEBUG : NIL) | 				(rwcopyp ? NIL : OP_READONLY))) {	  if (!mbxcopy (source,dest,mbx,T,NIL,merge)) retcode = 1;	  if (source->dtb->flags & DR_LOCAL) source = mail_close (source);	}	else printf ("can't open source mailbox %s\n",tmp+1);      }    }  }  else {    printf ("%s version %s.%s\n\n",pgm,CCLIENTVERSION,version);    printf (usage2,pgm,"command [switches] arguments",stdsw);    printf ("\nCommands:\n %s\n",usgchk);    puts   ("   ;; report number of messages and new messages");    printf (" %s\n",usgcre);    puts   ("   ;; create new mailbox");    printf (" %s\n",usgdel);    puts   ("   ;; delete existing mailbox");    printf (" %s\n",usgren);    puts   ("   ;; rename mailbox to a new name");    printf (" copy %s\n",usgcpymov);    printf (" move %s\n",usgcpymov);    puts   ("   ;; create new mailbox and copy/move messages");    printf (" append %s\n",usgappdel);    printf (" appenddelete %s\n",usgappdel);    puts   ("   ;; copy/move messages to existing mailbox");    printf (" %s\n",usgprn);    puts   ("   ;; prune mailbox of messages matching criteria");    printf (" %s\n",usgxfr);    puts   ("   ;; copy source hierarchy to destination");    puts   ("   ;;  -merge modes are prompt, append, or suffix=xxxx");  }				/* close streams */  if (source) mail_close (source);  if (dest) mail_close (dest);  exit (retcode);  return retcode;		/* stupid compilers */}/* Pruning criteria, somewhat extended from mail_criteria() * Accepts: criteria * Returns: search program if parse successful, else NIL */SEARCHPGM *prune_criteria (char *criteria){  SEARCHPGM *pgm = NIL;  char *criterion,*r,tmp[MAILTMPLEN];  int f;  if (criteria) {		/* only if criteria defined */				/* make writeable copy of criteria */    criteria = cpystr (criteria);				/* for each criterion */    for (pgm = mail_newsearchpgm (), criterion = strtok_r (criteria," ",&r);	 criterion; (criterion = strtok_r (NIL," ",&r))) {      f = NIL;			/* init then scan the criterion */      switch (*ucase (criterion)) {      case 'A':			/* possible ALL, ANSWERED */	if (!strcmp (criterion+1,"LL")) f = T;	else if (!strcmp (criterion+1,"NSWERED")) f = pgm->answered = T;	break;      case 'B':			/* possible BCC, BEFORE, BODY */	if (!strcmp (criterion+1,"CC"))	  f = mail_criteria_string (&pgm->bcc,&r);	else if (!strcmp (criterion+1,"EFORE"))	  f = mail_criteria_date (&pgm->before,&r);	else if (!strcmp (criterion+1,"ODY"))	  f = mail_criteria_string (&pgm->body,&r);	break;      case 'C':			/* possible CC */	if (!strcmp (criterion+1,"C")) f = mail_criteria_string (&pgm->cc,&r);	break;      case 'D':			/* possible DELETED, DRAFT */	if (!strcmp (criterion+1,"ELETED")) f = pgm->deleted = T;	else if (!strcmp (criterion+1,"RAFT")) f = pgm->draft = T;	break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -