Annotation of researchv10dc/ipc/libipc/ipcopen.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.