SRI-NOSC/mh/file.c

Compare this file to the similar file:
Show the results in this format:

#include "mh.h"
#include "stat.h"
#include "errors.h"
#define NFOLD 20                /* Allow 20 folder specs */

/* file [-src folder] [msgs] +folder [+folder ...]
 *
 * moves messages from src folder (or current) to other one(s).
 *
 *  all = first-last for a message sequence
 *  -preserve says preserve msg numbers
 *  -link says don't delete old msg
 */

char *anoyes[];         /* Std no/yes gans array        */

int fout, vecp, foldp, prsrvf;
char *vec[MAXARGS], maildir[128], *folder;
struct msgs *mp;

struct st_fold {
	char *f_name;
	struct msgs *f_mp;
} folders[NFOLD];

struct swit switches[] {
	"all",           -3,      /* 0 */
	"link",           0,      /* 1 */
	"nolink",         0,      /* 2 */
	"preserve",       0,      /* 3 */
	"nopreserve",     0,      /* 4 */
	"src +folder",    0,      /* 5 */
	"help",           4,      /* 6 */
	0,                0
};
main(argc, argv)
char *argv[];
{
	register int i, msgnum;
	register char *cp;
	char *msgs[128];
	int msgp, linkf;
	char *ap;
	char *arguments[50], **argp;

	fout = dup(1);
	if(argc < 2) {
 badarg:    printf("Usage: file [-src folder] [msg ...] +folder [+folder]\n");
	    goto leave;
	}
#ifdef NEWS
	m_news();
#endif
	folder = msgp = linkf = 0;
	vecp = 1;
	ap = cp = argv[0];
	while(*cp)
		if(*cp++ == '/')
			ap = cp;
	if((cp = m_find(ap)) != -1) {
		ap = brkstring(cp = getcpy(cp), " ", "\n");
		ap = copyip(ap, arguments);
	} else
		ap = arguments;
	copyip(argv+1, ap);
	argp = arguments;
	while(cp = *argp++) {
		if(*cp == '-')
			switch(smatch(++cp, switches)) {
			case -2:ambigsw(cp, switches);       /* ambiguous */
				goto leave;
							/* unknown */
			case -1:printf("file: -%s unknown\n", cp);
				goto leave;
						       /* -all */
			case 0: printf("\"-all\" changed to \"all\"\n");
				goto leave;
			case 1: linkf = 1;  continue;  /* -link */
			case 2: linkf = 0;  continue;  /* -nolink */
			case 3: prsrvf = 1;  continue; /* -preserve */
			case 4: prsrvf = 0;  continue; /* -nopreserve */
			case 5: if(folder) {           /* -src */
					printf("Only one src folder.\n");
					goto leave;
				}
				if(!(folder = *argp++) || *folder == '-') {
		printf("file: Missing argument for %s switch\n", argp[-2]);
					goto leave;
				}
				if(*folder == '+')
					folder++;
				continue;
							/* -help */
			case 6: help("file   [msgs] [switches]  +folder ...",
				     switches);
				goto leave;
			}
		if(*cp == '+')  {
			if(foldp < NFOLD)
				folders[foldp++].f_name = cp + 1;
			else {
				printf("Only %d folders allowed.\n", NFOLD);
				goto leave;
			}
		} else
			msgs[msgp++] = cp;
	}
	if(!foldp) {
		printf("No folder specified.\n");
		goto badarg;
	}
	if(!msgp)
		msgs[msgp++] = "cur";
	if(!folder)
		folder = m_getfolder();
	copy(m_maildir(folder), maildir);
	if(chdir(maildir) < 0) {
		printf("Can't chdir to: "); flush();
		perror(maildir);
		goto leave;
	}
	if(!(mp = m_gmsg(folder))) {
		printf("Can't read folder %s!?\n",folder);
		goto leave;
	}
	if(mp->hghmsg == 0) {
		printf("No messages in \"%s\".\n", folder);
		goto leave;
	}
	for(msgnum = 0; msgnum < msgp; msgnum++)
		if(!m_convert((cp = msgs[msgnum]), UNDELETED, UNDELETED))
			goto leave;
	if(mp->numsel == 0) {
		printf("No undeleted messages specified\n");       
		goto leave;
	}
	m_replace("folder", folder);
	if(mp->hghsel != mp->curmsg && ((mp->numsel != mp->nummsg) || linkf))
		m_setcur(mp->hghsel);
	if(opnfolds())
		goto leave;
	for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
		if(mp->msgstats[msgnum] & SELECTED)
			if(process(getcpy(m_name(msgnum))))
				goto leave;
	if(!linkf) {
		if((cp = m_find("delete-prog")) != -1) {
			if(mp->numsel > MAXARGS-2) {
	  printf("file: more than %d messages for deletion-prog\n",MAXARGS-2);
				printf("[messages not unlinked]\n");
				goto leave;
			}
			for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
				if(mp->msgstats[msgnum]&SELECTED)
					vec[vecp++] = getcpy(m_name(msgnum));
			vec[vecp] = 0;
			m_update();
			flush();
			vec[0] = cp;
			execvsrh(vec);
			printf("Can't exec deletion-prog--"); flush();
			perror(cp);
		} else {
			for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
				if(mp->msgstats[msgnum] & SELECTED)
					if(unlink(cp = getcpy(m_name(msgnum)))== -1) {
						printf("Can't unlink %s:",folder);
						flush(); perror(cp);
					}
		}
	}
leave:
	m_update();
	flush();
}


opnfolds()
{
	register int i;
	register char *cp;
	char nmaildir[128];
	struct inode stbuf;

	for(i = 0; i < foldp; i++) {
		copy(m_maildir(folders[i].f_name), nmaildir);
		if(stat(nmaildir, &stbuf) < 0) {
			cp = concat("Create folder \"", nmaildir, "\"? ", 0);
			if(!gans(cp, anoyes))
				goto bad;
			free(cp);
			if(!makedir(nmaildir)) {
				printf("Can't create folder.\n");
				goto bad;
			}
		}
		if(chdir(nmaildir) < 0) {
			printf("Can't chdir to: "); flush();
			perror(nmaildir);
			goto bad;
		}
		if(!(folders[i].f_mp = m_gmsg())) {
			printf("Can't read folder %s\n", folders[i].f_name);
			goto bad;
		}
	}
	chdir(maildir);         /* return to src folder */
	return(0);
bad:
	return(1);
}


process(msg)
{
	char newmsg[256], buf[512];
	register int i;
	register char *nmsg;
	register struct st_fold *fp;
	struct inode stbuf, stbf1;
	int n, o;

    for(fp = folders; fp < &folders[foldp]; fp++) {
	if(prsrvf)
		nmsg = msg;
	else
		nmsg = m_name(fp->f_mp->hghmsg++ + 1);
	copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
	if(link(msg, newmsg) < 0) {
		if(errno == EEXIST ||
		  (errno == EXDEV && stat(newmsg, &stbuf) != -1)) {
			if(errno != EEXIST || stat(msg, &stbf1) < 0 ||
			   stat(newmsg, &stbuf) < 0 ||
			   stbf1.i_number != stbuf.i_number) {
				printf("Message %s:%s already exists.\n",
				     fp->f_name, msg);
				return(1);
			}
			continue;
		}
		if(errno == EXDEV) {
			if((o = open(msg, 0)) == -1) {
				printf("Can't open %s:%s.\n",
					folder, msg);
				return(1);
			}
			fstat(o, &stbuf);
			if((n = creat(newmsg, stbuf.i_mode&0777)) == -1) {
				printf("Can't create %s:%s.\n",
					fp->f_name, nmsg);
				close(o);
				return(1);
			}
			do
				if((i=read(o, buf, sizeof buf)) < 0 ||
				  write(n, buf, i) == -1) {
				    printf("Copy error on %s:%s to %s:%s!\n",
					    folder, msg, fp->f_name, nmsg);
				    close(o); close(n);
				    return(1);
				}
			while(i == sizeof buf);
			close(n); close(o);
		} else {
			printf("Error on link %s:%s to %s:",
			    folder, msg, fp->f_name);
			flush();
			perror(nmsg);
			return(1);
		}
	}
cont:   ;
    }
    return(0);
}