- * Portal system call interface.
- *
- * This call creates a portal.
- * All the difficulty here is in dealing with errors.
- * A long sequence of steps is necessary:
- * 1. a socket must be allocated
- * 2. the server name length must be determined
- * 3. the portal must be entered into the file system
- * 4. the portal type and server must be entered into the portals' file
- * 5. a file descriptor referencing the socket+inode must be returned
- * If any errors occur in this process we must back it all out.
- */
-sportal()
-{
- register struct a {
- caddr_t name;
- int mode;
- caddr_t server;
- int kind;
- } *ap = (struct a *)u.u_ap;
- struct socket *so;
- struct inode *ip;
- struct file *fp;
- int err, len;
- char ch;
-
- /*
- * Allocate the socket for the portal.
- */
- u.u_error = socket(&so, SOCK_STREAM, &localaddr, SO_NEWFDONCONN);
- if (u.u_error)
- return;
-
- /*
- * Check that server name fis in a file system buffer.
- * This to simplify the creation of the portal service process.
- */
- if (ap->server) {
- u.u_dirp = ap->server;
- for (len = 0; len < BSIZE-2; len++) {
- register c = uchar();
- if (c < 0)
- goto bad;
- if (c == 0)
- break;
- }
- if (len == BSIZE - 2) {
- u.u_error = EINVAL;
- goto bad;
- }
- }
-
- /*
- * Make sure that nothing with the portal's name exists.
- */
- u.u_dirp = ap->name;
- ip = namei(uchar, 1);
- if (ip != NULL) {
- iput(ip);
- u.u_error = EEXIST;
- }
- if (u.u_error)
- goto bad;
-
- /*
- * Make a node in the file system for the portal.
- */
- ip = maknode((ap->mode & 0x7777) | IFPORTAL);
- if (ip == NULL)
- goto bad;
-
- /*
- * Make the first character of the contents of the
- * portal be the portal type and the rest of the portal be
- * the pathname of the server (if one was given).
- */
- ch = (char)ap->kind;
- u.u_base = (caddr_t)&ch;
- u.u_count = 1;
- u.u_offset = 0;
- u.u_segflg = 1;
- writei(ip);
- if (ap->server) {
- u.u_base = ap->server;
- u.u_count = len;
- u.u_segflg = 0;
- writei(ip);
- }
- if (u.u_error)
- goto bad2;
-
- /*
- * Allocate a file descriptor and make it reference both
- * the inode representing the portal and the call director
- * socket for the portal.
- */
- fp = falloc();
- if (fp == NULL)
- goto bad2;
- fp->f_flag = FPORTAL|FSOCKET;
- fp->f_inode = ip;
- fp->f_socket = so;
-
- /*
- * Make the in-core inode reference the socket.
- */
- ip->i_un.i_socket = so;
- irele(ip);
- return;
-bad2:
- err = u.u_error;
- iput(ip);
- u.u_dirp = ap->name;
- unlink();
- u.u_error = err;
-bad:
- sofree(so);
-}
-
-/*
- * Splice system call interface.
- */
-ssplice()
-{
- register struct a {
- int fd1;
- int fd2;
- } *ap = (struct a *)u.u_ap;
- struct file *f1, *f2;
- struct socket *pso, *pso2;
-
- f1 = getf(ap->fd1);
- if (f1 == NULL)
- return;
- f2 = getf(ap->fd2);
- if (f2 == NULL)
- return;
- if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) {
- u.u_error = ENOTSOCK;
- return;
- }
- if (f1->f_count > 1 || f2->f_count > 1) {
- u.u_error = ETOOMANYREFS;
- return;
- }
- u.u_error = pi_splice(f1->f_socket, f2->f_socket);
- if (u.u_error)
- return;
- u.u_ofile[ap->fd1] = 0;
- u.u_ofile[ap->fd2] = 0;
- f1->f_count = 0;
- f2->f_count = 0;
-}
-
-/*
- * Socket system call interface. Copy in arguments