1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#include <unistd.h>
#include <fcntl.h>
#include <alloca.h>
#include <stdio.h>
#include <sys/stat.h>
#include "ninitfeatures.h"
#include "error_table.h"
#include "uid.h"
#define U "unable to "
static char *e() { return error_string(table, errno); }
static void nomem() { die(111,"out of memory"); }
static void ex(char *s0, char *s1) { die(111,U,s0,": ",s1,": ",e()); }
static void doit(char *to, char *line) {
char *x, **arg, *target, *tmp;
char *type, *mid, *name, *alias;
unsigned long uid, gid, mode;
int in, out, len;
static char *uid_global, *gid_global, *mode_global, *mid_global, V;
len=splitmem(0,line,':'); if (len <7) return;
arg=alloca((len+1) * sizeof(char*)); if (arg==0) nomem();
splitmem(arg,line,':');
type = arg[0];
x=arg[1]; if (!*x==0 && uid_global) x=uid_global;
if (*x) uid=atoulong(x); else uid = -1;
x=arg[2]; if (!*x==0 && gid_global) x=gid_global;
if (*x) gid=atoulong(x); else gid = -1;
x=arg[3]; if (!*x && mode_global) x=mode_global; scan_8ulong(x,&mode);
mid = arg[4]; if (!*mid && mid_global) mid=mid_global;
name= arg[5];
x=arg[6]; alias = (*x) ? x : name;
len = str_len(to) + str_len(mid) + str_len(name);
x=alloca(2*len + 32); if (x==0) nomem();
target = x;
x += str_copy(x,to);
x += str_copy(x,mid);
x += str_copy(x,name);
while (target[0]=='/' && target[1]=='/') target++;
tmp = (*type=='x') ? x+2 : 0;
switch(*type) {
case 'p':
if (SYS_mknod(target,S_IFIFO|0600,0) == -1)
if (errno != EEXIST) ex("mknod",target);
if (V) msg("pipe:\t", target);
break;
case 'd':
if (mkdir(target,0700) == -1)
if (errno != EEXIST) ex("mkdir",target);
if (V) msg("mkdir:\t", target);
break;
case 'c':
case 'x':
if ((in=open(alias, O_RDONLY)) <0) ex("open",alias);
if (*type == 'c') out = open(target, O_WRONLY|O_CREAT|O_TRUNC, 0600);
else out = open_tmpfd(target, tmp, 0600);
if (out <0) ex("open",target);
x=alloca(8192); if (x==0) nomem();
for (;;) {
len=read(in,x,8192);
if (len==0) break;
else if (len==-1) ex("read",alias);
else if (len != write(out,x,len)) { die(111,U,"write",target); }
}
close(in);
if (fsync(out)) ex("fsync",target);
if (close(out)) ex("close",target);
if (tmp && rename(tmp,target))
{ die(111,U,"rename: ", tmp, " -> ", target, ": ", e()); }
if (V) msg(alias, "\t-> ", target);
break;
case 'g':
x=arg[1]; uid_global = (*x) ? x : 0;
x=arg[2]; gid_global = (*x) ? x : 0;
x=arg[3]; mode_global = (*x) ? x : 0;
x=arg[4]; mid_global = (*x) ? x : 0;
return;
case 'v':
if (arg[1][0]) V=1;
else V=0;
default:
return;
}
if (SYS_chown(target,uid,gid) <0) ex("chown",target);
if (chmod(target,mode) <0) ex("chmod",target);
}
int main(int argc, char **argv) {
char *to, **arg, *s=0;
if (argc<2) { die(100,"usage: install-bin Dir < File\n "
"install-bin Dir c:::755:mid:file:: x:::755:mid:name:source: ...\n"
"File contains lines:\ntype:uid:gid:mode:middle:target:source:\n"
"type is one of the letters: vpdcxg\n"
"type g sets global uid:gid:mode:middle\n"); }
to = argv[1];
errmsg_iam("install-bin");
umask(077);
if (argc == 2) {
int len;
if (GLOBAL_READ(0,s, len,100000)) ex("read","stdin");
close(0);
s[len]=0;
len = splitmem(0,s,'\n');
arg = alloca((len+1) * sizeof(char*)); if (arg==0) nomem();
splitmem(arg,s,'\n');
} else
arg = argv+2;
for (; (s=*arg); ++arg) doit(to, s);
return 0;
}
|