|
|
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.