chiark / gitweb /
Merge branches 'idx/verh' and 'idx/qmqpc'
[qmail] / qmail-newu.c
1 #include "stralloc.h"
2 #include "subfd.h"
3 #include "getln.h"
4 #include "substdio.h"
5 #include "cdbmss.h"
6 #include "exit.h"
7 #include "readwrite.h"
8 #include "open.h"
9 #include "error.h"
10 #include "case.h"
11 #include "auto_qmail.h"
12
13 void die_temp() { _exit(111); }
14
15 void die_chdir()
16 {
17   substdio_putsflush(subfderr,"qmail-newu: fatal: unable to chdir\n");
18   die_temp();
19 }
20 void die_nomem()
21 {
22   substdio_putsflush(subfderr,"qmail-newu: fatal: out of memory\n");
23   die_temp();
24 }
25 void die_opena()
26 {
27   substdio_putsflush(subfderr,"qmail-newu: fatal: unable to open users/assign\n");
28   die_temp();
29 }
30 void die_reada()
31 {
32   substdio_putsflush(subfderr,"qmail-newu: fatal: unable to read users/assign\n");
33   die_temp();
34 }
35 void die_format()
36 {
37   substdio_putsflush(subfderr,"qmail-newu: fatal: bad format in users/assign\n");
38   die_temp();
39 }
40 void die_opent()
41 {
42   substdio_putsflush(subfderr,"qmail-newu: fatal: unable to open users/cdb.tmp\n");
43   die_temp();
44 }
45 void die_writet()
46 {
47   substdio_putsflush(subfderr,"qmail-newu: fatal: unable to write users/cdb.tmp\n");
48   die_temp();
49 }
50 void die_rename()
51 {
52   substdio_putsflush(subfderr,"qmail-newu: fatal: unable to move users/cdb.tmp to users/cdb\n");
53   die_temp();
54 }
55
56 struct cdbmss cdbmss;
57 stralloc key = {0};
58 stralloc data = {0};
59
60 char inbuf[1024];
61 substdio ssin;
62
63 int fd;
64 int fdtemp;
65
66 stralloc line = {0};
67 int match;
68
69 stralloc wildchars = {0};
70
71 void main()
72 {
73   int i;
74   int numcolons;
75
76   umask(033);
77   if (chdir(auto_qmail) == -1) die_chdir();
78
79   fd = open_read("users/assign");
80   if (fd == -1) die_opena();
81
82   substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
83
84   fdtemp = open_trunc("users/cdb.tmp");
85   if (fdtemp == -1) die_opent();
86
87   if (cdbmss_start(&cdbmss,fdtemp) == -1) die_writet();
88
89   if (!stralloc_copys(&wildchars,"")) die_nomem();
90
91   for (;;) {
92     if (getln(&ssin,&line,&match,'\n') != 0) die_reada();
93     if (line.len && (line.s[0] == '.')) break;
94     if (!match) die_format();
95
96     if (byte_chr(line.s,line.len,'\0') < line.len) die_format();
97     i = byte_chr(line.s,line.len,':');
98     if (i == line.len) die_format();
99     if (i == 0) die_format();
100     if (!stralloc_copys(&key,"!")) die_nomem();
101     if (line.s[0] == '+') {
102       if (!stralloc_catb(&key,line.s + 1,i - 1)) die_nomem();
103       case_lowerb(key.s,key.len);
104       if (i >= 2)
105         if (byte_chr(wildchars.s,wildchars.len,line.s[i - 1]) == wildchars.len)
106           if (!stralloc_append(&wildchars,line.s + i - 1)) die_nomem();
107     }
108     else {
109       if (!stralloc_catb(&key,line.s + 1,i - 1)) die_nomem();
110       if (!stralloc_0(&key)) die_nomem();
111       case_lowerb(key.s,key.len);
112     }
113
114     if (!stralloc_copyb(&data,line.s + i + 1,line.len - i - 1)) die_nomem();
115
116     numcolons = 0;
117     for (i = 0;i < data.len;++i)
118       if (data.s[i] == ':') {
119         data.s[i] = 0;
120         if (++numcolons == 6)
121           break;
122       }
123     if (numcolons < 6) die_format();
124     data.len = i;
125
126     if (cdbmss_add(&cdbmss,key.s,key.len,data.s,data.len) == -1) die_writet();
127   }
128
129   if (cdbmss_add(&cdbmss,"",0,wildchars.s,wildchars.len) == -1) die_writet();
130
131   if (cdbmss_finish(&cdbmss) == -1) die_writet();
132   if (fsync(fdtemp) == -1) die_writet();
133   if (close(fdtemp) == -1) die_writet(); /* NFS stupidity */
134   if (rename("users/cdb.tmp","users/cdb") == -1) die_rename();
135
136   _exit(0);
137 }