|
|
1.1 root 1: #include <sys/types.h>
2: #include <sys/filio.h>
3: #include <ipc.h>
4: #include "defs.h"
5:
6: /* imports */
7: extern int conn_ld;
8: extern struct passwd *pwsearch();
9: extern char *strncpy();
10:
11: /* global to this file */
12: #define ROOTUID 0
13:
14: /*
15: * Attach to a name space. If the path is a single element,
16: * just mount into the file system. Otherwise, pass the request
17: * to a network dialer.
18: */
19: int
20: ipccreat(name, param)
21: char *name; /* name being dialed */
22: char *param; /* parameters for creation */
23: {
24: int pfd[2];
25: char *path=name;
26: ipcinfo info;
27: int nfd;
28:
29: if (path==NULL)
30: return ABORT(EINVAL, "name too long", (ipcinfo*)NULL);
31:
32: /*
33: * if a path is specified, pass the request through a dialer
34: */
35: if (strchr(path, '!')!=NULL) {
36: info.rfd = info.cfd = -1;
37: info.myname = info.user = info.machine = NULL;
38: info.uid = info.gid = -1;
39: info.name = name;
40: info.param = param;
41: info.flags = IPC_CREAT;
42: return ipcdial(&info);
43: }
44:
45: /*
46: * Try creating a file to mount on
47: */
48: if(access(path, 0) < 0){
49: nfd = creat(path, 0666);
50: if(nfd < 0)
51: return ABORT(errno, "can't mount", (ipcinfo*)NULL);
52: close(nfd);
53: }
54:
55: /*
56: * make a pipe to mount into the file system and push the
57: * connection line discipline. Conn_ld ensures that all
58: * opens of the pipe will spawn a unique connection.
59: */
60: if (pipe(pfd) < 0)
61: return ABORT(errno, "out of pipes", (ipcinfo*)NULL);
62: if (ioctl(pfd[1], FIOPUSHLD, &conn_ld) < 0) {
63: close(pfd[0]);
64: close(pfd[1]);
65: return ABORT(errno, "pushing line discipline", (ipcinfo*)NULL);
66: }
67:
68: /* mount */
69: if (fmount(3, pfd[1], path, 0) < 0) {
70: close(pfd[0]);
71: close(pfd[1]);
72: return ABORT(errno, "can't mount", (ipcinfo*)NULL);
73: }
74: close(pfd[1]);
75: return pfd[0];
76: }
77:
78: /*
79: * listen for a connection
80: */
81: ipcinfo *
82: ipclisten(fd)
83: int fd;
84: {
85: struct passfd pass;
86: int pfd[2];
87: static ipcinfo info;
88: static char user[32];
89: int fd1=-1, fd2=-1;
90:
91: /*
92: * Get a unique stream to a caller, or reuse this one if none is passed.
93: * The reuse is typical of the arpa! gateway.
94: */
95: if(_fd_read(fd, &pass) < 0) {
96: if(errno==EINTR)
97: return NULL;
98: info.uid = -1;
99: info.gid = -1;
100: info.rfd = dup(fd);
101: close(fd);
102: } else {
103: info.uid = pass.uid;
104: info.gid = pass.gid;
105: info.rfd = pass.fd;
106: }
107: strncpy(user, pass.logname, sizeof(pass.logname));
108: user[sizeof(pass.logname)] = '\0';
109: info.user = user;
110: (void)ioctl(info.rfd, FIOACCEPT, &pass);
111:
112: /*
113: * Get possible passed fds. Up to two can be passed, i.e.
114: * the fd to reply to and the one to use for communication.
115: */
116: if (_fd_read(info.rfd, &pass)>=0) {
117: fd1 = pass.fd;
118: if (_fd_read(info.rfd, &pass)>=0) {
119: fd2 = pass.fd;
120: } else if(errno==EINTR){
121: close(info.rfd);
122: close(fd1);
123: return NULL;
124: }
125: } else if(errno==EINTR){
126: close(info.rfd);
127: return NULL;
128: }
129:
130: /*
131: * get the request
132: */
133: if (_info_read(info.rfd, &info)<0) {
134: /* requestor gave up */
135: close(info.rfd);
136: if(fd1>=0)
137: close(fd1);
138: if(fd2>=0)
139: close(fd2);
140: return NULL;
141: }
142:
143: if (info.flags & IPC_HANDOFF) {
144: /*
145: * This is a call passed to us
146: * by someone else.
147: */
148: close(info.rfd);
149: info.rfd = fd1;
150: info.cfd = fd2;
151: info.flags &= ~IPC_HANDOFF;
152: } else {
153: /*
154: * By default the fd on which the
155: * request was received will be used
156: * both for replies and communication
157: */
158: info.cfd = fd1;
159: if (fd2>=0)
160: close(fd2);
161: }
162: return &info;
163: }
164:
165: /*
166: * Accept a connection.
167: * Close all fd's except ip->cfd.
168: */
169: int
170: ipcaccept(ip)
171: ipcinfo *ip;
172: {
173: return ipcdaccept(ip, -1, "who_cares");
174: }
175:
176: /*
177: * Accept a connection, and supply a source address and communications fd
178: */
179: int
180: ipcdaccept(ip, commfd, source)
181: ipcinfo *ip;
182: int commfd;
183: char *source;
184: {
185: if (commfd >= 0) {
186: /*
187: * supply our own channel for communications
188: */
189: if (_fd_write(ip->rfd, commfd) < 0) {
190: close(commfd);
191: return ABORT(errno, "can't pass conection", ip);
192: }
193: _reply_write(ip->rfd, 0, source);
194: ABORT(0, "", ip);
195: ip->cfd = commfd;
196: } else if (ip->cfd >= 0) {
197: /*
198: * use client supplied channel for communications
199: */
200: _reply_write(ip->rfd, 0, "");
201: close(ip->rfd);
202: ip->rfd = -1;
203: } else {
204: /*
205: * use reply channel for communications
206: */
207: _reply_write(ip->rfd, 0, "");
208: ip->cfd = ip->rfd;
209: ip->rfd = -1;
210: }
211: return(ip->cfd);
212: }
213:
214: /*
215: * Reject a connection.
216: */
217: int
218: ipcreject(ip, no, str)
219: ipcinfo *ip;
220: int no; /* error number */
221: char *str; /* error string */
222: {
223: _reply_write(ip->rfd, no, str);
224: ABORT(no, str, ip);
225: return 0;
226: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.