Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libcs/cssend.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* send n fds to stream fd
26
*/
27
28
#include "cslib.h"
29
30
int
31
cssend(register Cs_t* state, int fd, int* fds, int n)
32
{
33
34
#if CS_LIB_STREAM || CS_LIB_V10
35
36
register int i;
37
struct csfdhdr hdr;
38
39
if (n > 0)
40
{
41
#if CS_LIB_STREAM
42
struct strbuf dat;
43
#endif
44
csprotect(&cs);
45
hdr.count = n;
46
hdr.pid = getpid();
47
#if CS_LIB_STREAM
48
dat.buf = "";
49
dat.len = 0;
50
if (putmsg(fd, NiL, &dat, 0) < 0 || write(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
51
#else
52
if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
53
#endif
54
{
55
messagef((state->id, NiL, -1, "send: %d: hdr write error", fd));
56
return -1;
57
}
58
for (i = 0; i < n; i++)
59
if (ioctl(fd, I_SENDFD, FDARG(fds[i])))
60
{
61
messagef((state->id, NiL, -1, "send: %d: ioctl I_SENDFD error", fd));
62
return -1;
63
}
64
}
65
return 0;
66
67
#else
68
69
#if CS_LIB_SOCKET_RIGHTS
70
71
register char* s;
72
register int i;
73
struct iovec iov;
74
Csid_t id;
75
struct msghdr msg;
76
struct
77
{
78
#if _mem_msg_control_msghdr
79
struct cmsghdr hdr;
80
#else
81
#define msg_control msg_accrights
82
#define msg_controllen msg_accrightslen
83
#endif
84
int fds[OPEN_MAX + 1];
85
} ctl;
86
char tmp[PATH_MAX + 1];
87
88
csprotect(&cs);
89
if (n >= elementsof(ctl.fds))
90
{
91
errno = EINVAL;
92
return -1;
93
}
94
95
/*
96
* the first fd is to verify uid,gid in csrecv()
97
*/
98
99
s = csvar(state, CS_VAR_LOCAL, 0);
100
if (eaccess(s, X_OK) && (mkdir(s, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(s, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)))
101
{
102
messagef((state->id, NiL, -1, "send: %d: %s: invalid authentication directory ", fd, s));
103
return -1;
104
}
105
if (!(s = pathtemp(tmp, sizeof(tmp), s, "cs", 0)))
106
{
107
messagef((state->id, NiL, -1, "send: %d: authentication tmp file error", fd));
108
return -1;
109
}
110
if ((i = open(s, O_WRONLY|O_CREAT|O_TRUNC, CS_AUTH_MODE)) < 0 || chmod(s, CS_AUTH_MODE) < 0)
111
{
112
messagef((state->id, NiL, -1, "send: %d: %s: authentication file creat error", fd, s));
113
return -1;
114
}
115
if (remove(s))
116
{
117
messagef((state->id, NiL, -1, "send: %d: %s: authentication file remove error", fd, s));
118
close(i);
119
errno = EPERM;
120
return -1;
121
}
122
ctl.fds[0] = i;
123
for (i = 0; i < n; i++)
124
ctl.fds[i + 1] = fds[i];
125
id.hid = 0;
126
id.pid = getpid();
127
id.uid = geteuid();
128
id.gid = getegid();
129
msg.msg_name = 0;
130
msg.msg_namelen = 0;
131
msg.msg_iov = &iov;
132
msg.msg_iovlen = 1;
133
iov.iov_base = (caddr_t)&id;
134
iov.iov_len = sizeof(id);
135
msg.msg_control = (caddr_t)&ctl;
136
msg.msg_controllen = (char*)&ctl.fds[n + 1] - (char*)&ctl;
137
#if _mem_msg_control_msghdr
138
ctl.hdr.cmsg_len = msg.msg_controllen;
139
ctl.hdr.cmsg_level = SOL_SOCKET;
140
ctl.hdr.cmsg_type = SCM_RIGHTS;
141
#endif
142
#ifdef EMSGSIZE
143
n = 0;
144
while ((i = sendmsg(fd, &msg, 0) < 0 ? -1 : 0) < 0 && errno == EMSGSIZE && n++ < 5)
145
sleep(1);
146
#else
147
i = sendmsg(fd, &msg, 0) < 0 ? -1 : 0;
148
#endif
149
if (i) messagef((state->id, NiL, -1, "send: %d: sendmsg error", fd));
150
close(ctl.fds[0]);
151
return i;
152
153
#else
154
155
messagef((state->id, NiL, -8, "send(%d,%d) call", fd, n));
156
if (!access(CS_PROC_FD_TST, F_OK))
157
{
158
register int i;
159
register int j;
160
register char* s;
161
162
static struct
163
{
164
int* fds;
165
int num;
166
int max;
167
} hold;
168
169
/*
170
* the sent fd's must be kept open until
171
* the other side receives them, so we dup
172
* and hold them open until the next cssend()
173
*/
174
175
if (hold.fds)
176
for (i = 0; i < hold.num; i++)
177
if (hold.fds[i] >= 0)
178
{
179
close(hold.fds[i]);
180
hold.fds[i] = 0;
181
}
182
if (n > hold.max)
183
{
184
hold.max = roundof(n, 8);
185
hold.fds = newof(hold.fds, int, hold.max, 0);
186
}
187
s = state->temp;
188
s += sfsprintf(s, sizeof(state->temp), "%lu %d", getpid(), n);
189
if (hold.fds)
190
{
191
hold.num = n;
192
for (i = 0; i < n; i++)
193
{
194
if ((j = hold.fds[i] = dup(fds[i])) < 0)
195
j = fds[i];
196
else fcntl(j, F_SETFD, FD_CLOEXEC);
197
s += sfsprintf(s, sizeof(state->temp) - (s - state->temp), " %d", j);
198
}
199
}
200
else for (i = 0; i < n; i++)
201
s += sfsprintf(s, sizeof(state->temp) - (s - state->temp), " %d", fds[i]);
202
s += sfsprintf(s, sizeof(state->temp) - (s - state->temp), "\n");
203
n = s - state->temp;
204
messagef((state->id, NiL, -8, "send(%d, %-*.*s) call", fd, n - 1, n - 1, state->temp));
205
i = send(fd, state->temp, n, 0) == n ? 0 : -1;
206
if (i) messagef((state->id, NiL, -1, "send: %d: write error", fd));
207
return i;
208
}
209
errno = EINVAL;
210
messagef((state->id, NiL, -1, "send: %d: not supported", fd));
211
return -1;
212
213
#endif
214
215
#endif
216
217
}
218
219
int
220
_cs_send(int fd, int* fds, int n)
221
{
222
return cssend(&cs, fd, fds, n);
223
}
224
225