|
|
1.1 root 1: #include <sys/types.h>
2: #include <sys/ioctl.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: /* dial a name and return an fd to the connection */
15: int
16: ipcopen(name, param)
17: char *name; /* name being dialed */
18: char *param; /* parameters for dialer */
19: {
20: ipcinfo info;
21:
22: info.rfd = info.cfd = -1;
23: info.myname = info.user = info.machine = NULL;
24: info.uid = info.gid = -1;
25: info.name = name;
26: info.param = param;
27: info.flags = IPC_OPEN;
28: return ipcdial(&info);
29: }
30:
31: /*
32: * Open a mounted steam. ip->name points to a string of the form
33: * path!address. Path must be a file system path to a mounted stream.
34: */
35: _ipcopen(ip)
36: ipcinfo *ip;
37: {
38: static stretch path;
39: char *np;
40: int fd;
41: struct stat sbuf;
42:
43: /* split into path and network address */
44: _strcat(&path, ip->name, (char *)NULL, (char *)NULL);
45: np = strchr(path.ptr, '!');
46: if (np) {
47: *np = '\0';
48: ip->name += np - path.ptr + 1;
49: }
50: if (ip->flags&IPC_CAREFUL) {
51: if (stat(path.ptr, &sbuf)<0)
52: return ABORT(ENOENT, "destination nonexistent", NULLINFO);
53: if (sbuf.st_mode&6 != 6)
54: return ABORT(EACCES, "permission denied", NULLINFO);
55: }
56: if ((fd = open(path.ptr, 2))<0) {
57: if (errno==EACCES){
58: if (*(ip->name))
59: return ABORT(EACCES, "can't access dialer", NULLINFO);
60: else
61: return ABORT(EACCES, "permission denied", NULLINFO);
62: } else
63: return ABORT(ENOENT, "destination nonexistent", NULLINFO);
64: }
65:
66: /* update the translated part of the name */
67: if(ip->myname)
68: _strcat(&path, ip->myname, "!", path.ptr);
69: ip->myname = path.ptr;
70: return fd;
71: }
72:
73: /* dial a name and return an fd to the connection */
74: int
75: ipcdial(ip)
76: ipcinfo *ip;
77: {
78: struct passfd pass;
79: int fd;
80:
81: if ((fd = _ipcopen(ip))<0)
82: return -1;
83:
84: /* pass reply channel */
85: if (ip->rfd >= 0) {
86: if (_fd_write(fd, ip->rfd)<0) {
87: close(fd);
88: return ABORT(EIO, "protocol botch", ip);
89: }
90: close(ip->rfd);
91: ip->rfd = -1;
92: }
93:
94: /* pass communications channel (if not same as reply channel) */
95: if (ip->cfd >= 0) {
96: if (_fd_write(fd, ip->cfd)<0) {
97: close(fd);
98: return ABORT(EIO, "protocol botch", ip);
99: }
100: close(ip->cfd);
101: ip->cfd = -1;
102: }
103:
104: /* pass the info on */
105: if (_info_write(fd, ip) < 0) {
106: close(fd);
107: return ABORT(errno, errstr, ip);
108: }
109: if (ip->flags&IPC_HANDOFF)
110: return fd;
111:
112: /* get the reply */
113: if (_fd_read(fd, &pass)>=0) {
114: _reply_read(fd);
115: if (errno != 0) {
116: close(fd);
117: close(pass.fd);
118: return ABORT(errno, errstr, NULLINFO);
119: }
120: return pass.fd;
121: } else {
122: _reply_read(fd);
123: if (errno != 0) {
124: close(fd);
125: return ABORT(errno, errstr, NULLINFO);
126: }
127: return fd;
128: }
129: }
130:
131: /*
132: * Pass a request to someone else to handle.
133: */
134: ipcpass(ip)
135: ipcinfo *ip;
136: {
137: ip->flags |= IPC_HANDOFF;
138: return ipcdial(ip);
139: }
140:
141: /* set error number and string and return -1 */
142: int
143: _ipcabort(no, err, ip)
144: int no;
145: char *err;
146: ipcinfo *ip;
147: {
148: if (ip!=NULLINFO) {
149: if (ip->cfd>0) {
150: close(ip->cfd);
151: ip->cfd = -1;
152: }
153: if (ip->rfd>0) {
154: close(ip->rfd);
155: ip->rfd = -1;
156: }
157: }
158: errstr = err;
159: errno = no;
160: return -1;
161: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.