|
|
1.1 root 1: #include <sys/types.h>
2: #include <sys/filio.h>
3: #include <sys/stat.h>
4: #include <ipc.h>
5: #include "defs.h"
6:
7: /* exported */
8: char *errstr;
9:
10: /* imports */
11: extern int atoi();
12: extern char *memchr();
13:
14: /*
15: * dial a name and return an fd to the connection
16: */
17: int
18: ipcopen(name, param)
19: char *name; /* name being dialed */
20: char *param; /* parameters for dialer */
21: {
22: ipcinfo info;
23:
24: info.rfd = info.cfd = -1;
25: info.myname = info.user = info.machine = NULL;
26: info.uid = info.gid = -1;
27: info.name = name;
28: info.param = param;
29: info.flags = IPC_OPEN;
30: return ipcdial(&info);
31: }
32:
33: /*
34: * Open a mounted steam. ip->name points to a string of the form
35: * path!address. Path must be a file system path to a mounted stream.
36: * One element moves from the beginning of ip->name to the end of ip->myname.
37: */
38: _ipcopen(ip)
39: ipcinfo *ip;
40: {
41: static stretch path;
42: static stretch myname;
43: int fd;
44: char *np;
45: char *oname;
46: struct stat sbuf;
47:
48: /*
49: * remove next element of ip->name ...
50: */
51: oname = ip->name;
52: _strcat(&path, ip->name, (char *)NULL, (char *)NULL);
53: np = strchr(path.ptr, '!');
54: if (np) {
55: *np = '\0';
56: ip->name += np - path.ptr + 1;
57: } else
58: ip->name += strlen(ip->name);
59:
60: /*
61: * ... and add it to the translated part
62: */
63: if(ip->myname) {
64: _strcat(&myname, ip->myname, "!", path.ptr);
65: ip->myname = myname.ptr;
66: } else
67: ip->myname = path.ptr;
68:
69: /*
70: * make sure this is a mounted file. the link count for
71: * such beasts is 0. There should be a less hacky way.
72: */
73: if (stat(path.ptr, &sbuf)<0 || sbuf.st_nlink) {
74: ip->name = oname;
75: return ABORT(ENOENT, "destination nonexistent", NULLINFO);
76: }
77:
78: /*
79: * This is a hack. Daemon's should not blithely write on files
80: * without checking permissions. Setting IPC_CAREFUL makes us
81: * check for blanket write permission before writing on a file.
82: */
83: if (ip->flags&IPC_CAREFUL) {
84: if (sbuf.st_mode&6 != 6){
85: ip->name = oname;
86: return ABORT(EACCES, "permission denied", NULLINFO);
87: }
88: }
89:
90: /*
91: * Finally, open the (presumabley mounted upon) file
92: */
93: if ((fd = open(path.ptr, 2))<0) {
94: ip->name = oname;
95: if (errno==EACCES){
96: if (*(ip->name))
97: return ABORT(EACCES, "can't access dialer", NULLINFO);
98: else
99: return ABORT(EACCES, "permission denied", NULLINFO);
100: } else
101: return ABORT(ENOENT, "destination nonexistent", NULLINFO);
102: }
103: return fd;
104: }
105:
106: /*
107: * dial a name and return an fd to the connection
108: */
109: int
110: ipcdial(ip)
111: ipcinfo *ip;
112: {
113: struct passfd pass;
114: int fd;
115:
116: /*
117: * open the mounted stream, the result is a unique connection to
118: * the mounting process.
119: */
120: if ((fd = _ipcopen(ip))<0)
121: return -1;
122:
123: /*
124: * pass reply channel
125: */
126: if (ip->rfd >= 0) {
127: if (_fd_write(fd, ip->rfd)<0) {
128: close(fd);
129: return ABORT(EIO, "protocol botch", ip);
130: }
131: close(ip->rfd);
132: ip->rfd = -1;
133: }
134:
135: /*
136: * pass communications channel (if not same as reply channel)
137: */
138: if (ip->cfd >= 0) {
139: if (_fd_write(fd, ip->cfd)<0) {
140: close(fd);
141: return ABORT(EIO, "protocol botch", ip);
142: }
143: close(ip->cfd);
144: ip->cfd = -1;
145: }
146:
147: /*
148: * pass the request
149: */
150: if (_info_write(fd, ip) < 0) {
151: close(fd);
152: return ABORT(errno, errstr, ip);
153: }
154: if (ip->flags&IPC_HANDOFF)
155: return fd;
156:
157: /*
158: * get the reply, it may be preceded by a
159: * file descriptor to use as the communications
160: * channel.
161: */
162: if (_fd_read(fd, &pass)>=0) {
163: _reply_read(fd);
164: if (errno != 0) {
165: close(fd);
166: close(pass.fd);
167: return ABORT(errno, errstr, NULLINFO);
168: }
169: close(fd);
170: return pass.fd;
171: } else {
172: _reply_read(fd);
173: if (errno != 0) {
174: close(fd);
175: return ABORT(errno, errstr, NULLINFO);
176: }
177: return fd;
178: }
179: }
180:
181: /*
182: * Pass a request to someone else to handle.
183: */
184: ipcpass(ip)
185: ipcinfo *ip;
186: {
187: ip->flags |= IPC_HANDOFF;
188: return ipcdial(ip);
189: }
190:
191: /*
192: * Cause network to recdial a call. Return 0 if dialer took the redial, -1
193: * otherwise. In any case, close off the connection.
194: */
195: ipcredial(ip)
196: ipcinfo *ip;
197: {
198: int fd;
199:
200: if(ip->rfd){
201: _reply_write(ip->rfd, -1, "redial");
202: close(ip->rfd);
203: ip->rfd = -1;
204: }
205: ip->flags = IPC_REDIAL;
206: fd = ipcdial(ip);
207: if(fd<0)
208: return -1;
209: ABORT(0, (char *)0, ip);
210: close(fd);
211: return 0;
212: }
213:
214: /*
215: * set error number and string and return -1
216: */
217: int
218: _ipcabort(no, err, ip)
219: int no;
220: char *err;
221: ipcinfo *ip;
222: {
223: if (ip!=NULLINFO) {
224: if (ip->cfd>0) {
225: close(ip->cfd);
226: ip->cfd = -1;
227: }
228: if (ip->rfd>0) {
229: close(ip->rfd);
230: ip->rfd = -1;
231: }
232: }
233: errstr = err;
234: errno = no;
235: return -1;
236: }
237:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.