shithub: fork

ref: 9e8b2bef252b18322aa341e1995d8ae70ea22938
dir: /sys/src/cmd/upas/q/qer.c/

View raw version
#include "common.h"

typedef struct Qfile Qfile;
struct Qfile
{
	Qfile	*next;
	char	*name;
	char	*tname;
} *files;

char *user;
int isnone;

int	copy(Qfile*);

void
usage(void)
{
	fprint(2, "usage: qer [-f file] [-q dir] q-root description reply-to arg-list\n");
	exits("usage");
}

void
error(char *f, char *a)
{
	char err[ERRMAX];
	char buf[256];

	rerrstr(err, sizeof(err));
	snprint(buf, sizeof(buf),  f, a);
	fprint(2, "qer: %s: %s\n", buf, err);
	exits(buf);
}

void
main(int argc, char**argv)
{
	Dir	*dir;
	String	*f, *c;
	int	fd;
	char	file[1024];
	char	buf[1024];
	long	n;
	char	*cp, *qdir;
	int	i;
	Qfile	*q, **l;

	l = &files;
	qdir = 0;

	ARGBEGIN {
	case 'f':
		q = malloc(sizeof(Qfile));
		q->name = ARGF();
		q->next = *l;
		*l = q;
		break;
	case 'q':
		qdir = ARGF();
		if(qdir == 0)
			usage();
		break;
	default:
		usage();
	} ARGEND;

	if(argc < 3)
		usage();
	user = getuser();
	isnone = (qdir != 0) || (strcmp(user, "none") == 0);

	if(qdir == 0) {
		qdir = user;
		if(qdir == 0)
			error("unknown user", 0);
	}
	snprint(file, sizeof(file), "%s/%s", argv[0], qdir);

	/*
	 *  data file name
	 */
	f = s_copy(file);
	s_append(f, "/D.XXXXXX");
	mktemp(s_to_c(f));
	cp = utfrrune(s_to_c(f), '/');
	cp++;

	/*
	 *  create directory and data file.  once the data file
	 *  exists, runq won't remove the directory
	 */
	fd = -1;
	for(i = 0; i < 10; i++){
		int perm;

		dir = dirstat(file);
		if(dir == nil){
			perm = isnone?0777:0775;
			if(sysmkdir(file, perm) < 0)
				continue;
		} else {
			if((dir->qid.type&QTDIR)==0)
				error("not a directory %s", file);
		}
		perm = isnone?0664:0660;
		fd = create(s_to_c(f), OWRITE, perm);
		if(fd >= 0)
			break;
		sleep(250);
	}
	if(fd < 0)
		error("creating data file %s", s_to_c(f));

	/*
	 *  copy over associated files
	 */
	if(files){
		*cp = 'F';
		for(q = files; q; q = q->next){
			q->tname = strdup(s_to_c(f));
			if(copy(q) < 0)
				error("copying %s to queue", q->name);
			(*cp)++;
		}
	}

	/*
	 *  copy in the data file
	 */
	i = 0;
	while((n = read(0, buf, sizeof(buf)-1)) > 0){
		if(i++ == 0 && strncmp(buf, "From", 4) != 0){
			buf[n] = 0;
			syslog(0, "smtp", "qer usys data starts with %-40.40s", buf);
		}
		if(write(fd, buf, n) != n)
			error("writing data file %s", s_to_c(f));
	}
/*	if(n < 0)
		error("reading input"); */
	close(fd);

	/*
	 *  create control file
	 */
	*cp = 'C';
	fd = syscreatelocked(s_to_c(f), OWRITE, 0664);
	if(fd < 0)
		error("creating control file %s", s_to_c(f));
	c = s_new();
	for(i = 1; i < argc; i++){
		s_append(c, argv[i]);
		s_append(c, " ");
	}
	for(q = files; q; q = q->next){
		s_append(c, q->tname);
		s_append(c, " ");
	}
	s_append(c, "\n");
	if(write(fd, s_to_c(c), strlen(s_to_c(c))) < 0) {
		sysunlockfile(fd);
		error("writing control file %s", s_to_c(f));
	}
	sysunlockfile(fd);
	exits(0);
}

int
copy(Qfile *q)
{
	int from, to, n;
	char buf[4096];

	from = open(q->name, OREAD);
	if(from < 0)
		return -1;
	to = create(q->tname, OWRITE, 0660);
	if(to < 0){
		close(from);
		return -1;
	}
	for(;;){
		n = read(from, buf, sizeof(buf));
		if(n <= 0)
			break;
		n = write(to, buf, n);
		if(n < 0)
			break;
	}
	close(to);
	close(from);
	return n;
}