plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

qer.c (3179B)


      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 }