Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
}