xref: /plan9/sys/src/cmd/upas/q/qer.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include "common.h"
2 
3 typedef struct Qfile Qfile;
4 struct Qfile
5 {
6 	Qfile	*next;
7 	char	*name;
8 	char	*tname;
9 } *files;
10 
11 char *user;
12 int isnone;
13 
14 int	copy(Qfile*);
15 
16 void
usage(void)17 usage(void)
18 {
19 	fprint(2, "usage: qer [-f file] [-q dir] q-root description reply-to arg-list\n");
20 	exits("usage");
21 }
22 
23 void
error(char * f,char * a)24 error(char *f, char *a)
25 {
26 	char err[Errlen+1];
27 	char buf[256];
28 
29 	rerrstr(err, sizeof(err));
30 	snprint(buf, sizeof(buf),  f, a);
31 	fprint(2, "qer: %s: %s\n", buf, err);
32 	exits(buf);
33 }
34 
35 void
main(int argc,char ** argv)36 main(int argc, char**argv)
37 {
38 	Dir	*dir;
39 	String	*f, *c;
40 	int	fd;
41 	char	file[1024];
42 	char	buf[1024];
43 	long	n;
44 	char	*cp, *qdir;
45 	int	i;
46 	Qfile	*q, **l;
47 
48 	l = &files;
49 	qdir = 0;
50 
51 	ARGBEGIN {
52 	case 'f':
53 		q = malloc(sizeof(Qfile));
54 		q->name = ARGF();
55 		q->next = *l;
56 		*l = q;
57 		break;
58 	case 'q':
59 		qdir = ARGF();
60 		if(qdir == 0)
61 			usage();
62 		break;
63 	default:
64 		usage();
65 	} ARGEND;
66 
67 	if(argc < 3)
68 		usage();
69 	user = getuser();
70 	isnone = (qdir != 0) || (strcmp(user, "none") == 0);
71 
72 	if(qdir == 0) {
73 		qdir = user;
74 		if(qdir == 0)
75 			error("unknown user", 0);
76 	}
77 	snprint(file, sizeof(file), "%s/%s", argv[0], qdir);
78 
79 	/*
80 	 *  data file name
81 	 */
82 	f = s_copy(file);
83 	s_append(f, "/D.XXXXXX");
84 	mktemp(s_to_c(f));
85 	cp = utfrrune(s_to_c(f), '/');
86 	cp++;
87 
88 	/*
89 	 *  create directory and data file.  once the data file
90 	 *  exists, runq won't remove the directory
91 	 */
92 	fd = -1;
93 	for(i = 0; i < 10; i++){
94 		int perm;
95 
96 		dir = dirstat(file);
97 		if(dir == nil){
98 			perm = isnone?0777:0775;
99 			if(sysmkdir(file, perm) < 0)
100 				continue;
101 		} else {
102 			if((dir->qid.type&QTDIR)==0)
103 				error("not a directory %s", file);
104 		}
105 		perm = isnone?0664:0660;
106 		fd = create(s_to_c(f), OWRITE, perm);
107 		if(fd >= 0)
108 			break;
109 		sleep(250);
110 	}
111 	if(fd < 0)
112 		error("creating data file %s", s_to_c(f));
113 
114 	/*
115 	 *  copy over associated files
116 	 */
117 	if(files){
118 		*cp = 'F';
119 		for(q = files; q; q = q->next){
120 			q->tname = strdup(s_to_c(f));
121 			if(copy(q) < 0)
122 				error("copying %s to queue", q->name);
123 			(*cp)++;
124 		}
125 	}
126 
127 	/*
128 	 *  copy in the data file
129 	 */
130 	i = 0;
131 	while((n = read(0, buf, sizeof(buf)-1)) > 0){
132 		if(i++ == 0 && strncmp(buf, "From", 4) != 0){
133 			buf[n] = 0;
134 			syslog(0, "smtp", "qer usys data starts with %-40.40s\n", buf);
135 		}
136 		if(write(fd, buf, n) != n)
137 			error("writing data file %s", s_to_c(f));
138 	}
139 /*	if(n < 0)
140 		error("reading input"); */
141 	close(fd);
142 
143 	/*
144 	 *  create control file
145 	 */
146 	*cp = 'C';
147 	fd = syscreatelocked(s_to_c(f), OWRITE, 0664);
148 	if(fd < 0)
149 		error("creating control file %s", s_to_c(f));
150 	c = s_new();
151 	for(i = 1; i < argc; i++){
152 		s_append(c, argv[i]);
153 		s_append(c, " ");
154 	}
155 	for(q = files; q; q = q->next){
156 		s_append(c, q->tname);
157 		s_append(c, " ");
158 	}
159 	s_append(c, "\n");
160 	if(write(fd, s_to_c(c), strlen(s_to_c(c))) < 0) {
161 		sysunlockfile(fd);
162 		error("writing control file %s", s_to_c(f));
163 	}
164 	sysunlockfile(fd);
165 	exits(0);
166 }
167 
168 int
copy(Qfile * q)169 copy(Qfile *q)
170 {
171 	int from, to, n;
172 	char buf[4096];
173 
174 	from = open(q->name, OREAD);
175 	if(from < 0)
176 		return -1;
177 	to = create(q->tname, OWRITE, 0660);
178 	if(to < 0){
179 		close(from);
180 		return -1;
181 	}
182 	for(;;){
183 		n = read(from, buf, sizeof(buf));
184 		if(n <= 0)
185 			break;
186 		n = write(to, buf, n);
187 		if(n < 0)
188 			break;
189 	}
190 	close(to);
191 	close(from);
192 	return n;
193 }
194