xref: /plan9/sys/src/cmd/upas/q/qer.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include "common.h"
23e12c5d1SDavid du Colombier 
3219b2ee8SDavid du Colombier typedef struct Qfile Qfile;
4219b2ee8SDavid du Colombier struct Qfile
5219b2ee8SDavid du Colombier {
6219b2ee8SDavid du Colombier 	Qfile	*next;
7219b2ee8SDavid du Colombier 	char	*name;
8219b2ee8SDavid du Colombier 	char	*tname;
9219b2ee8SDavid du Colombier } *files;
10219b2ee8SDavid du Colombier 
117dd7cddfSDavid du Colombier char *user;
127dd7cddfSDavid du Colombier int isnone;
137dd7cddfSDavid du Colombier 
14219b2ee8SDavid du Colombier int	copy(Qfile*);
15219b2ee8SDavid du Colombier 
163e12c5d1SDavid du Colombier void
usage(void)173e12c5d1SDavid du Colombier usage(void)
183e12c5d1SDavid du Colombier {
197dd7cddfSDavid du Colombier 	fprint(2, "usage: qer [-f file] [-q dir] q-root description reply-to arg-list\n");
203e12c5d1SDavid du Colombier 	exits("usage");
213e12c5d1SDavid du Colombier }
223e12c5d1SDavid du Colombier 
233e12c5d1SDavid du Colombier void
error(char * f,char * a)243e12c5d1SDavid du Colombier error(char *f, char *a)
253e12c5d1SDavid du Colombier {
26*9a747e4fSDavid du Colombier 	char err[Errlen+1];
273e12c5d1SDavid du Colombier 	char buf[256];
283e12c5d1SDavid du Colombier 
29*9a747e4fSDavid du Colombier 	rerrstr(err, sizeof(err));
307dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf),  f, a);
313e12c5d1SDavid du Colombier 	fprint(2, "qer: %s: %s\n", buf, err);
323e12c5d1SDavid du Colombier 	exits(buf);
333e12c5d1SDavid du Colombier }
343e12c5d1SDavid du Colombier 
353e12c5d1SDavid du Colombier void
main(int argc,char ** argv)36219b2ee8SDavid du Colombier main(int argc, char**argv)
373e12c5d1SDavid du Colombier {
38*9a747e4fSDavid du Colombier 	Dir	*dir;
393e12c5d1SDavid du Colombier 	String	*f, *c;
403e12c5d1SDavid du Colombier 	int	fd;
413e12c5d1SDavid du Colombier 	char	file[1024];
423e12c5d1SDavid du Colombier 	char	buf[1024];
433e12c5d1SDavid du Colombier 	long	n;
447dd7cddfSDavid du Colombier 	char	*cp, *qdir;
453e12c5d1SDavid du Colombier 	int	i;
46219b2ee8SDavid du Colombier 	Qfile	*q, **l;
473e12c5d1SDavid du Colombier 
48219b2ee8SDavid du Colombier 	l = &files;
497dd7cddfSDavid du Colombier 	qdir = 0;
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier 	ARGBEGIN {
52219b2ee8SDavid du Colombier 	case 'f':
53219b2ee8SDavid du Colombier 		q = malloc(sizeof(Qfile));
54219b2ee8SDavid du Colombier 		q->name = ARGF();
55219b2ee8SDavid du Colombier 		q->next = *l;
56219b2ee8SDavid du Colombier 		*l = q;
57219b2ee8SDavid du Colombier 		break;
587dd7cddfSDavid du Colombier 	case 'q':
597dd7cddfSDavid du Colombier 		qdir = ARGF();
607dd7cddfSDavid du Colombier 		if(qdir == 0)
617dd7cddfSDavid du Colombier 			usage();
627dd7cddfSDavid du Colombier 		break;
63219b2ee8SDavid du Colombier 	default:
64219b2ee8SDavid du Colombier 		usage();
65219b2ee8SDavid du Colombier 	} ARGEND;
66219b2ee8SDavid du Colombier 
67219b2ee8SDavid du Colombier 	if(argc < 3)
683e12c5d1SDavid du Colombier 		usage();
697dd7cddfSDavid du Colombier 	user = getuser();
707dd7cddfSDavid du Colombier 	isnone = (qdir != 0) || (strcmp(user, "none") == 0);
713e12c5d1SDavid du Colombier 
727dd7cddfSDavid du Colombier 	if(qdir == 0) {
737dd7cddfSDavid du Colombier 		qdir = user;
747dd7cddfSDavid du Colombier 		if(qdir == 0)
757dd7cddfSDavid du Colombier 			error("unknown user", 0);
763e12c5d1SDavid du Colombier 	}
777dd7cddfSDavid du Colombier 	snprint(file, sizeof(file), "%s/%s", argv[0], qdir);
783e12c5d1SDavid du Colombier 
793e12c5d1SDavid du Colombier 	/*
807dd7cddfSDavid du Colombier 	 *  data file name
813e12c5d1SDavid du Colombier 	 */
823e12c5d1SDavid du Colombier 	f = s_copy(file);
833e12c5d1SDavid du Colombier 	s_append(f, "/D.XXXXXX");
843e12c5d1SDavid du Colombier 	mktemp(s_to_c(f));
857dd7cddfSDavid du Colombier 	cp = utfrrune(s_to_c(f), '/');
867dd7cddfSDavid du Colombier 	cp++;
877dd7cddfSDavid du Colombier 
887dd7cddfSDavid du Colombier 	/*
897dd7cddfSDavid du Colombier 	 *  create directory and data file.  once the data file
907dd7cddfSDavid du Colombier 	 *  exists, runq won't remove the directory
917dd7cddfSDavid du Colombier 	 */
927dd7cddfSDavid du Colombier 	fd = -1;
937dd7cddfSDavid du Colombier 	for(i = 0; i < 10; i++){
947dd7cddfSDavid du Colombier 		int perm;
957dd7cddfSDavid du Colombier 
96*9a747e4fSDavid du Colombier 		dir = dirstat(file);
97*9a747e4fSDavid du Colombier 		if(dir == nil){
987dd7cddfSDavid du Colombier 			perm = isnone?0777:0775;
997dd7cddfSDavid du Colombier 			if(sysmkdir(file, perm) < 0)
1007dd7cddfSDavid du Colombier 				continue;
1017dd7cddfSDavid du Colombier 		} else {
102*9a747e4fSDavid du Colombier 			if((dir->qid.type&QTDIR)==0)
1037dd7cddfSDavid du Colombier 				error("not a directory %s", file);
1047dd7cddfSDavid du Colombier 		}
1057dd7cddfSDavid du Colombier 		perm = isnone?0664:0660;
1067dd7cddfSDavid du Colombier 		fd = create(s_to_c(f), OWRITE, perm);
1077dd7cddfSDavid du Colombier 		if(fd >= 0)
1087dd7cddfSDavid du Colombier 			break;
1097dd7cddfSDavid du Colombier 		sleep(250);
1107dd7cddfSDavid du Colombier 	}
1117dd7cddfSDavid du Colombier 	if(fd < 0)
1127dd7cddfSDavid du Colombier 		error("creating data file %s", s_to_c(f));
113219b2ee8SDavid du Colombier 
114219b2ee8SDavid du Colombier 	/*
115219b2ee8SDavid du Colombier 	 *  copy over associated files
116219b2ee8SDavid du Colombier 	 */
117219b2ee8SDavid du Colombier 	if(files){
118219b2ee8SDavid du Colombier 		*cp = 'F';
119219b2ee8SDavid du Colombier 		for(q = files; q; q = q->next){
120219b2ee8SDavid du Colombier 			q->tname = strdup(s_to_c(f));
121219b2ee8SDavid du Colombier 			if(copy(q) < 0)
122219b2ee8SDavid du Colombier 				error("copying %s to queue", q->name);
123219b2ee8SDavid du Colombier 			(*cp)++;
124219b2ee8SDavid du Colombier 		}
125219b2ee8SDavid du Colombier 	}
126219b2ee8SDavid du Colombier 
127219b2ee8SDavid du Colombier 	/*
128219b2ee8SDavid du Colombier 	 *  copy in the data file
129219b2ee8SDavid du Colombier 	 */
1307dd7cddfSDavid du Colombier 	i = 0;
1317dd7cddfSDavid du Colombier 	while((n = read(0, buf, sizeof(buf)-1)) > 0){
1327dd7cddfSDavid du Colombier 		if(i++ == 0 && strncmp(buf, "From", 4) != 0){
1337dd7cddfSDavid du Colombier 			buf[n] = 0;
1347dd7cddfSDavid du Colombier 			syslog(0, "smtp", "qer usys data starts with %-40.40s\n", buf);
1357dd7cddfSDavid du Colombier 		}
1363e12c5d1SDavid du Colombier 		if(write(fd, buf, n) != n)
1373e12c5d1SDavid du Colombier 			error("writing data file %s", s_to_c(f));
1387dd7cddfSDavid du Colombier 	}
1393e12c5d1SDavid du Colombier /*	if(n < 0)
1403e12c5d1SDavid du Colombier 		error("reading input"); */
1413e12c5d1SDavid du Colombier 	close(fd);
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier 	/*
1443e12c5d1SDavid du Colombier 	 *  create control file
1453e12c5d1SDavid du Colombier 	 */
1463e12c5d1SDavid du Colombier 	*cp = 'C';
1477dd7cddfSDavid du Colombier 	fd = syscreatelocked(s_to_c(f), OWRITE, 0664);
1483e12c5d1SDavid du Colombier 	if(fd < 0)
1493e12c5d1SDavid du Colombier 		error("creating control file %s", s_to_c(f));
1503e12c5d1SDavid du Colombier 	c = s_new();
151219b2ee8SDavid du Colombier 	for(i = 1; i < argc; i++){
152219b2ee8SDavid du Colombier 		s_append(c, argv[i]);
153219b2ee8SDavid du Colombier 		s_append(c, " ");
154219b2ee8SDavid du Colombier 	}
155219b2ee8SDavid du Colombier 	for(q = files; q; q = q->next){
156219b2ee8SDavid du Colombier 		s_append(c, q->tname);
1573e12c5d1SDavid du Colombier 		s_append(c, " ");
1583e12c5d1SDavid du Colombier 	}
1593e12c5d1SDavid du Colombier 	s_append(c, "\n");
1607dd7cddfSDavid du Colombier 	if(write(fd, s_to_c(c), strlen(s_to_c(c))) < 0) {
1617dd7cddfSDavid du Colombier 		sysunlockfile(fd);
1623e12c5d1SDavid du Colombier 		error("writing control file %s", s_to_c(f));
1637dd7cddfSDavid du Colombier 	}
1647dd7cddfSDavid du Colombier 	sysunlockfile(fd);
1653e12c5d1SDavid du Colombier 	exits(0);
1663e12c5d1SDavid du Colombier }
167219b2ee8SDavid du Colombier 
168219b2ee8SDavid du Colombier int
copy(Qfile * q)169219b2ee8SDavid du Colombier copy(Qfile *q)
170219b2ee8SDavid du Colombier {
171219b2ee8SDavid du Colombier 	int from, to, n;
172219b2ee8SDavid du Colombier 	char buf[4096];
173219b2ee8SDavid du Colombier 
174219b2ee8SDavid du Colombier 	from = open(q->name, OREAD);
175219b2ee8SDavid du Colombier 	if(from < 0)
176219b2ee8SDavid du Colombier 		return -1;
177219b2ee8SDavid du Colombier 	to = create(q->tname, OWRITE, 0660);
178219b2ee8SDavid du Colombier 	if(to < 0){
179219b2ee8SDavid du Colombier 		close(from);
180219b2ee8SDavid du Colombier 		return -1;
181219b2ee8SDavid du Colombier 	}
182219b2ee8SDavid du Colombier 	for(;;){
183219b2ee8SDavid du Colombier 		n = read(from, buf, sizeof(buf));
184219b2ee8SDavid du Colombier 		if(n <= 0)
185219b2ee8SDavid du Colombier 			break;
186219b2ee8SDavid du Colombier 		n = write(to, buf, n);
187219b2ee8SDavid du Colombier 		if(n < 0)
188219b2ee8SDavid du Colombier 			break;
189219b2ee8SDavid du Colombier 	}
190219b2ee8SDavid du Colombier 	close(to);
191219b2ee8SDavid du Colombier 	close(from);
192219b2ee8SDavid du Colombier 	return n;
193219b2ee8SDavid du Colombier }
194