chiark / gitweb /
Upstream qmail 1.01
[qmail] / install.c
1 #include "substdio.h"
2 #include "stralloc.h"
3 #include "getln.h"
4 #include "readwrite.h"
5 #include "exit.h"
6 #include "open.h"
7 #include "error.h"
8 #include "strerr.h"
9 #include "byte.h"
10 #include "fifo.h"
11
12 stralloc target = {0};
13 char *to;
14
15 #define FATAL "install: fatal: "
16 void nomem() { strerr_die2x(111,FATAL,"out of memory"); }
17
18 char inbuf[SUBSTDIO_INSIZE];
19 char outbuf[SUBSTDIO_OUTSIZE];
20 substdio ssin;
21 substdio ssout;
22
23 void doit(line)
24 stralloc *line;
25 {
26   char *x;
27   unsigned int xlen;
28   unsigned int i;
29   char *type;
30   char *uidstr;
31   char *gidstr;
32   char *modestr;
33   char *mid;
34   char *name;
35   unsigned long uid;
36   unsigned long gid;
37   unsigned long mode;
38   int fdin;
39   int fdout;
40   unsigned long zlen;
41
42   x = line->s; xlen = line->len;
43
44   type = x;
45   i = byte_chr(x,xlen,':'); if (i == xlen) return;
46   x[i++] = 0; x += i; xlen -= i;
47
48   uidstr = x;
49   i = byte_chr(x,xlen,':'); if (i == xlen) return;
50   x[i++] = 0; x += i; xlen -= i;
51
52   gidstr = x;
53   i = byte_chr(x,xlen,':'); if (i == xlen) return;
54   x[i++] = 0; x += i; xlen -= i;
55
56   modestr = x;
57   i = byte_chr(x,xlen,':'); if (i == xlen) return;
58   x[i++] = 0; x += i; xlen -= i;
59
60   mid = x;
61   i = byte_chr(x,xlen,':'); if (i == xlen) return;
62   x[i++] = 0; x += i; xlen -= i;
63
64   name = x;
65   i = byte_chr(x,xlen,':'); if (i == xlen) return;
66   x[i++] = 0; x += i; xlen -= i;
67
68   if (!stralloc_copys(&target,to)) nomem();
69   if (!stralloc_cats(&target,mid)) nomem();
70   if (!stralloc_cats(&target,name)) nomem();
71   if (!stralloc_0(&target)) nomem();
72
73   uid = -1; if (*uidstr) scan_ulong(uidstr,&uid);
74   gid = -1; if (*gidstr) scan_ulong(gidstr,&gid);
75   scan_8long(modestr,&mode);
76
77   switch(*type) {
78     case 'z':
79       scan_ulong(type + 1,&zlen);
80
81       fdout = open_trunc(target.s);
82       if (fdout == -1)
83         strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
84       substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof(outbuf));
85
86       while (zlen--)
87         if (substdio_put(&ssout,"",1) == -1)
88           strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
89
90       if (substdio_flush(&ssout) == -1)
91         strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
92       if (fsync(fdout) == -1)
93         strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
94       close(fdout);
95       break;
96
97     case 'p':
98       if (fifo_make(target.s,0700) == -1)
99         if (errno != error_exist)
100           strerr_die4sys(111,FATAL,"unable to mkfifo ",target.s,": ");
101       break;
102
103     case 'd':
104       if (mkdir(target.s,0700) == -1)
105         if (errno != error_exist)
106           strerr_die4sys(111,FATAL,"unable to mkdir ",target.s,": ");
107       break;
108
109     case 'c':
110       fdin = open_read(name);
111       if (fdin == -1)
112         strerr_die4sys(111,FATAL,"unable to read ",name,": ");
113       substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof(inbuf));
114
115       fdout = open_trunc(target.s);
116       if (fdout == -1)
117         strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
118       substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof(outbuf));
119
120       switch(substdio_copy(&ssout,&ssin)) {
121         case -2:
122           strerr_die4sys(111,FATAL,"unable to read ",name,": ");
123         case -3:
124           strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
125       }
126
127       close(fdin);
128       if (substdio_flush(&ssout) == -1)
129         strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
130       if (fsync(fdout) == -1)
131         strerr_die4sys(111,FATAL,"unable to write ",target.s,": ");
132       close(fdout);
133       break;
134
135     default:
136       return;
137   }
138
139   if (chown(target.s,uid,gid) == -1)
140     strerr_die4sys(111,FATAL,"unable to chown ",target.s,": ");
141   if (chmod(target.s,mode) == -1)
142     strerr_die4sys(111,FATAL,"unable to chmod ",target.s,": ");
143 }
144
145 char buf[256];
146 substdio in = SUBSTDIO_FDBUF(read,0,buf,sizeof(buf));
147 stralloc line = {0};
148
149 void main(argc,argv)
150 int argc;
151 char **argv;
152 {
153   int match;
154
155   umask(077);
156
157   to = argv[1];
158   if (!to) strerr_die2x(100,FATAL,"install: usage: install dir");
159
160   for (;;) {
161     if (getln(&in,&line,&match,'\n') == -1)
162       strerr_die2sys(111,FATAL,"unable to read input: ");
163     doit(&line);
164     if (!match)
165       _exit(0);
166   }
167 }