home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume3 / rfs / part7 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  62.3 KB

  1. Subject: RFS: remote file system (part 7 of 7)
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 3, Issue 83
  6. Submitted by: tektronix!tekcrl!toddb
  7.  
  8. #!/bin/sh
  9. #
  10. # RFS, a kernel-resident remote file system.  Shar 7 of 7
  11. #
  12. #
  13. # This is a shell archive, meaning:
  14. # 1. Remove everything above the #!/bin/sh line.
  15. # 2. Save the resulting text in a file.
  16. # 3. Execute the file with /bin/sh (not csh) to create the files:
  17. #    remote/usr.sys.remote/rmt_general.c
  18. #    remote/usr.sys.remote/rmt_generic.c
  19. #    remote/usr.sys.remote/rmt_io.c
  20. #    remote/usr.sys.remote/rmt_subr.c
  21. #    remote/usr.sys.remote/rmt_syscall1.c
  22. #    remote/usr.sys.remote/rmt_syscall2.c
  23. #
  24. # remote/usr.sys.remote/rmt_general.c
  25. #
  26. if [ -f remote/usr.sys.remote/rmt_general.c ]; then 
  27.     echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_general.c or ^C to quit' 
  28.     read ans 
  29.     rm -f remote/usr.sys.remote/rmt_general.c 
  30. fi 
  31.  
  32. sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_general.c
  33. X/*
  34. X * Copyright 1985, Todd Brunhoff.
  35. X *
  36. X * This software was written at Tektronix Computer Research Laboratories
  37. X * as partial fulfillment of a Master's degree at the University of Denver.
  38. X * This is not Tektronix proprietary software and should not be
  39. X * confused with any software product sold by Tektronix.  No warranty is
  40. X * expressed or implied on the reliability of this software; the author,
  41. X * the University of Denver, and Tektronix, inc. accept no liability for
  42. X * any damage done directly or indirectly by this software.  This software
  43. X * may be copied, modified or used in any way, without fee, provided this
  44. X * notice remains an unaltered part of the software.
  45. X *
  46. X * $Header: rmt_general.c,v 2.0 85/12/07 18:18:06 toddb Rel $
  47. X *
  48. X * $Log:    rmt_general.c,v $
  49. X * Revision 2.0  85/12/07  18:18:06  toddb
  50. X * First public release.
  51. X * 
  52. X */
  53. X#include    "../h/param.h"
  54. X#ifndef pyr    /* Pyramid */
  55. X#include    "../machine/pte.h"
  56. X#endif
  57. X#include    "../h/systm.h"
  58. X#include    "../h/map.h"
  59. X#include    "../h/dir.h"
  60. X#include    "../h/user.h"
  61. X#include    "../h/kernel.h"
  62. X#include    "../h/proc.h"
  63. X#ifdef BSD4_3
  64. X#include    "../h/namei.h"
  65. X#else BSD4_3
  66. X#include    "../h/nami.h"
  67. X#endif BSD4_3
  68. X#include    "../h/inode.h"
  69. X#include    "../h/mbuf.h"
  70. X#include    "../h/socket.h"
  71. X#include    "../remote/remotefs.h"
  72. X#include    "../h/errno.h"
  73. X#include    "../netinet/in.h"
  74. X#include    "../h/file.h"
  75. X
  76. Xextern long    remote_sysindex;
  77. Xextern struct mbuf    *remote_path;
  78. Xextern u_char    remote_sysmap[];
  79. Xextern syscalls    remote_syscall[];
  80. Xextern struct remoteinfo    remote_info[];
  81. X
  82. X/*
  83. X * This routine is the main gateway into the remote software.  It should
  84. X * be called from syscall().  Note that sysnum is already mapped to our
  85. X * idea of the system call number.
  86. X */
  87. X#ifdef pyr    /* Pyramid */
  88. Xremote_startup(pass, sysnum, arg1, arg2, arg3, arg4, arg5, arg6)
  89. X#else pyr
  90. Xremote_startup(pass, sysnum)
  91. X#endif
  92. X    long    sysnum, pass;
  93. X{
  94. X    struct a {
  95. X        long    arg1,
  96. X            arg2;
  97. X    } *uap = (struct a *)u.u_ap;
  98. X    long    error, sysindex;
  99. X    extern long    remote_fd();
  100. X    register syscalls    *sp = remote_syscall + sysnum;
  101. X    register struct file    *fp;
  102. X    register struct proc    *p;
  103. X    register func    general = sp->sys_gen;
  104. X    register unsigned    fd1,
  105. X                fd2;
  106. X#ifdef pyr    /* Pyramid */
  107. X    long    args[ 6 ];
  108. X
  109. X    args[0] = arg1;
  110. X    args[1] = arg2;
  111. X    args[2] = arg3;
  112. X    args[3] = arg4;
  113. X    args[4] = arg5;
  114. X    args[5] = arg6;
  115. X    u.u_ap = args;
  116. X    uap = (struct a *) args;
  117. X#endif pyr
  118. X
  119. X    debug1("%d strt:#%d,pass%d,%s\n",
  120. X        u.u_procp->p_pid, sysnum, pass,
  121. X        pass == 0 ? (!sp->sys_before ? "too soon" : "before") :
  122. X                (pass == 1       ? "do it"    : "too late"));
  123. X
  124. X    /*
  125. X     * For the greatest of speed we check here for invalid or non-
  126. X     * remote file descriptors.  Make sure that we let a dup2() go
  127. X     * through, even if the first fd is non-remote.
  128. X     */
  129. X    if (general == remote_fd) {
  130. X        /*
  131. X         * Gross kludge from v7 for the bourne shell.
  132. X         */
  133. X        fd1 = uap->arg1;
  134. X        if (sysnum == RSYS_dup && (fd1 &~ 077)) {
  135. X            fd1 &= 077;
  136. X            sysnum = RSYS_dup2;
  137. X        }
  138. X        error = 2;
  139. X        if (fd1 >= NOFILE
  140. X        || (fp = u.u_ofile[fd1]) == NULL
  141. X        || (fp->f_flag & FREMOTE) == 0)
  142. X            error--;
  143. X        if (sysnum != RSYS_dup2)
  144. X            error--;
  145. X        else {
  146. X            fd2 = uap->arg2;
  147. X            if (fd2 >= NOFILE
  148. X            || (fp = u.u_ofile[fd2]) == NULL
  149. X            || (fp->f_flag & FREMOTE) == 0)
  150. X                error--;
  151. X        }
  152. X        if (! error)
  153. X            return(FALSE);
  154. X        uap->arg1 = fd1;
  155. X    }
  156. X    /*
  157. X     * Check to see if this is being done too soon.  Note that this is
  158. X     * on the else side of the check for remote_fd.  i.e., this code
  159. X     * assumes that remote_fd() routines should always be done before
  160. X     * the real routines.
  161. X     */
  162. X    else if (pass == 0) {
  163. X        u.u_rmtoffset[0] = -1;
  164. X        u.u_rmtoffset[1] = -1;
  165. X        if (! sp->sys_before)
  166. X            return(FALSE);
  167. X    }
  168. X    else if (pass > 1) {
  169. X        u.u_error = EISREMOTE;
  170. X        return(TRUE);
  171. X    }
  172. X
  173. X    /*
  174. X     * finally, if the user has turned off remote access for himself,
  175. X     * then just return.
  176. X     */
  177. X    p = u.u_procp;
  178. X    if (p->p_flag & SNOREMOTE)
  179. X        return(FALSE);
  180. X    u.u_error = 0;
  181. X
  182. X    /*
  183. X     * do the remote syscall.
  184. X     */
  185. X    error = (*general)(sysnum);
  186. X    debug1("%d startup done: ret1=%d, ret2=%d, err=%d\n",
  187. X        u.u_procp->p_pid, u.u_r.r_val1, u.u_r.r_val2, error);
  188. X    if (error < 0)    /* call the real system call */
  189. X        return(FALSE);
  190. X    u.u_error = error;
  191. X    return(TRUE);
  192. X}
  193. X
  194. X/*
  195. X * This routine handles most system calls that have no special requirements
  196. X * and have a single path in their first argument.
  197. X */
  198. Xremote_path1(sysnum)
  199. X    int    sysnum;
  200. X{
  201. X    struct a {
  202. X        char    *path;
  203. X    } *uap = (struct a *)u.u_ap;
  204. X    long    sysindex, len;
  205. X    struct message *msg;
  206. X    struct mbuf    *m;
  207. X    register syscalls    *sp = remote_syscall + sysnum;
  208. X    register long        error;
  209. X
  210. X    /*
  211. X     * Get the path mbuf chain and its length.  Also the remote sys #.
  212. X     */
  213. X    if ((m = remote_path) == NULL)
  214. X        return(ENOBUFS);
  215. X    for (len=0; m; m = m->m_next)
  216. X        len += m->m_len;
  217. X    m = remote_path;
  218. X    remote_path = NULL;
  219. X    sysindex = remote_sysindex;
  220. X
  221. X    /*
  222. X     * Initialize the message and call the specific syscall handler.
  223. X     */
  224. X    msg = mtod(m, struct message *);
  225. X    introduce(msg, sysnum);
  226. X    msg->m_hdlen = len;
  227. X    error = (*sp->sys_spec)(sysindex, m, sysnum);
  228. X
  229. X    if (error < 0) {
  230. X        msg = &remote_info[ sysindex ].r_msg;
  231. X#ifdef BSD4_3
  232. X#else BSD4_3
  233. X        u.u_dirp = (caddr_t) u.u_arg[0];
  234. X#endif BSD4_3
  235. X        u.u_rmtoffset[0] = msg->m_args[0];
  236. X        return ( -1 );
  237. X    }
  238. X    return ( error );
  239. X}
  240. X/*
  241. X * This routine handles all two-path system calls.
  242. X *
  243. X *    RSYS_link: the placement of path2 determines where
  244. X *        we run the syscall because path2 is the file
  245. X *         that is created.  Isremote() must also resolve the
  246. X *        path1 so that the remote link will know what file to
  247. X *        link it to.  Both path1 and path2 must be on the same
  248. X *        system.  Unfortunately, in kernel mode, we don't know
  249. X *        which path was found to be remote: we must check both again.
  250. X *    RSYS_rename: Same as RSYS_link.
  251. X *    RSYS_symlink: path2 is the only possible remote file and
  252. X *        path1 does not need to be resolved because symlink()
  253. X *        blindly creats a symbolic link to it.
  254. X */
  255. Xremote_path2(sysnum)
  256. X    int    sysnum;
  257. X{
  258. X    struct a {
  259. X        char    *path1;
  260. X        char    *path2;
  261. X    } *uap = (struct a *)u.u_ap;
  262. X    long    sysindex,
  263. X        len,
  264. X        error;
  265. X    struct message    *msg;
  266. X    struct mbuf    *m;
  267. X
  268. X    if ((m = remote_path) == NULL)
  269. X        return(ENOBUFS);
  270. X    /*
  271. X     * If this is rename or link, then throw away what is in remote_path
  272. X     * because we don't know which path it refers to .
  273. X     */
  274. X    remote_path = NULL;
  275. X    if (sysnum != RSYS_symlink) {
  276. X        m_freem(m);
  277. X        m = NULL;
  278. X        sysindex = rmt_checkpath(uap->path2, &m, sysnum);
  279. X        if (sysindex < 0)
  280. X            return(-1);
  281. X    }
  282. X    else
  283. X        sysindex = remote_sysindex;
  284. X    /*
  285. X     * Ok, path2 is now safely in our mbuf.  Set the PATHOFF field for
  286. X     * the beginning of where path1 will be.
  287. X     */
  288. X    msg = mtod(m, struct message *);
  289. X    introduce_1extra(msg, sysnum, u.u_cmask);
  290. X    msg->m_args[ R_PATHOFF ] = htonl(msg->m_hdlen);
  291. X
  292. X    /*
  293. X     * If its a symbolic link, we can just copy the path onto the
  294. X     * end of our mbuf chain.
  295. X     */
  296. X    if (sysnum == RSYS_symlink) {
  297. X        error = rmt_copypath(uap->path1, m, TRUE);
  298. X        if (error) {
  299. X            m_freem(m);
  300. X            return(error);
  301. X        }
  302. X    }
  303. X    /*
  304. X     * Link and rename have to have path1 on the same system as path2.
  305. X     */
  306. X    else if (rmt_checkpath(uap->path1, &m, sysnum) != sysindex) {
  307. X        m_freem(m);
  308. X        return(-1);
  309. X    }
  310. X
  311. X    error = rmt_msgfin(sysindex, m, 0);
  312. X
  313. X    if(error < 0)
  314. X        if (sysnum != RSYS_rename && sysnum != RSYS_link) {
  315. X            msg = &remote_info[ sysindex ].r_msg;
  316. X#ifdef BSD4_3
  317. X#else BSD4_3
  318. X            u.u_dirp = (caddr_t) u.u_arg[0];
  319. X#endif BSD4_3
  320. X            u.u_rmtoffset[0] = msg->m_args[0];
  321. X            u.u_rmtoffset[1] = ntohl(msg->m_args[1]);
  322. X            return ( -1 );
  323. X        }
  324. X        else
  325. X            error = EISREMOTE;
  326. X    return( error );
  327. X}
  328. X
  329. X/*
  330. X * Check a remote file for its "remoteness".  After namei() is called (in
  331. X * the kernel) and isremote() is called as a result, we can get the result
  332. X * from remote_path and put it on the end of 'mhead'.
  333. X */
  334. Xrmt_checkpath(path, mhead, sysnum)
  335. X    char    *path;
  336. X    struct mbuf    **mhead;
  337. X    long    sysnum;
  338. X{
  339. X    char    *psrc, *pdest;
  340. X    struct mbuf    *m;
  341. X    struct message    *msg;
  342. X    long    len;
  343. X    struct inode    *ip;
  344. X
  345. X#ifdef BSD4_3
  346. X    register struct nameidata *ndp = &u.u_nd;
  347. X    long    follow = remote_syscall[ sysnum ].sys_follow ? FOLLOW : 0;
  348. X
  349. X    ndp->ni_nameiop = LOOKUP | follow;
  350. X    ndp->ni_segflg = UIO_USERSPACE;
  351. X    ndp->ni_dirp = (caddr_t)path;
  352. X    ip = namei(ndp);
  353. X#else BSD4_3
  354. X    u.u_dirp = path;
  355. X    ip = namei(uchar, LOOKUP, remote_syscall[ sysnum ].sys_follow);
  356. X#endif BSD4_3
  357. X    if (ip != NULL || u.u_error != EISREMOTE) {
  358. X        if (ip)
  359. X            iput(ip);
  360. X        return(-1);
  361. X    }
  362. X    u.u_error = 0;
  363. X
  364. X    if (remote_path == NULL)
  365. X        return(-1);
  366. X    if (*mhead == NULL)
  367. X        *mhead = remote_path;
  368. X    else {
  369. X        /*
  370. X         * If we were handed an mbuf, then we tack the new string
  371. X         * of mbufs on the end.  Note that we bump the offset so that
  372. X         * the mtod(m, char *) points to the beginning of the path.
  373. X         */
  374. X        for (m = *mhead; m->m_next; )
  375. X            m = m->m_next;
  376. X        m->m_next = remote_path;
  377. X        msg = mtod(remote_path, struct message *);
  378. X        len = msg->m_hdlen - (R_MINRMSG + R_PATHSTART*sizeof(long));
  379. X        remote_path->m_off += R_MINRMSG + R_PATHSTART*sizeof(long);
  380. X        remote_path->m_len -= R_MINRMSG + R_PATHSTART*sizeof(long);
  381. X        msg = mtod(*mhead, struct message *);
  382. X        msg->m_hdlen += len;
  383. X    }
  384. X    remote_path = NULL;
  385. X    return(remote_sysindex);
  386. X}
  387. X
  388. X/*
  389. X * Remote exit()
  390. X */
  391. Xremote_exit()
  392. X{
  393. X    struct remoteinfo    *rp, *rmt_hostdir();
  394. X    struct file    *fp;
  395. X    long    i;
  396. X    struct mbuf    *m;
  397. X    struct message *msg;
  398. X
  399. X    /*
  400. X     * Throw away remote file descriptors.
  401. X     */
  402. X    for (i=0; i<NOFILE; i++)
  403. X        if ((fp = u.u_ofile[ i ]) && (fp->f_flag & FREMOTE))
  404. X            rmt_deallocfd(i);
  405. X    u.u_procp->p_flag &= ~SREMOTE;
  406. X    if (rp = rmt_hostdir(u.u_cdir, &i))
  407. X        rp->r_nchdir--;
  408. X    /*
  409. X     * Send the exit message to every remote system to which we
  410. X     * have a connection.
  411. X     */
  412. X    for (rp = remote_info, i=0; i<R_MAXSYS; i++, rp++)
  413. X        if (rmthostused(i) && rp->r_sock) {
  414. X            /*
  415. X             * If ours is the last usage of this connection, then
  416. X             * shut it down.
  417. X             */
  418. X            debug4("%d off #%d, now %d usrs\n", u.u_procp->p_pid,
  419. X                i, rp->r_users-1); 
  420. X            if (--rp->r_users <= 0 && rp->r_sock) {
  421. X                if (rp->r_close)
  422. X                    rmt_shutdown(i);
  423. X                else
  424. X                    rmt_closehost(rp);
  425. X                continue;
  426. X            }
  427. X            MGET(m, M_WAIT, MT_DATA);
  428. X            if (m == NULL)
  429. X                break;
  430. X            msg = mtod(m, struct message *);
  431. X            msg->m_hdlen = m->m_len = introduce(msg, RSYS_exit);
  432. X            rmt_msgfin(i, m, RFLG_INFO);
  433. X        }
  434. X
  435. X    return( -1 ); /* do the real syscall, too */
  436. X}
  437. X
  438. X/*
  439. X * Remote fork()
  440. X */
  441. Xremote_fork(sysnum)
  442. X    long    sysnum;
  443. X{
  444. X    register long        i, child, pid, ppid, val1;
  445. X    long            rmtdir = u.u_rmtcdir,
  446. X                sysindex;
  447. X    struct message        *msg;
  448. X    register struct remoteinfo    *rp;
  449. X    struct remoteinfo    *rmt_hostdir();
  450. X    struct mbuf    *m;
  451. X    register struct file    *fp;
  452. X    long            rmtsys;    
  453. X
  454. X    /*
  455. X     * We may not need to even notify anyone, if this process is not
  456. X     * doing anything interesting.  If there are no open files or
  457. X     * a remote current working directory, then do no more.
  458. X     */
  459. X    rmtcopyhosts(rmtsys, u.u_rmtsys);
  460. X    rmtclearhosts();
  461. X    for (i=0; i<NOFILE; i++) {
  462. X        if ((fp = u.u_ofile[ i ]) && (fp->f_flag & FREMOTE)) {
  463. X            remote_info[ (int)fp->f_data ].r_nfile++;
  464. X            rmtusehost((int)fp->f_data);
  465. X        }
  466. X    }
  467. X    if (rp = rmt_hostdir(u.u_cdir, &sysindex)) {
  468. X        rmtusehost(sysindex);
  469. X        rp->r_nchdir++;
  470. X    }
  471. X
  472. X    /*
  473. X     * Do the fork.
  474. X     */
  475. X    if (sysnum == RSYS_vfork)
  476. X        vfork();
  477. X    else
  478. X        fork();
  479. X    val1 = u.u_r.r_val1;
  480. X    child = u.u_r.r_val2;
  481. X    if (u.u_error)
  482. X        child = FALSE;
  483. X    if (u.u_error || u.u_rmtsys == 0)
  484. X        goto done;
  485. X
  486. X    if (child) {
  487. X        ppid = u.u_procp->p_ppid;
  488. X        pid = u.u_procp->p_pid;
  489. X        u.u_procp->p_flag |= SREMOTE; /* set remote flag in child */
  490. X        u.u_rmtcdir = rmtdir;
  491. X    }
  492. X    else { /* parent */
  493. X        /* "if I am the parent && this is a vfork" */
  494. X        if (sysnum == RSYS_vfork)
  495. X            goto done;
  496. X        ppid = u.u_procp->p_pid;
  497. X        pid = u.u_r.r_val1;
  498. X    }
  499. X    /*
  500. X     * Parent (fork() only) and child tell all remote hosts.
  501. X     * Also, bump the count of users using all connections.
  502. X     */
  503. X    for (rp=remote_info, i=0; i<R_MAXSYS; i++, rp++)
  504. X        if (rmthostused(i) && rp->r_sock) {
  505. X            if(child)
  506. X                rp->r_users++;
  507. X            debug4("fork: %s %d notify %s(%d), users=%d\n",
  508. X                child ? "chld" : "prnt", u.u_procp->p_pid,
  509. X                rp->r_mntpath, i, rp->r_users);
  510. X            MGET(m, M_WAIT, MT_DATA);
  511. X            if (m == NULL)
  512. X                continue;
  513. X            msg = mtod(m, struct message *);
  514. X            msg->m_hdlen = m->m_len =
  515. X                introduce_2extra(msg, sysnum, pid, ppid);
  516. X            rmt_msgfin(i, m, RFLG_INFO);
  517. X        }
  518. X    /*
  519. X     * In the kernel, the r_val[12] elements get tromped on by the
  520. X     * io to the server hosts, so restore them here.
  521. X     * The 'u.u_error = 0;' is so that we don't run the real syscall
  522. X     * (already run) and so that any io errors while notifying servers
  523. X     * don't returned to the user... otherwise he might think the fork
  524. X     * or vfork failed.
  525. X     */
  526. X    u.u_r.r_val1 = val1;
  527. X    u.u_r.r_val2 = child;
  528. X    u.u_error = 0;
  529. Xdone:
  530. X    if (! child)
  531. X        rmtcopyhosts(u.u_rmtsys, rmtsys);
  532. X    return(u.u_error);
  533. X}
  534. X
  535. X/*
  536. X * This routine handles most system calls having a file descriptor as
  537. X * its first argument.  We are guarenteed at this point that uap->fd is
  538. X * a valid remote file descriptor.  We optimize for reads and writes.
  539. X */
  540. Xremote_fd(sysnum)
  541. X    register long    sysnum;
  542. X{
  543. X    struct a {
  544. X        long    fd;
  545. X        char    *buf;
  546. X        long    len;
  547. X    } *uap = (struct a *)u.u_ap;
  548. X    register long    sysindex, error;
  549. X    register struct message    *msg;
  550. X    register struct mbuf    *m;
  551. X    register syscalls    *sp = remote_syscall + sysnum;
  552. X    register struct file    *fp = u.u_ofile[ uap->fd ];
  553. X
  554. X    MGET(m, M_WAIT, MT_DATA);
  555. X    if (m == NULL)
  556. X        return(ENOBUFS);
  557. X    msg = mtod(m, struct message *);
  558. X    msg->m_hdlen = 0; /* rmt_datafin() or rmt_msgfin() will assign this */
  559. X    m->m_len = introduce_2extra(msg, sysnum, uap->fd, uap->len);
  560. X
  561. X    sysindex = (long)fp->f_data;
  562. X    error = (*sp->sys_spec)(sysindex, m, sp->sys_flag);
  563. X    if (! error)
  564. X        switch (sysnum) {
  565. X        case RSYS_read:
  566. X        case RSYS_write:
  567. X        case RSYS_readv:
  568. X        case RSYS_writev:
  569. X            fp->f_offset += u.u_r.r_val1;
  570. X            break;
  571. X        }
  572. X    return(error);
  573. X}
  574. X
  575. X/*
  576. X * Deallocate a file descriptor.
  577. X */
  578. Xrmt_deallocfd(fd)
  579. X    int    fd;
  580. X{
  581. X    register struct file    *fp;
  582. X    register struct remoteinfo    *rp;
  583. X    register unsigned    system;
  584. X
  585. X    fp = u.u_ofile[fd];
  586. X    u.u_ofile[fd] = NULL;
  587. X    if (fp == NULL
  588. X    || ((system = (unsigned)fp->f_data) >= R_MAXSYS)) {
  589. X        debug6("dealloc: fp=%x,fd=%d,sys=%d,pid=%d\n",
  590. X            fp, fd, system, u.u_procp->p_pid);
  591. X        return;
  592. X    }
  593. X
  594. X    remote_info[ (int)fp->f_data ].r_nfile--;
  595. X    closef(fp);
  596. X}
  597. SHAREOF
  598. chmod 444 remote/usr.sys.remote/rmt_general.c
  599. #
  600. # remote/usr.sys.remote/rmt_generic.c
  601. #
  602. if [ -f remote/usr.sys.remote/rmt_generic.c ]; then 
  603.     echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_generic.c or ^C to quit' 
  604.     read ans 
  605.     rm -f remote/usr.sys.remote/rmt_generic.c 
  606. fi 
  607.  
  608. sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_generic.c
  609. X/*
  610. X * Copyright 1985, Todd Brunhoff.
  611. X *
  612. X * This software was written at Tektronix Computer Research Laboratories
  613. X * as partial fulfillment of a Master's degree at the University of Denver.
  614. X * This is not Tektronix proprietary software and should not be
  615. X * confused with any software product sold by Tektronix.  No warranty is
  616. X * expressed or implied on the reliability of this software; the author,
  617. X * the University of Denver, and Tektronix, inc. accept no liability for
  618. X * any damage done directly or indirectly by this software.  This software
  619. X * may be copied, modified or used in any way, without fee, provided this
  620. X * notice remains an unaltered part of the software.
  621. X *
  622. X * $Header: rmt_generic.c,v 2.2 86/01/02 13:52:32 toddb Exp $
  623. X *
  624. X * $Log:    rmt_generic.c,v $
  625. X * Revision 2.2  86/01/02  13:52:32  toddb
  626. X * Ifdef'ed calls to sockargs() for the differences in 4.2 vs. 4.3.
  627. X * 
  628. X * Revision 2.1  85/12/30  16:58:59  toddb
  629. X * Isremote() was not freeing it's chain of mbufs if rmt_copypath() failed.
  630. X * Now it does.
  631. X * 
  632. X * Revision 2.0  85/12/07  18:18:27  toddb
  633. X * First public release.
  634. X * 
  635. X */
  636. X#include "../h/param.h"
  637. X#include "../h/systm.h"
  638. X#include "../h/inode.h"
  639. X#include "../h/dir.h"
  640. X#ifdef BSD4_3
  641. X#include "../h/namei.h"
  642. X#else BSD4_3
  643. X#include "../h/nami.h"
  644. X#endif BSD4_3
  645. X#ifndef pyr    /* Pyramid */
  646. X#include "../machine/pte.h"
  647. X#endif
  648. X#include "../h/user.h"
  649. X#include "../h/proc.h"
  650. X#include "../h/buf.h"
  651. X#include "../h/file.h"
  652. X#include "../h/uio.h"
  653. X#include "../h/mbuf.h"
  654. X#include "../h/socket.h"
  655. X#include "../h/socketvar.h"
  656. X#include "../h/errno.h"
  657. X#include "../remote/remotefs.h"
  658. X
  659. Xextern    long        remote_sysindex;
  660. Xextern struct mbuf    *remote_path;
  661. Xextern struct remoteinfo remote_info[];
  662. Xextern struct remoteinfo *remote_generic;
  663. Xextern struct nameserver    remote_ns;
  664. X
  665. X/*
  666. X * Remote "mount point" definition.
  667. X */
  668. X#ifdef pyr    /* Pyramid */
  669. Xremoteon(arg1, arg2, arg3, arg4)
  670. X{
  671. X#ifdef BSD4_3
  672. X    register struct nameidata *ndp = &u.u_nd;
  673. X#else BSD4_3
  674. X#endif BSD4_3
  675. X    struct a {
  676. X        char    *path;
  677. X        unsigned pathlen;
  678. X        caddr_t    name;
  679. X        unsigned namelen;
  680. X    } ua;
  681. X    register struct a *uap = &ua;
  682. X    register struct inode        *ip;
  683. X    register struct remoteinfo    *rp;
  684. X    struct remoteinfo        *rmt_findslot(),
  685. X                    *rmt_host();
  686. X    register int            error = 0;
  687. X    long                sysnum;
  688. X    struct mbuf *m = NULL;
  689. X
  690. X    uap->path = (char *)arg1;
  691. X    uap->pathlen = (unsigned)arg2;
  692. X    uap->name = (caddr_t)arg3;
  693. X    uap->namelen = (unsigned)arg4;
  694. X#else pyr
  695. Xremoteon()
  696. X{
  697. X#ifdef BSD4_3
  698. X    register struct nameidata *ndp = &u.u_nd;
  699. X#else BSD4_3
  700. X#endif BSD4_3
  701. X    register struct a {
  702. X        char    *path;
  703. X        unsigned pathlen;
  704. X        caddr_t    name;
  705. X        unsigned namelen;
  706. X    } *uap = (struct a *)u.u_ap;
  707. X    register struct inode        *ip;
  708. X    register struct remoteinfo    *rp;
  709. X    struct remoteinfo        *rmt_findslot(),
  710. X                    *rmt_host();
  711. X    register int            error = 0;
  712. X    long                sysnum;
  713. X    struct mbuf *m = NULL;
  714. X#endif
  715. X
  716. X    if (uap->path == NULL) {
  717. X        u.u_procp->p_flag &= ~SNOREMOTE;
  718. X        return;
  719. X    }
  720. X    if (!suser())
  721. X        return;
  722. X#ifdef BSD4_3
  723. X    ndp->ni_nameiop = LOOKUP;
  724. X    ndp->ni_segflg = UIO_USERSPACE;
  725. X    ndp->ni_dirp = (caddr_t)uap->path;
  726. X    ip = namei(ndp);
  727. X#else BSD4_3
  728. X    ip = namei(uchar, LOOKUP, 0);
  729. X#endif BSD4_3
  730. X    debug5("remote on ip=%x,path=%x,pthlen=%d,name=%x,nmlen=%d\n",
  731. X        ip, uap->path, uap->pathlen, uap->name, uap->namelen);
  732. X    if (ip == NULL)
  733. X        return;
  734. X    if (uap->pathlen >= R_MNTPATHLEN)
  735. X        uap->pathlen = R_MNTPATHLEN - 1;
  736. X
  737. X    /*
  738. X     * Check for all kinds of errors.
  739. X     */
  740. X    if (rmt_host(ip, &sysnum) || (uap->name == NULL && remote_generic))
  741. X        error = EBUSY;
  742. X    else if ((ip->i_mode&IFMT) == IFDIR)
  743. X        error = EISDIR;
  744. X    else if (uap->name)
  745. X#ifdef BSD4_3
  746. X        error = sockargs(&m, uap->name, uap->namelen, MT_SONAME);
  747. X#else BSD4_3
  748. X        error = sockargs(&m, uap->name, uap->namelen);
  749. X#endif BSD4_3
  750. X    if (error)
  751. X        goto out;
  752. X
  753. X    /*
  754. X     * Everything is ok... so put it in our list.
  755. X     */
  756. X    rp = rmt_findslot(&sysnum);
  757. X    if (rp == NULL)
  758. X        error = ETOOMANYREMOTE;
  759. X    else {
  760. X        debug5("rp=%x, m=%x ip=%x sys=%d\n", rp, m, ip, sysnum);
  761. X        rp->r_mntpt = ip;
  762. X        if ((rp->r_name = m) == NULL)
  763. X            remote_generic = rp;
  764. X        (void)copyin((caddr_t)uap->path, (caddr_t)rp->r_mntpath,
  765. X            MIN(uap->pathlen, R_MNTPATHLEN));
  766. X        u.u_r.r_val1 = sysnum;
  767. X        iunlock(ip);
  768. X        return;
  769. X    }
  770. X
  771. Xout:
  772. X    u.u_error = error;
  773. X    iput(ip);
  774. X}
  775. X
  776. X/*
  777. X * Turn off the remote file system.  If the path to unmount is NULL, then
  778. X * turn off all remote access for this process.
  779. X */
  780. X#ifdef pyr    /* Pyramid */
  781. Xremoteoff(arg1)
  782. X{
  783. X#ifdef BSD4_3
  784. X    register struct nameidata *ndp = &u.u_nd;
  785. X#else BSD4_3
  786. X#endif BSD4_3
  787. X    struct a {
  788. X        char    *path;
  789. X    } ua;
  790. X    register struct a *uap = &ua;
  791. X    register struct inode *ip;
  792. X    register struct remoteinfo    *rp;
  793. X    struct remoteinfo        *rmt_host();
  794. X    long            sysnum;
  795. X
  796. X    uap->path = (char *)arg1;
  797. X#else pyr
  798. Xremoteoff()
  799. X{
  800. X#ifdef BSD4_3
  801. X    register struct nameidata *ndp = &u.u_nd;
  802. X#else BSD4_3
  803. X#endif BSD4_3
  804. X    register struct a {
  805. X        char    *path;
  806. X    } *uap = (struct a *)u.u_ap;
  807. X    register struct inode *ip;
  808. X    register struct remoteinfo    *rp;
  809. X    struct remoteinfo        *rmt_host();
  810. X    long            sysnum;
  811. X#endif pyr
  812. X
  813. X    if (uap->path == NULL) {
  814. X        u.u_procp->p_flag |= SNOREMOTE;
  815. X        return;
  816. X    }
  817. X    if (!suser())
  818. X        return;
  819. X#ifdef BSD4_3
  820. X    ndp->ni_nameiop = LOOKUP;
  821. X    ndp->ni_segflg = UIO_USERSPACE;
  822. X    ndp->ni_dirp = (caddr_t)uap->path;
  823. X    ip = namei(ndp);
  824. X#else BSD4_3
  825. X    ip = namei(uchar, LOOKUP, 0);
  826. X#endif BSD4_3
  827. X    if (ip == NULL || (rp = rmt_host(ip, &sysnum)) == NULL) {
  828. X        if (ip)
  829. X            iput(ip);
  830. X        debug5("remoteoff: nope! ip=%x error=%d\n",
  831. X            ip, u.u_error);
  832. X        u.u_error = EINVAL;
  833. X        return;
  834. X    }
  835. X
  836. X    debug5("remote off ip=%x\n", ip);
  837. X    iput(ip);
  838. X
  839. X    /*
  840. X     * Now try to shut it down. 
  841. X     */
  842. X    rp->r_close = TRUE;
  843. X    if (u.u_error = rmt_shutdown(sysnum))
  844. X        return;
  845. X    u.u_r.r_val1 = remote_sysindex;
  846. X    /*
  847. X     * reinitialize the structure for the next time,
  848. X     * freeing the mbuf and closing the socket.
  849. X     */
  850. X    rp->r_refcnt = 0;
  851. X    rp->r_nchdir = 0;
  852. X    rp->r_nfile = 0;
  853. X    if (rp->r_mntpt)
  854. X        irele(rp->r_mntpt);
  855. X    rp->r_mntpt = 0;
  856. X    if (rp->r_name)
  857. X        (void)m_free(rp->r_name);
  858. X    else
  859. X        remote_generic = NULL;
  860. X    rp->r_name = 0;
  861. X    return;
  862. X}
  863. X
  864. X/*
  865. X * This provides the nameserver function allowing
  866. X * name information to pass to and from a server and the kernel.
  867. X */
  868. X#ifdef pyr    /* Pyramid */
  869. Xremotename(arg1, arg2, arg3, arg4)
  870. X{
  871. X    struct a {
  872. X        long    action;
  873. X        caddr_t    name;
  874. X        long    namelen;
  875. X        char    *path;
  876. X    } ap;
  877. X    register struct a *uap = ≈
  878. X    register long    error = 0;
  879. X    struct mbuf        *m;
  880. X    register struct proc    *p = u.u_procp;
  881. X
  882. X    uap->action = (long)arg1;
  883. X    uap->name = (caddr_t)arg2;
  884. X    uap->namelen = (long)arg3;
  885. X    uap->path = (char *)arg4;
  886. X#else pyr
  887. Xremotename()
  888. X{
  889. X    register struct a {
  890. X        long    action;
  891. X        caddr_t    name;
  892. X        long    namelen;
  893. X        char    *path;
  894. X    } *uap = (struct a *)u.u_ap;
  895. X    register long    error = 0;
  896. X    struct mbuf        *m;
  897. X    register struct proc    *p = u.u_procp;
  898. X#endif pyr
  899. X
  900. X    if ((uap->action == NM_WHATNAME || uap->action == NM_NAMEIS)
  901. X    && ! server_alive(p))
  902. X        error = EPERM;
  903. X    else switch (uap->action) {
  904. X    case NM_SERVER:        /* register as name server */
  905. X    {
  906. X        struct proc    *p2;
  907. X        short        pid;
  908. X
  909. X        if (!suser())
  910. X            return;
  911. X        p2 = remote_ns.rn_proc;
  912. X        pid = remote_ns.rn_pid;
  913. X        if (server_alive(p2))
  914. X            error = EBUSY;
  915. X        else {
  916. X            remote_ns.rn_proc = p;
  917. X            remote_ns.rn_pid = p->p_pid;
  918. X        }
  919. X        break;
  920. X    }
  921. X    case NM_WHATNAME:
  922. X        if (remote_ns.rn_path)
  923. X            error = copyout((caddr_t)remote_ns.rn_path,
  924. X                (caddr_t)uap->path,
  925. X                MIN(uap->namelen, remote_ns.rn_pathlen));
  926. X        else
  927. X            error = ENOREMOTEFS;
  928. X        break;
  929. X    case NM_NAMEIS:
  930. X    {
  931. X        register char    *cp;
  932. X
  933. X        m = remote_ns.rn_name;
  934. X        if (m) {
  935. X            debug13("free old mbuf@%x\n", m);
  936. X            m_free(m); /* free extra mbuf */
  937. X            m = remote_ns.rn_name = NULL;
  938. X        }
  939. X#ifdef BSD4_3
  940. X        error = sockargs(&m, uap->name, uap->namelen, MT_SONAME);
  941. X#else BSD4_3
  942. X        error = sockargs(&m, uap->name, uap->namelen);
  943. X#endif BSD4_3
  944. X        if (error == 0) {
  945. X            cp = mtod(m, char *) + m->m_len;
  946. X            if (error = copyin((caddr_t)uap->path, (caddr_t)cp,
  947. X                MIN(R_MNTPATHLEN, MLEN - m->m_len))) {
  948. X                m_free(m);
  949. X                m = NULL;
  950. X            }
  951. X            debug13("nmsrv: %s@%x\n", cp, m);
  952. X        }
  953. X        remote_ns.rn_name = m;
  954. X        wakeup(&remote_ns.rn_name);
  955. X        break;
  956. X    }
  957. X#ifdef RFSDEBUG
  958. X    case NM_DEBUG:
  959. X        remote_debug = (long)uap->name;
  960. X        printf("dbg=%d\n", remote_debug);
  961. X        break;
  962. X#endif RFSDEBUG
  963. X    default:
  964. X        error = EINVAL;
  965. X        break;
  966. X    }
  967. X    if (error)
  968. X        u.u_error = error;
  969. X}
  970. X
  971. X/*
  972. X * This is the routine called by namei() when it encounters what it thinks
  973. X * might be a remote mount point.
  974. X */
  975. Xisremote(ip, path, base)
  976. X    register struct inode *ip;
  977. X    char        *path, *base;
  978. X{
  979. X    struct remoteinfo *rmt_host(), *rmt_findhost();
  980. X    register short    offset;
  981. X    register struct remoteinfo *rp;
  982. X    register struct mbuf    *m;
  983. X    register struct message    *msg;
  984. X    register int    error;
  985. X    long            sysnum;
  986. X
  987. X    rp = rmt_host(ip, &sysnum);
  988. X    if (rp == NULL) {
  989. X        debug7("%s, ip=\"%x\" is not remote\n", path, ip);
  990. X        return(FALSE);
  991. X    }
  992. X    if (remote_path)
  993. X        m_freem(remote_path);
  994. X    remote_path = NULL;
  995. X
  996. X    /*
  997. X     * Adjust the path so that if there is a leading '/', the path
  998. X     * will start there.
  999. X     */
  1000. X    if (path != base && *path != '/' && *(path-1) == '/')
  1001. X        path--;
  1002. X
  1003. X    /*
  1004. X     * Although we know the file is remote, it may have a loop back
  1005. X     * to this side; a simple case being if the path is '..' while
  1006. X     * in the root directory of the remote system.  If this is the case
  1007. X     * then the server will reply with errno == -1, remote_path[12]()
  1008. X     * will assign u.u_rmtoffset[0,1] and the real system call will be
  1009. X     * run again, bringing us back to here.  We know that that has
  1010. X     * happened if either of u.u_rmtoffset[0,1] is >= 0.  We then
  1011. X     * just adjust the path handed to us by namei() and return
  1012. X     * -1 which signals namei() to begin again with the new
  1013. X     * path with directory set to root (/).
  1014. X     */
  1015. X    if ((u.u_procp->p_flag & SREMOTE) == 0) {
  1016. X        u.u_rmtcdir = -1;
  1017. X        offset = -1;
  1018. X    }
  1019. X    else if ((offset = u.u_rmtoffset[0]) >= 0)
  1020. X        u.u_rmtoffset[0] = -1;
  1021. X    else if ((offset = u.u_rmtoffset[1]) >= 0)
  1022. X        u.u_rmtoffset[1] = -1;
  1023. X    if (offset >= 0) {
  1024. X        register char    *pstart = path + offset;
  1025. X        register char    *p = path;
  1026. X
  1027. X        debug8("restart path %s locally, offset=%d\n", path, offset);
  1028. X        if (offset) /* validate offset value */
  1029. X            while (p <= pstart)
  1030. X                if (*p++ == '\0') {
  1031. X                    u.u_error = EINVAL;
  1032. X                    return(FALSE);
  1033. X                } 
  1034. X        if (base != pstart) {
  1035. X            path = base;
  1036. X            do {
  1037. X                *path++ = *pstart;
  1038. X            } while (*pstart++);
  1039. X        }
  1040. X        return(-1);
  1041. X    }
  1042. X
  1043. X    /*
  1044. X     * We have a remote mount point.  However, it may be in the midst of
  1045. X     * shutting down from some error.  This mount point may also be
  1046. X     * a "generic" mount point, in which case, we must figure out
  1047. X     * the host.
  1048. X     */
  1049. X    if (rp->r_name == NULL) {
  1050. X        rp = rmt_findhost(&path, &sysnum);
  1051. X        if (rp == NULL) {
  1052. X            debug8("isremote: can't map path %s\n", path);
  1053. X            return(TRUE);
  1054. X        }
  1055. X    }
  1056. X    if (rp->r_close) {
  1057. X        debug8("isremote: host %s is closing\n", rp->r_mntpath);
  1058. X        u.u_error = ENOREMOTEFS;
  1059. X        return(TRUE);
  1060. X    }
  1061. X    u.u_error = EISREMOTE;
  1062. X    remote_sysindex = sysnum;
  1063. X    /*
  1064. X     * Set the remote flag for this user and bump the
  1065. X     * user count.
  1066. X     */
  1067. X    u.u_procp->p_flag |= SREMOTE;
  1068. X    if (! rmthostused(sysnum)) {
  1069. X        rp->r_users++;
  1070. X        rmtusehost(sysnum);
  1071. X        debug4("%d uses rmt %d\n", u.u_procp->p_pid, sysnum);
  1072. X    }
  1073. X    rmtusehost(sysnum);
  1074. X    debug7("%s, ip=%x is remote, idx=%d\n", path, ip, remote_sysindex);
  1075. X    MGET(m, M_WAIT, MT_DATA);
  1076. X    if (m != NULL) {
  1077. X        msg = mtod(m, struct message *);
  1078. X        msg->m_hdlen = R_MINRMSG + R_PATHSTART*sizeof(long);
  1079. X        m->m_len = R_MINRMSG + R_PATHSTART*sizeof(long);
  1080. X        if (error = rmt_copypath(path, m, FALSE)) {
  1081. X            m_freem(m);
  1082. X            u.u_error = error;
  1083. X            return(TRUE);
  1084. X        }
  1085. X        remote_path = m;
  1086. X    }
  1087. X    else
  1088. X        u.u_error = ENOBUFS;
  1089. X    return(TRUE);
  1090. X}
  1091. SHAREOF
  1092. chmod 444 remote/usr.sys.remote/rmt_generic.c
  1093. #
  1094. # remote/usr.sys.remote/rmt_io.c
  1095. #
  1096. if [ -f remote/usr.sys.remote/rmt_io.c ]; then 
  1097.     echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_io.c or ^C to quit' 
  1098.     read ans 
  1099.     rm -f remote/usr.sys.remote/rmt_io.c 
  1100. fi 
  1101.  
  1102. sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_io.c
  1103. X/*
  1104. X * Copyright 1985, Todd Brunhoff.
  1105. X *
  1106. X * This software was written at Tektronix Computer Research Laboratories
  1107. X * as partial fulfillment of a Master's degree at the University of Denver.
  1108. X * This is not Tektronix proprietary software and should not be
  1109. X * confused with any software product sold by Tektronix.  No warranty is
  1110. X * expressed or implied on the reliability of this software; the author,
  1111. X * the University of Denver, and Tektronix, inc. accept no liability for
  1112. X * any damage done directly or indirectly by this software.  This software
  1113. X * may be copied, modified or used in any way, without fee, provided this
  1114. X * notice remains an unaltered part of the software.
  1115. X *
  1116. X * $Header: rmt_io.c,v 2.1 85/12/30 16:53:01 toddb Exp $
  1117. X *
  1118. X * $Log:    rmt_io.c,v $
  1119. X * Revision 2.1  85/12/30  16:53:01  toddb
  1120. X * Changed shutdown messages for the remotefs from debug messages to 
  1121. X * printf messages.  Also fixed a bug where the return value field in
  1122. X * rp->r_msg.m_args[ R_RETVAL ] was getting cleared for process `x'
  1123. X * by process `y' when process `y' was executing an INFO_ONLY type
  1124. X * of remote system call (like close or fork).  This bug was causing
  1125. X * random system calls (like read or write) to return 0 when it should
  1126. X * have returned something non-zero.
  1127. X * 
  1128. X * Revision 2.0  85/12/07  18:18:51  toddb
  1129. X * First public release.
  1130. X * 
  1131. X */
  1132. X#include "../h/param.h"
  1133. X#include "../h/dir.h"
  1134. X#ifndef pyr    /* Pyramid */
  1135. X#include "../machine/pte.h"
  1136. X#endif
  1137. X#include "../h/user.h"
  1138. X#include "../h/proc.h"
  1139. X#include "../h/buf.h"
  1140. X#include "../h/uio.h"
  1141. X#include "../h/mbuf.h"
  1142. X#include "../h/socket.h"
  1143. X#include "../h/socketvar.h"
  1144. X#include "../h/protosw.h"
  1145. X#include "../h/errno.h"
  1146. X#include "../remote/remotefs.h"
  1147. X#include "../h/inode.h"
  1148. X#include "../h/kernel.h"
  1149. X#include "../netinet/in.h"
  1150. X
  1151. Xextern struct remoteinfo    remote_info[];
  1152. Xextern struct remoteinfo    *remote_generic;
  1153. X
  1154. X/*
  1155. X * Obtain a connection to 'system'.
  1156. X */
  1157. Xremote_getconnection(system)
  1158. X    register int    system;
  1159. X{
  1160. X    register struct remoteinfo    *rp = remote_info + system;
  1161. X    register err, s, opening = FALSE;
  1162. X    short    uid;
  1163. X    struct socket *so = NULL;
  1164. X
  1165. X    if (! rp->r_name) {
  1166. X        rmt_unuse(rp, system);
  1167. X        return(ENOREMOTEFS);    /* no address to call. */
  1168. X    }
  1169. X
  1170. X    /*
  1171. X     * Lock out other processes from doing an open at the same time.
  1172. X     */
  1173. X    if (rp->r_opening) {
  1174. X        if (setjmp(&u.u_qsave)) {
  1175. X            rmt_unuse(rp, system);
  1176. X            return(EINTR);
  1177. X        }
  1178. X        while (rp->r_opening)
  1179. X            sleep((caddr_t)&rp->r_sock);
  1180. X        if (rp->r_sock)
  1181. X            return(0);
  1182. X        rmt_unuse(rp, system);
  1183. X        return(rp->r_openerr);
  1184. X    }
  1185. X    /*
  1186. X     * We may already have a connection
  1187. X     */
  1188. X    else if (rp->r_sock)
  1189. X        return(0);
  1190. X    /*
  1191. X     * If we have failed previously, it may be time to try again.
  1192. X     */
  1193. X    else if (rp->r_failed) {
  1194. X        if (rp->r_age > time.tv_sec)
  1195. X            return(rp->r_openerr);
  1196. X        rp->r_failed = FALSE;
  1197. X    }
  1198. X    rp->r_opening = TRUE;
  1199. X
  1200. X    /*
  1201. X     * pseudo loop to avoid labels...
  1202. X     */
  1203. X    do {
  1204. X        /*
  1205. X         * Fortunately, there is security with ports.  Unfortunately,
  1206. X         * you must be root to do it.  So we change our uid for a
  1207. X         * brief moment.
  1208. X         */
  1209. X        uid = u.u_uid;
  1210. X        if (setjmp(&u.u_qsave)) {
  1211. X            u.u_uid = uid;
  1212. X            if (u.u_error == 0)
  1213. X                err = EINTR;
  1214. X            break;
  1215. X        }
  1216. X
  1217. X        /*
  1218. X         * first, make a socket for the connection; then connect.  (the
  1219. X         * connection code is basically connect(2)).
  1220. X         */
  1221. X        if (err = socreate(AF_INET, &rp->r_sock, SOCK_STREAM, 0))
  1222. X            break;
  1223. X
  1224. X        so = rp->r_sock;
  1225. X        debug9("connect...");
  1226. X        err = soconnect(so, rp->r_name);
  1227. X        u.u_uid = uid;
  1228. X        if (err)
  1229. X            break;
  1230. X
  1231. X        s = splnet();
  1232. X        if ((so->so_state & SS_NBIO) &&
  1233. X            (so->so_state & SS_ISCONNECTING)) {
  1234. X            err = EINPROGRESS;
  1235. X            splx(s);
  1236. X            break;
  1237. X        }
  1238. X        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
  1239. X            debug9(".");
  1240. X            sleep((caddr_t)&so->so_timeo, PZERO+1);
  1241. X        }
  1242. X        err = so->so_error;
  1243. X        so->so_error = 0;
  1244. X        rp->r_sock = so;
  1245. X        rp->r_sender = rp->r_recver = -1;
  1246. X        sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, NULL);
  1247. X        splx(s);
  1248. X    } while (FALSE);
  1249. X
  1250. X    if (err) {
  1251. X        rp->r_sock = 0;
  1252. X        rp->r_openerr = err;
  1253. X        rp->r_failed = TRUE;
  1254. X        rp->r_age = time.tv_sec + R_RETRY;
  1255. X        debug9("err=%d\n", err);
  1256. X        rmt_unuse(rp, system);
  1257. X        if (so)
  1258. X            soclose(so);
  1259. X    }
  1260. X    else
  1261. X        debug9(" done.\n");
  1262. X    rp->r_opening = FALSE;
  1263. X    wakeup((caddr_t)&rp->r_sock);
  1264. X    return(err);
  1265. X}
  1266. X
  1267. X/*
  1268. X * Back out of references to a remote host.
  1269. X */
  1270. Xrmt_unuse(rp, system)
  1271. X    register struct remoteinfo *rp;
  1272. X    register long    system;
  1273. X{
  1274. X    rp->r_users--;
  1275. X    rmtunusehost(system);
  1276. X    if (u.u_rmtsys == 0)
  1277. X        u.u_procp->p_flag &= ~SREMOTE;
  1278. X}
  1279. X
  1280. X/*
  1281. X * Send out the message.
  1282. X */
  1283. Xremoteio(system, m, uio, flags)
  1284. X    register int    system;
  1285. X    register struct mbuf    **m;
  1286. X    register struct uio *uio;
  1287. X    int    flags;
  1288. X{
  1289. X    register int    error, signaled = 0, position;
  1290. X    register struct remoteinfo    *rp = remote_info + system;
  1291. X    register struct socket    *so;
  1292. X    register struct iovec *iov;
  1293. X    register struct proc    *p;
  1294. X    long    soreceive(), sosend();
  1295. X    long    oldmask;
  1296. X
  1297. X
  1298. X    /*
  1299. X     * get a connection.
  1300. X     */
  1301. X    if ((so = rp->r_sock) == NULL)
  1302. X        if (error = remote_getconnection(system)) {
  1303. X            (void) m_freem(*m);
  1304. X            return(error);
  1305. X        }
  1306. X        else
  1307. X            so = rp->r_sock;
  1308. X
  1309. X    /*
  1310. X     * "Hold" SIGTSTP and SIGSTOP signals until we are done.
  1311. X     */
  1312. X    p = u.u_procp;
  1313. X    oldmask = (1 << (SIGTSTP-1))
  1314. X        | (1 << (SIGSTOP-1));
  1315. X    oldmask = (p->p_sigmask & oldmask);
  1316. X    p->p_sigmask |= (1 << (SIGTSTP-1))
  1317. X            | (1 << (SIGSTOP-1));
  1318. X
  1319. X    /*
  1320. X     * Note that we re-do the setjmp each time we change state.
  1321. X     * Two reasons: 1) we are effectively ignoring interrupts until
  1322. X     * either the message has been completely sent or has been
  1323. X     * completely recieved. 2) setjmp() restores register variables to
  1324. X     * their state at the time of the call and since we modify them
  1325. X     * all the time, we need to re-save the state.
  1326. X     */
  1327. X    position = R_NOTHINGSENT;
  1328. X    rp->r_refcnt++; /* we are actively using conection */
  1329. X
  1330. X    while(position != 0) {
  1331. X        if (setjmp(&u.u_qsave)) {
  1332. X            error = EINTR;
  1333. X            debug10("signal to %d\n", u.u_procp->p_pid);
  1334. X            if (rp->r_close)
  1335. X                goto remoteio_done;
  1336. X            signaled++;
  1337. X            continue;
  1338. X        }
  1339. X
  1340. X        switch (position) {
  1341. X        case R_NOTHINGSENT:
  1342. X            /*
  1343. X             * make sure that this is not someone elses data.
  1344. X             */
  1345. X            if (signaled)
  1346. X                goto remoteio_done;
  1347. X            while (!rp->r_close && rp->r_sender >= 0) {
  1348. X                debug10("I am %d, not %d. Goodnight.\n",
  1349. X                    u.u_procp->p_pid, rp->r_sender);
  1350. X                sleep((caddr_t)&rp->r_sender, PZERO+1);
  1351. X            }
  1352. X            if (rp->r_close)
  1353. X                goto remoteio_done;
  1354. X
  1355. X            /*
  1356. X             * We update position BEFORE we call tcp_usrreq()
  1357. X             * because we are guarenteed that the data will be
  1358. X             * sent just by making the call.  i.e. we will never
  1359. X             * come back to this point once we've been here.
  1360. X             */
  1361. X            if (uio && (flags & RFLG_WR))
  1362. X                position = R_DATANOTSENT;
  1363. X            else
  1364. X                position = R_MSGNOTRED;
  1365. X            rp->r_sender = u.u_procp->p_pid;
  1366. X            debug10("%d sending... ", rp->r_sender);
  1367. X            error = (*so->so_proto->pr_usrreq)(so,
  1368. X                PRU_SEND, *m, 0, 0);
  1369. X            if (error) {
  1370. X                printf("error=%d on sending msg\n", error);
  1371. X                rp->r_close = TRUE;
  1372. X                goto remoteio_done;
  1373. X            }
  1374. X            *m = 0;
  1375. X            break;
  1376. X
  1377. X        case R_DATANOTSENT:
  1378. X            debug10("%d data\n", u.u_procp->p_pid);
  1379. X            if (error = rmt_uio(rp, uio, sosend))
  1380. X                flushmsg(rp, uio->uio_resid, FALSE);
  1381. X            position = R_MSGNOTRED;
  1382. X            break;
  1383. X
  1384. X        case R_MSGNOTRED:
  1385. X            /*
  1386. X             * Finally, read from the socket.  Also, if
  1387. X             * we have been interrupted, now is the time to
  1388. X             * notify the other side.
  1389. X             */
  1390. X            rp->r_sender = -1;
  1391. X            wakeup(&rp->r_sender);
  1392. X            if (flags & RFLG_INFO) {
  1393. X                position = 0;
  1394. X                break;
  1395. X            }
  1396. X            debug10("%d recving\n", u.u_procp->p_pid);
  1397. X            if (signaled)
  1398. X                sendrsig(system);
  1399. X            error = rmt_getmsg(system);
  1400. X            rp->r_received = FALSE;
  1401. X            if (error || rp->r_close)
  1402. X                goto remoteio_done;
  1403. X            if (uio && (flags & RFLG_RD))
  1404. X                position = R_DATANOTRED;
  1405. X            else {
  1406. X                rp->r_recver = -1;
  1407. X                position = 0;
  1408. X                wakeup(&rp->r_recver);
  1409. X            }
  1410. X            break;
  1411. X        case R_DATANOTRED:
  1412. X            debug10("%d recving data\n", u.u_procp->p_pid);
  1413. X            if (rp->r_msg.m_args[ R_RETVAL ] > uio->uio_resid) {
  1414. X                printf("usr needs %d, srvr says %d\n",
  1415. X                    uio->uio_resid,
  1416. X                    rp->r_msg.m_args[ R_RETVAL ]);
  1417. X                rp->r_close = TRUE;
  1418. X                goto remoteio_done;
  1419. X            }
  1420. X                    
  1421. X            uio->uio_resid = rp->r_msg.m_args[ R_RETVAL ];
  1422. X            if (error = rmt_uio(rp, uio, soreceive)) {
  1423. X                flushmsg(rp, uio->uio_resid, TRUE);
  1424. X                break;
  1425. X            }
  1426. X            rp->r_recver = -1;
  1427. X            wakeup(&rp->r_recver);
  1428. X            position = 0;
  1429. X            break;
  1430. X        }
  1431. X    }
  1432. Xremoteio_done:
  1433. X    /*
  1434. X     * Restore mask by first taking out SIGTSTP and SIGSTOP, whatever
  1435. X     * their values.  And then or'ing in the original value.
  1436. X     */
  1437. X    p = u.u_procp;
  1438. X    p->p_sigmask &= ~((1 << (SIGTSTP-1))
  1439. X            | (1 << (SIGSTOP-1)));
  1440. X    p->p_sigmask |= oldmask;
  1441. X
  1442. X    rp->r_refcnt--; /* we are done with this transaction */
  1443. X    if (rp->r_close)
  1444. X        error = ECONNABORTED;
  1445. X    if (error) {
  1446. X        debug11("remoteio: err=%d, close=%s\n",
  1447. X            error, rp->r_close ? "true" : "false");
  1448. X        rmt_shutdown(system);
  1449. X    }
  1450. X    return(error);
  1451. X}
  1452. X
  1453. X/*
  1454. X * Force io to happen and consume all of uio->uio_resid.
  1455. X */
  1456. Xrmt_uio(rp, uio, sockfunc)
  1457. X    register struct remoteinfo    *rp;
  1458. X    register struct uio    *uio;
  1459. X    register func        sockfunc;
  1460. X{
  1461. X    register struct socket    *so = rp->r_sock;
  1462. X    label_t    qsave;
  1463. X    register long    error = 0,
  1464. X            flag = (sockfunc == soreceive)
  1465. X                ? SS_CANTRCVMORE : SS_CANTSENDMORE;
  1466. X
  1467. X    bcopy(&u.u_qsave, &qsave, sizeof(label_t));
  1468. X    if (setjmp(&u.u_qsave)) {
  1469. X        debug11("rmt_uio: sig %d\n", u.u_procp->p_pid);
  1470. X        if (rp->r_close)
  1471. X            error = ECONNABORTED;
  1472. X    }
  1473. X    while(uio->uio_resid > 0 && ! error && (so->so_state & flag) == 0)
  1474. X        error = (*sockfunc)(so, 0, uio, 0, 0);
  1475. X    bcopy(&qsave, &u.u_qsave, sizeof(label_t));
  1476. X    if (so->so_state & flag) {
  1477. X        rp->r_close = TRUE;
  1478. X        error = ECONNABORTED;
  1479. X    }
  1480. X    return(error);
  1481. X}
  1482. X
  1483. X/*
  1484. X * Obtain the next message from the server.  We don't return from this
  1485. X * routine until our personal message has been received or an error
  1486. X * has occured.
  1487. X */
  1488. Xrmt_getmsg(system)
  1489. X    register int    system;
  1490. X{
  1491. X    struct proc    *p = NULL;
  1492. X    struct remoteinfo    *rp = remote_info + system;
  1493. X    struct socket *so = rp->r_sock;
  1494. X    struct uio    auio;
  1495. X    struct iovec    iov;
  1496. X    register long    msglen, len, error = 0;
  1497. X    long        soreceive();
  1498. X
  1499. X    for(;;) {
  1500. X        iov.iov_len = auio.uio_resid = R_MINRMSG+sizeof(long);
  1501. X        auio.uio_segflg = 1;    /* kernel bcopy */
  1502. X        auio.uio_iov = &iov;
  1503. X        auio.uio_iovcnt = 1;
  1504. X        auio.uio_offset = 0;
  1505. X        iov.iov_base = (caddr_t)&rp->r_msg;
  1506. X
  1507. X        /*
  1508. X         * Since we may have been usurped by this time, or a different
  1509. X         * syscall may have been repsponded to, we must make sure
  1510. X         * that we are the recipient of this message.  In fact,
  1511. X         * the message may have already arrived.
  1512. X         */
  1513. X        while (rp->r_recver != u.u_procp->p_pid && rp->r_recver != -1)
  1514. X            sleep((caddr_t)&rp->r_recver, PZERO+1);
  1515. X        if (rp->r_recver == u.u_procp->p_pid && rp->r_received) {
  1516. X            auio.uio_resid = 0;
  1517. X            break;
  1518. X        }
  1519. X        rp->r_recver = u.u_procp->p_pid;
  1520. X
  1521. X        /*
  1522. X         * get the message.
  1523. X         */
  1524. X        if (error = rmt_uio(rp, &auio, soreceive)) {
  1525. X            debug11("1st: err=%d\n", error);
  1526. X            break;
  1527. X        }
  1528. X#ifndef magnolia
  1529. X        rp->r_msg.m_totlen  = ntohl(rp->r_msg.m_totlen);
  1530. X        rp->r_msg.m_hdlen   = ntohs(rp->r_msg.m_hdlen);
  1531. X        rp->r_msg.m_pid     = ntohs(rp->r_msg.m_pid);
  1532. X        rp->r_msg.m_uid     = ntohs(rp->r_msg.m_uid);
  1533. X        rp->r_msg.m_errno = ntohs(rp->r_msg.m_errno);
  1534. X        rp->r_msg.m_args[ R_RETVAL ]
  1535. X                = ntohl(rp->r_msg.m_args[ R_RETVAL ]);
  1536. X#endif
  1537. X        msglen = rp->r_msg.m_hdlen;
  1538. X        if (msglen > R_MAXRMSG
  1539. X         || msglen < R_MINRMSG+sizeof(long)
  1540. X         || auio.uio_offset < R_MINRMSG+sizeof(long)) {
  1541. X            debug11("msg len=%d, off=%d!\n",
  1542. X                msglen, auio.uio_offset);
  1543. X            error = ECONNABORTED;
  1544. X            break;
  1545. X        }
  1546. X
  1547. X        /*
  1548. X         * We may need a few more bytes.
  1549. X         */
  1550. X        if (msglen > R_MINRMSG + sizeof(long)) {
  1551. X            iov.iov_len = auio.uio_resid =
  1552. X                msglen - auio.uio_offset;
  1553. X            auio.uio_iov = &iov;
  1554. X            auio.uio_iovcnt = 1;
  1555. X            debug10("getmsg2: resid=%d... cc=%d\n",
  1556. X                auio.uio_resid, so->so_rcv.sb_cc);
  1557. X            if (error = rmt_uio(rp, &auio, soreceive)) {
  1558. X                debug11("2nd: err=%d, resid=%d, msglen=%d\n",    
  1559. X                    error, auio.uio_resid, msglen);
  1560. X                break;
  1561. X            }
  1562. X        }
  1563. X
  1564. X        /*
  1565. X         * Now find the right recipient.
  1566. X         */
  1567. X        rp->r_received = TRUE;
  1568. X        rp->r_recver = rp->r_msg.m_pid;
  1569. X        if (rp->r_recver == u.u_procp->p_pid)
  1570. X            break;
  1571. X        if (rp->r_recver >= 0 && (p = pfind(rp->r_recver))) {
  1572. X            debug11("%d: msg for %d@%x\n",
  1573. X                u.u_procp->p_pid, rp->r_recver, p->p_wchan);
  1574. X            if (p->p_wchan == (caddr_t)&rp->r_recver)
  1575. X                setrun(p);
  1576. X            continue;
  1577. X        }
  1578. X        else
  1579. X            debug11("proc %d?\n", rp->r_recver);
  1580. X        flushmsg(rp, rp->r_msg.m_totlen - rp->r_msg.m_hdlen, TRUE);
  1581. X    }
  1582. X
  1583. X    /*
  1584. X     * Wrap up and decide if everything is still kosher...
  1585. X     */
  1586. X    if (rp->r_close || error || auio.uio_resid) {
  1587. X        debug11("%d: getmsg: close=%s,err=%d,resid=%d\n",
  1588. X            u.u_procp->p_pid, rp->r_close ? "true" : "false",
  1589. X            error, auio.uio_resid);
  1590. X        rp->r_close = TRUE;
  1591. X        rmt_shutdown(system);
  1592. X        error = ECONNABORTED;
  1593. X    }
  1594. X    return(error);
  1595. X}
  1596. X
  1597. Xflushmsg(rp, len, input)
  1598. X    register struct remoteinfo    *rp;
  1599. X    register long    len, input;
  1600. X{
  1601. X    register struct socket *so = rp->r_sock;
  1602. X    register long    error = 0, need;
  1603. X    struct uio    auio;
  1604. X    struct iovec    iov;
  1605. X    char    buf[ MLEN ];
  1606. X    extern long    sosend(), soreceive();
  1607. X    func        ioroutine = (input ? soreceive : sosend);
  1608. X
  1609. X    debug11("flush %d %s bytes\n", len, input ? "input" : "output");
  1610. X    auio.uio_segflg = 1;    /* kernel bcopy */
  1611. X    while (len > 0 && ! error) {
  1612. X        need = iov.iov_len = auio.uio_resid = MIN(len, MLEN);
  1613. X        auio.uio_iov = &iov;
  1614. X        auio.uio_iovcnt = 1;
  1615. X        iov.iov_base = (caddr_t)buf;
  1616. X        debug11("flush: resid=%d... cc=%d\n",
  1617. X            auio.uio_resid, so->so_rcv.sb_cc);
  1618. X        error = rmt_uio(rp, &auio, ioroutine);
  1619. X        len -= need - auio.uio_resid;
  1620. X    }
  1621. X    if (error)
  1622. X        rp->r_close = TRUE;
  1623. X    if (input) {
  1624. X        rp->r_recver = -1;
  1625. X        rp->r_received = FALSE;
  1626. X        wakeup((caddr_t)&rp->r_recver);
  1627. X    }
  1628. X    else {
  1629. X        rp->r_sender = -1;
  1630. X        ioroutine = sosend;
  1631. X        wakeup((caddr_t)&rp->r_sender);
  1632. X    }
  1633. X    debug11("flush: error=%d\n", error);
  1634. X}
  1635. X
  1636. Xrmt_shutdown(system)
  1637. X    register int    system;
  1638. X{
  1639. X    register struct remoteinfo *rp = remote_info + system;
  1640. X    register struct proc    *p;
  1641. X
  1642. X    wakeup((caddr_t)&rp->r_sender);
  1643. X    wakeup((caddr_t)&rp->r_recver);
  1644. X    if (rp->r_recver >= 0 && (p = pfind(rp->r_recver)) && p->p_wchan) {
  1645. X        debug12("wake rder %d\n", p->p_pid);
  1646. X        wakeup((caddr_t)p->p_wchan);
  1647. X    }
  1648. X    if (rp->r_sender >= 0 && (p = pfind(rp->r_sender)) && p->p_wchan) {
  1649. X        debug12("wake wrter %d\n", p->p_pid);
  1650. X        wakeup((caddr_t)p->p_wchan);
  1651. X    }
  1652. X    debug12("shtdwn: ref=%d, reason=", rp->r_refcnt);
  1653. X    if (rp->r_close || (rp->r_sock->so_state & SS_CANTRCVMORE))
  1654. X        debug12("%s\n",
  1655. X            (rp->r_sock->so_state & SS_CANTRCVMORE)
  1656. X            ? "no more" : "closed");
  1657. X    else {
  1658. X        debug12("?, not done\n");
  1659. X        return(EBUSY);
  1660. X    }
  1661. X    rp->r_close = TRUE;
  1662. X    if (rp->r_refcnt || rp->r_users)
  1663. X        return(EBUSY);
  1664. X    rmt_closehost(rp);
  1665. X    return(0);
  1666. X}
  1667. X
  1668. X/*
  1669. X * Close a host connection.
  1670. X */
  1671. Xrmt_closehost(rp)
  1672. X    register struct remoteinfo    *rp;
  1673. X{
  1674. X    struct socket    *so;
  1675. X
  1676. X    so = rp->r_sock;
  1677. X    rp->r_recver = rp->r_sender = -1;
  1678. X    rp->r_sock = NULL;
  1679. X    rp->r_age = time.tv_sec;
  1680. X    rp->r_close = 0;
  1681. X    if (so)
  1682. X        soclose(so);
  1683. X    else
  1684. X        debug12("rmt_closehost: so == 0, rp=%x\n", rp);
  1685. X}
  1686. X
  1687. Xsendrsig(system)
  1688. X    register int    system;
  1689. X{
  1690. X    debug11("would have sent sig to system %d\n", system);
  1691. X}
  1692. SHAREOF
  1693. chmod 444 remote/usr.sys.remote/rmt_io.c
  1694. #
  1695. # remote/usr.sys.remote/rmt_subr.c
  1696. #
  1697. if [ -f remote/usr.sys.remote/rmt_subr.c ]; then 
  1698.     echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_subr.c or ^C to quit' 
  1699.     read ans 
  1700.     rm -f remote/usr.sys.remote/rmt_subr.c 
  1701. fi 
  1702.  
  1703. sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_subr.c
  1704. X/*
  1705. X * Copyright 1985, Todd Brunhoff.
  1706. X *
  1707. X * This software was written at Tektronix Computer Research Laboratories
  1708. X * as partial fulfillment of a Master's degree at the University of Denver.
  1709. X * This is not Tektronix proprietary software and should not be
  1710. X * confused with any software product sold by Tektronix.  No warranty is
  1711. X * expressed or implied on the reliability of this software; the author,
  1712. X * the University of Denver, and Tektronix, inc. accept no liability for
  1713. X * any damage done directly or indirectly by this software.  This software
  1714. X * may be copied, modified or used in any way, without fee, provided this
  1715. X * notice remains an unaltered part of the software.
  1716. X *
  1717. X * $Header: rmt_subr.c,v 2.0 85/12/07 18:19:10 toddb Rel $
  1718. X *
  1719. X * $Log:    rmt_subr.c,v $
  1720. X * Revision 2.0  85/12/07  18:19:10  toddb
  1721. X * First public release.
  1722. X * 
  1723. X */
  1724. X#include    "../h/param.h"
  1725. X#ifndef pyr    /* Pyramid */
  1726. X#include    "../machine/pte.h"
  1727. X#endif
  1728. X#include    "../h/systm.h"
  1729. X#include    "../h/map.h"
  1730. X#include    "../h/dir.h"
  1731. X#include    "../h/user.h"
  1732. X#include    "../h/proc.h"
  1733. X#ifdef BSD4_3
  1734. X#include    "../h/namei.h"
  1735. X#else BSD4_3
  1736. X#include    "../h/nami.h"
  1737. X#endif BSD4_3
  1738. X#include    "../h/inode.h"
  1739. X#include    "../h/mbuf.h"
  1740. X#include    "../h/socket.h"
  1741. X#include    "../remote/remotefs.h"
  1742. X#include    "../h/errno.h"
  1743. X#include    "../netinet/in.h"
  1744. X#include    "../h/file.h"
  1745. X
  1746. Xextern struct remoteinfo remote_info[];
  1747. Xextern struct remoteinfo *remote_generic;
  1748. Xextern struct nameserver    remote_ns;
  1749. X
  1750. X/*
  1751. X * A fast routine for determining whether an inode is in the list of
  1752. X * remote hosts, and returning a pointer into that list.
  1753. X * Failure returns NULL.
  1754. X */
  1755. Xstruct remoteinfo *rmt_host(ip, asysnum)
  1756. X    register struct inode    *ip;
  1757. X    register long        *asysnum;
  1758. X{
  1759. X    register struct remoteinfo    *rp = remote_info;
  1760. X    register long            i;
  1761. X    
  1762. X    if (ip == NULL)
  1763. X        printf("rmt_host: ip=0\n");
  1764. X    else for(i=0; i < R_MAXSYS; i++, rp++)
  1765. X        if (rp->r_mntpt == ip) {
  1766. X            *asysnum = i;
  1767. X            return(rp);
  1768. X        }
  1769. X    return(NULL);
  1770. X}
  1771. X
  1772. X/*
  1773. X * This is an extension to rmt_host() in that if rmt_host() returns a
  1774. X * pointer to a generic mount point, we return the pointer to the entry
  1775. X * that describes where we have our current working directory.
  1776. X */
  1777. Xstruct remoteinfo *rmt_hostdir(ip, asysnum)
  1778. X    register struct inode    *ip;
  1779. X    register long        *asysnum;
  1780. X{
  1781. X    register struct remoteinfo *rp;
  1782. X
  1783. X    rp = rmt_host(ip, asysnum);
  1784. X    if (rp == NULL)
  1785. X        return(NULL);
  1786. X    if (rp->r_name == NULL)
  1787. X        if (u.u_rmtcdir < 0)
  1788. X            return(rp);
  1789. X        else
  1790. X            return(remote_info + (*asysnum = u.u_rmtcdir));
  1791. X    return(rp);
  1792. X}
  1793. X
  1794. X/*
  1795. X * called by isremote() to figure out if there is a host implied by
  1796. X * 'path'.  Note that a user process must have ``registered'' with
  1797. X * the kernel as being willing to provide name service.
  1798. X */
  1799. Xstruct remoteinfo *rmt_findhost(apath, asysnum)
  1800. X    char    **apath;
  1801. X    register long    *asysnum;
  1802. X{
  1803. X    label_t                qsave;
  1804. X    register struct remoteinfo    *rp;
  1805. X    char                savec;
  1806. X    struct remoteinfo        *rmt_findaddr(),
  1807. X                    *rmt_findslot();
  1808. X    register struct proc        *p;
  1809. X    register char            *path = *apath, *cp;
  1810. X    register struct mbuf        *m = NULL;
  1811. X    register long            error = 0,
  1812. X                    i;
  1813. X
  1814. X    /*
  1815. X     * If the path is relative, then it must be because we have done
  1816. X     * a remote chdir()... take the directory from there.
  1817. X     */
  1818. X    if (*path != '/' && u.u_rmtcdir >= 0) {
  1819. X        debug13("path %s==>cwd=#%d\n", path, u.u_rmtcdir);
  1820. X        *asysnum = u.u_rmtcdir;
  1821. X        return (remote_info + u.u_rmtcdir);
  1822. X    }
  1823. X
  1824. X    /*
  1825. X     * First try to satisfy the name from the existing table... there
  1826. X     * may have been a mount done explicitly that has the form
  1827. X     * "/hostname", or there may have been an implicit mount.  Check
  1828. X     * for both.
  1829. X     */
  1830. X    rp = remote_info;
  1831. X    for(i=0; i < R_MAXSYS; i++, rp++)
  1832. X        if (rp->r_name && rmt_pathimplies(rp, apath)) {
  1833. X            debug13("%s==>mntpt=%s(#%d)\n",
  1834. X                *apath, rp->r_mntpath, i);
  1835. X            *asysnum = i;
  1836. X            return(rp);
  1837. X        }
  1838. X
  1839. X    /*
  1840. X     * If that fails, then give the name server a crack at it.  Note that
  1841. X     * we don't check to see if we found an open slot, because the address
  1842. X     * that we get back may match an existing address.
  1843. X     * If the nameserver is around, send him a signal.  Then wait
  1844. X     * patiently for the response.
  1845. X     */
  1846. X    while (remote_ns.rn_path) /* Lock out all other nameserver action */
  1847. X        sleep((caddr_t)&remote_ns.rn_path, PZERO+1);
  1848. X
  1849. X    bcopy(&u.u_qsave, &qsave, sizeof(label_t));
  1850. X    if (setjmp(&u.u_qsave)) {
  1851. X        error = EINTR;
  1852. X        goto out;
  1853. X    }
  1854. X
  1855. X    /*
  1856. X     * The nameserver only needs the first component.
  1857. X     */
  1858. X    cp = path;
  1859. X    while (*cp == '/')
  1860. X        cp++;
  1861. X    while (*cp && *cp != '/')
  1862. X        cp++;
  1863. X    savec = *cp;
  1864. X    *cp = '\0';
  1865. X    remote_ns.rn_pathlen = cp - path + 1;
  1866. X    remote_ns.rn_path = path;
  1867. X    p = remote_ns.rn_proc;
  1868. X    if (server_alive(p)) {
  1869. X        psignal(p, SIGURG);
  1870. X        sleep((caddr_t)&remote_ns.rn_name, PZERO+1);
  1871. X    }
  1872. X    *cp = savec;
  1873. X
  1874. X    /*
  1875. X     * Ok, now see what the server had to say...
  1876. X     */
  1877. X    m = remote_ns.rn_name;
  1878. X    remote_ns.rn_name = NULL;
  1879. X    if (m == NULL)
  1880. X        error = EADDRNOTAVAIL;
  1881. X    else {
  1882. X        rp = rmt_findaddr(m, asysnum);
  1883. X        *apath = cp;
  1884. X    }
  1885. X    if (rp || m == NULL)
  1886. X        goto out;
  1887. X
  1888. X    if ((rp = rmt_findslot(asysnum)) == NULL)
  1889. X        error = ETOOMANYREMOTE;
  1890. X    else {
  1891. X        if (rp->r_name) {
  1892. X            debug13("findhost: reusing %d, %s\n",
  1893. X                asysnum, rp->r_mntpath);
  1894. X            (void) m_free(rp->r_name);
  1895. X        }
  1896. X        rp->r_name = m;
  1897. X        bcopy (mtod(m, caddr_t) + m->m_len, rp->r_mntpath,
  1898. X            MIN(R_MNTPATHLEN, MLEN - m->m_len));
  1899. X        m = NULL;
  1900. X    }
  1901. X
  1902. Xout:
  1903. X    if (remote_ns.rn_name)
  1904. X        (void) m_free(remote_ns.rn_name);
  1905. X    else if (m)
  1906. X        (void) m_free(m);
  1907. X    remote_ns.rn_name = NULL;
  1908. X    remote_ns.rn_path = NULL;
  1909. X    wakeup((caddr_t)&remote_ns.rn_path);
  1910. X    if (error) {
  1911. X        rp = NULL;
  1912. X        u.u_error = error;
  1913. X    }
  1914. X
  1915. X    /*
  1916. X     * Since we are returning and may sleep again, we must restore the
  1917. X     * setjmp info so that we don't kill ourselves.
  1918. X     */
  1919. X    bcopy(&qsave, &u.u_qsave, sizeof(label_t));
  1920. X    return (rp);
  1921. X}
  1922. X
  1923. X/*
  1924. X * if (index >= 0) i.e. valid remote host
  1925. X *    Set the working directory to the mount point for system 'index'.
  1926. X *    This, along with what the server does, will effect a chdir("remotedir");
  1927. X * if (index < 0)
  1928. X *    then simply decrement the number of chdir's on the current remote
  1929. X *    host, if any.
  1930. X */
  1931. Xremotechdir(index)
  1932. X    long    index;
  1933. X{
  1934. X    register struct inode *ip = NULL, *oip;
  1935. X    register struct remoteinfo    *rp;
  1936. X    register long            error = 0;
  1937. X    long                i;
  1938. X    struct remoteinfo        *rmt_host();
  1939. X
  1940. X    debug14("cd #%d\n", index);
  1941. X    if (index >= R_MAXSYS)
  1942. X        return(ENOENT);
  1943. X    /*
  1944. X     * If we are currently cd'ed to another remote host, decrement its'
  1945. X     * reference count.
  1946. X     */
  1947. X    oip = u.u_cdir;
  1948. X    if (rp = rmt_hostdir(oip, &i)) {
  1949. X        debug14("uncd #%d, ip=%x\n", i, oip);
  1950. X        rp->r_nchdir--;
  1951. X    }
  1952. X    rp = remote_info + index;
  1953. X    if (index >= 0) {
  1954. X        /*
  1955. X         * If this is an implied mount point, find the inode for the
  1956. X         * generic mount pt.
  1957. X         */
  1958. X        if (rp->r_mntpt == NULL) {
  1959. X            if (remote_generic)
  1960. X                ip = remote_generic->r_mntpt; 
  1961. X            debug14("cd is generic, ip=%x\n", ip);
  1962. X            if (ip == NULL)
  1963. X                return(ENOENT);
  1964. X        }
  1965. X        else
  1966. X            ip = rp->r_mntpt;
  1967. X        rp->r_nchdir++;        /* bump the reference count */
  1968. X        u.u_rmtcdir = index;
  1969. X        irele(oip);
  1970. X        ip->i_count++;
  1971. X        u.u_cdir = ip;
  1972. X    }
  1973. X
  1974. X    return(error);
  1975. X}
  1976. X
  1977. X/*
  1978. X * See if a host is implied in a remote_info entry from the path name 'path'.
  1979. X */
  1980. Xrmt_pathimplies(rp, path)
  1981. X    register struct remoteinfo    *rp;
  1982. X    register char            **path;
  1983. X{
  1984. X    register char    *p1, *p2, *pend;
  1985. X
  1986. X    p1 = rp->r_mntpath;
  1987. X    while(*p1 == '/')
  1988. X        p1++;
  1989. X    p2 = *path;
  1990. X    while(*p2 == '/')
  1991. X        p2++;
  1992. X
  1993. X    /*
  1994. X     * Compare against the mount point.
  1995. X     */
  1996. X    pend = rp->r_mntpath + R_MNTPATHLEN;
  1997. X    while (*p1 == *p2 && *p1 && p1 < pend)
  1998. X        p1++, p2++;
  1999. X    if (*p1 == *p2 || (*p1 == '\0' && *p2 == '/')) {
  2000. X        *path = p2;
  2001. X        return(TRUE);
  2002. X    }
  2003. X
  2004. X    return (FALSE);
  2005. X}
  2006. X
  2007. X/*
  2008. X * See if any remote entry already had address 'addr'.
  2009. X */
  2010. Xstruct remoteinfo *rmt_findaddr(m, asysnum)
  2011. X    register struct mbuf    *m;
  2012. X    register long        *asysnum;
  2013. X{
  2014. X    register struct remoteinfo    *rp;
  2015. X    register caddr_t        addr;
  2016. X    register int            i, len;
  2017. X
  2018. X    addr = mtod(m, caddr_t);
  2019. X    len = m->m_len;
  2020. X    for (i=0, rp = remote_info; i < R_MAXSYS; i++, rp++)
  2021. X        if (rp->r_name
  2022. X        && len == rp->r_name->m_len
  2023. X        && bcmp(rp->r_name, addr, len) == 0) {
  2024. X            *asysnum = i;
  2025. X            debug13("%s: same as mnt %d\n", addr+len, i);
  2026. X            return(rp);
  2027. X        }
  2028. X    return(NULL);
  2029. X}
  2030. X
  2031. X/*
  2032. X * Find an open slot in the remote info.
  2033. X */
  2034. Xstruct remoteinfo *rmt_findslot(asysnum)
  2035. X    register long    *asysnum;
  2036. X{
  2037. X    register struct remoteinfo    *rp,
  2038. X                    *frp = NULL;
  2039. X    register int            i, fi;
  2040. X
  2041. X    for (i=0, rp = remote_info; i < R_MAXSYS; i++, rp++) {
  2042. X        if (rp->r_mntpt || rp ->r_sock) /* active connections */
  2043. X            continue;
  2044. X        if (rp->r_name == NULL) {
  2045. X            frp = rp;
  2046. X            fi = i;
  2047. X            break;
  2048. X        }
  2049. X        if (frp == NULL || rp->r_age < frp->r_age) {
  2050. X            frp = rp;
  2051. X            fi = i;
  2052. X        }
  2053. X    }
  2054. X    if (frp) {
  2055. X        debug13("slt: %d\n", fi);
  2056. X        *asysnum = fi;
  2057. X        return(frp);
  2058. X    }
  2059. X
  2060. X    /*
  2061. X     * No slot... do garbage collection.
  2062. X     */
  2063. X    for (i=0, rp = remote_info; i < R_MAXSYS; i++, rp++)
  2064. X        if (rp->r_mntpt == NULL
  2065. X         && rp->r_nchdir == 0 && rp->r_nfile == 0) {
  2066. X            debug13("fndslt: usurp %d=%s\n",
  2067. X                rp - remote_info, rp->r_mntpath);
  2068. X            *asysnum = i;
  2069. X            rmt_closehost(rp);
  2070. X            (void) m_free(rp->r_name);
  2071. X            rp->r_name = NULL;
  2072. X            return(rp);
  2073. X        }
  2074. X
  2075. X    return(NULL);
  2076. X}
  2077. SHAREOF
  2078. chmod 444 remote/usr.sys.remote/rmt_subr.c
  2079. #
  2080. # remote/usr.sys.remote/rmt_syscall1.c
  2081. #
  2082. if [ -f remote/usr.sys.remote/rmt_syscall1.c ]; then 
  2083.     echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_syscall1.c or ^C to quit' 
  2084.     read ans 
  2085.     rm -f remote/usr.sys.remote/rmt_syscall1.c 
  2086. fi 
  2087.  
  2088. sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_syscall1.c
  2089. X/*
  2090. X * Copyright 1985, Todd Brunhoff.
  2091. X *
  2092. X * This software was written at Tektronix Computer Research Laboratories
  2093. X * as partial fulfillment of a Master's degree at the University of Denver.
  2094. X * This is not Tektronix proprietary software and should not be
  2095. X * confused with any software product sold by Tektronix.  No warranty is
  2096. X * expressed or implied on the reliability of this software; the author,
  2097. X * the University of Denver, and Tektronix, inc. accept no liability for
  2098. X * any damage done directly or indirectly by this software.  This software
  2099. X * may be copied, modified or used in any way, without fee, provided this
  2100. X * notice remains an unaltered part of the software.
  2101. X *
  2102. X * $Header: rmt_syscall1.c,v 2.0 85/12/07 18:19:21 toddb Rel $
  2103. X *
  2104. X * $Log:    rmt_syscall1.c,v $
  2105. X * Revision 2.0  85/12/07  18:19:21  toddb
  2106. X * First public release.
  2107. X * 
  2108. X */
  2109. X#include    "../h/param.h"
  2110. X#ifndef pyr    /* Pyramid */
  2111. X#include    "../machine/pte.h"
  2112. X#endif
  2113. X#include    "../h/systm.h"
  2114. X#include    "../h/map.h"
  2115. X#include    "../h/dir.h"
  2116. X#include    "../h/user.h"
  2117. X#include    "../h/kernel.h"
  2118. X#include    "../h/proc.h"
  2119. X#include    "../h/mbuf.h"
  2120. X#include    "../h/socket.h"
  2121. X#include    "../h/file.h"
  2122. X#include    "../remote/remotefs.h"
  2123. X#include    "../h/stat.h"
  2124. X#include    "../h/errno.h"
  2125. X#include    "../netinet/in.h"
  2126. X
  2127. Xextern struct remoteinfo    remote_info[];
  2128. X
  2129. X/*
  2130. X * Remote access()
  2131. X */
  2132. Xrmt_access (sysindex, m)
  2133. X    int    sysindex;
  2134. X    struct mbuf    *m;
  2135. X{
  2136. X    struct message    *msg = mtod(m, struct message *);
  2137. X    struct a {
  2138. X        char    *path;
  2139. X        long    mode;
  2140. X    } *uap = (struct a *)u.u_ap;
  2141. X
  2142. X    msg->m_args[ 0 ] = htonl(uap->mode);
  2143. X    
  2144. X    /*
  2145. X     * Now send it.
  2146. X     */
  2147. X    return( rmt_msgfin(sysindex, m, 0) );
  2148. X}
  2149. X
  2150. X/*
  2151. X * Remote chdir()
  2152. X */
  2153. Xrmt_chdir (sysindex, m)
  2154. X    int    sysindex;
  2155. X    struct mbuf    *m;
  2156. X{
  2157. X    int    error;
  2158. X
  2159. X    /*
  2160. X     * Now send it.
  2161. X     */
  2162. X    if ((error = rmt_msgfin(sysindex, m, 0)) == 0)
  2163. X        error = remotechdir(sysindex);
  2164. X
  2165. X    return( error );
  2166. X}
  2167. X
  2168. X/*
  2169. X * Remote chmod() and fchmod()
  2170. X */
  2171. Xrmt_chmod (sysindex, m)
  2172. X    int    sysindex;
  2173. X    struct mbuf    *m;
  2174. X{
  2175. X    int    i = 0;
  2176. X    struct message *msg = mtod(m, struct message *);
  2177. X    struct a {
  2178. X        long    path_or_fd;
  2179. X        long    mode;
  2180. X    } *uap = (struct a *)u.u_ap;
  2181. X
  2182. X    if (htons(msg->m_syscall) == RSYS_fchmod)
  2183. X        i++;
  2184. X    msg->m_args[ i ] = htonl(uap->mode);
  2185. X    /*
  2186. X     * Now send it.
  2187. X     */
  2188. X    return( rmt_msgfin(sysindex, m, 0) );
  2189. X}
  2190. X
  2191. X/*
  2192. X * Remote chown() and fchown()
  2193. X */
  2194. Xrmt_chown (sysindex, m)
  2195. X    int    sysindex;
  2196. X    struct mbuf    *m;
  2197. X{
  2198. X    int    i = 0;
  2199. X    struct message *msg = mtod(m, struct message *);
  2200. X    struct a {
  2201. X        long    path_or_fd;
  2202. X        long    owner, group;
  2203. X    } *uap = (struct a *)u.u_ap;
  2204. X
  2205. X    if (htons(msg->m_syscall) == RSYS_fchown)
  2206. X        i++, m->m_len = R_MINRMSG + 3*sizeof(long);
  2207. X    msg->m_args[ i++ ] = htonl(uap->owner);
  2208. X    msg->m_args[ i ] = htonl(uap->group);
  2209. X    /*
  2210. X     * Now send it.
  2211. X     */
  2212. X    return( rmt_msgfin(sysindex, m, 0) );
  2213. X}
  2214. X
  2215. X/*
  2216. X * Remote dup()
  2217. X */
  2218. Xrmt_dup (sysindex, m)
  2219. X    long    sysindex;
  2220. X    struct mbuf    *m;
  2221. X{
  2222. X    int    fd, error;
  2223. X    struct message *msg = mtod(m, struct message *);
  2224. X    struct file    *fp;
  2225. X    struct a {
  2226. X        long    fd;
  2227. X    } *uap = (struct a *)u.u_ap;
  2228. X
  2229. X    fp = u.u_ofile[ uap->fd ];
  2230. X    fd = ufalloc(0);
  2231. X    if (fd < 0)
  2232. X        return(-1);
  2233. X    remote_info[ (int)fp->f_data ].r_nfile++;
  2234. X    dupit(fd, fp, u.u_pofile[uap->fd]);
  2235. X    msg->m_args[ 1 ] = htonl(fd);
  2236. X
  2237. X    /*
  2238. X     * Now send it.
  2239. X     */
  2240. X    error = rmt_msgfin(sysindex, m, 0);
  2241. X    if (error)
  2242. X        rmt_deallocfd(fd);
  2243. X    return(error);
  2244. X}
  2245. X
  2246. X/*
  2247. X * Remote dup2()
  2248. X */
  2249. Xrmt_dup2 (sysindex, m)
  2250. X    long    sysindex;
  2251. X    struct mbuf    *m;
  2252. X{
  2253. X    struct message *msg = mtod(m, struct message *);
  2254. X    struct file    *oldfp, *newfp;
  2255. X    struct a {
  2256. X        long    oldfd,
  2257. X            newfd;
  2258. X    } *uap = (struct a *)u.u_ap;
  2259. X    long    oldfd = uap->oldfd,
  2260. X        newfd = uap->newfd,
  2261. X        error;
  2262. X
  2263. X    oldfp = u.u_ofile[ oldfd ];
  2264. X    if (newfd >= NOFILE)
  2265. X        return(EBADF);
  2266. X    if (oldfd == newfd)
  2267. X        return(newfd);
  2268. X    if (newfp = u.u_ofile[ newfd ]) {
  2269. X        /*
  2270. X         * If the new file descriptor (which must be closed) is
  2271. X         * remote on system 'n', then we may have to send a close
  2272. X         * message to system 'n', but only if
  2273. X         *    1. the file descriptor being duped is non-remote
  2274. X         *        or
  2275. X         *    2. the file descriptor being duped is on a different
  2276. X         *       remote system.
  2277. X         * Note that case number 1 implies that there is no more
  2278. X         * remote work to be done.
  2279. X         */
  2280. X        if (newfp->f_flag & FREMOTE) {
  2281. X            if ((oldfp->f_flag & FREMOTE) == 0
  2282. X             || newfp->f_data != oldfp->f_data) {
  2283. X                if ((oldfp->f_flag & FREMOTE) == 0)
  2284. X                    sysindex = -1;
  2285. X                uap->oldfd = uap->newfd;
  2286. X                remote_fd(RSYS_close);
  2287. X            }
  2288. X            else
  2289. X                closef(newfp);
  2290. X        }
  2291. X        else
  2292. X            closef(newfp);
  2293. X    }
  2294. X    dupit(newfd, oldfp, u.u_pofile[ oldfd ]);
  2295. X
  2296. X    /*
  2297. X     * We may already be done.
  2298. X     */
  2299. X    if (sysindex < 0)
  2300. X        return(0);
  2301. X    
  2302. X    /*
  2303. X     * Now send it.
  2304. X     */
  2305. X    remote_info[ sysindex ].r_nfile++;
  2306. X    msg->m_args[ 1 ] = htonl(newfd);
  2307. X    error = rmt_msgfin(sysindex, m, 0);
  2308. X    if (error)
  2309. X        rmt_deallocfd(newfd);
  2310. X
  2311. X    return(error);
  2312. X}
  2313. X
  2314. X/*
  2315. X * routine for handling an error.  We should never get here... but if we
  2316. X * do.....
  2317. X */
  2318. Xrmt_error(sysnum)
  2319. X    int    sysnum;
  2320. X{
  2321. X    debug1("error reached\n");
  2322. X    return(EINVAL);
  2323. X}
  2324. SHAREOF
  2325. chmod 444 remote/usr.sys.remote/rmt_syscall1.c
  2326. #
  2327. # remote/usr.sys.remote/rmt_syscall2.c
  2328. #
  2329. if [ -f remote/usr.sys.remote/rmt_syscall2.c ]; then 
  2330.     echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_syscall2.c or ^C to quit' 
  2331.     read ans 
  2332.     rm -f remote/usr.sys.remote/rmt_syscall2.c 
  2333. fi 
  2334.  
  2335. sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_syscall2.c
  2336. X/*
  2337. X * Copyright 1985, Todd Brunhoff.
  2338. X *
  2339. X * This software was written at Tektronix Computer Research Laboratories
  2340. X * as partial fulfillment of a Master's degree at the University of Denver.
  2341. X * This is not Tektronix proprietary software and should not be
  2342. X * confused with any software product sold by Tektronix.  No warranty is
  2343. X * expressed or implied on the reliability of this software; the author,
  2344. X * the University of Denver, and Tektronix, inc. accept no liability for
  2345. X * any damage done directly or indirectly by this software.  This software
  2346. X * may be copied, modified or used in any way, without fee, provided this
  2347. X * notice remains an unaltered part of the software.
  2348. X *
  2349. X * $Header: rmt_syscall2.c,v 2.0 85/12/07 18:19:28 toddb Rel $
  2350. X *
  2351. X * $Log:    rmt_syscall2.c,v $
  2352. X * Revision 2.0  85/12/07  18:19:28  toddb
  2353. X * First public release.
  2354. X * 
  2355. X */
  2356. X#include    "../h/param.h"
  2357. X#ifndef pyr    /* Pyramid */
  2358. X#include    "../machine/pte.h"
  2359. X#endif
  2360. X#include    "../h/systm.h"
  2361. X#include    "../h/map.h"
  2362. X#include    "../h/dir.h"
  2363. X#include    "../h/user.h"
  2364. X#include    "../h/kernel.h"
  2365. X#include    "../h/proc.h"
  2366. X#include    "../h/mbuf.h"
  2367. X#include    "../h/socket.h"
  2368. X#include    "../remote/remotefs.h"
  2369. X#include    "../h/file.h"
  2370. X#include    "../h/stat.h"
  2371. X#include    "../h/errno.h"
  2372. X#include    "../netinet/in.h"
  2373. X#include    "../h/uio.h"
  2374. X
  2375. Xextern struct remoteinfo    remote_info[];
  2376. Xextern syscalls            remote_syscall[];
  2377. X
  2378. X/*
  2379. X * Remote fcntl()
  2380. X */
  2381. X
  2382. Xrmt_fcntl (sysindex, m)
  2383. X    int    sysindex;
  2384. X    struct mbuf    *m;
  2385. X{
  2386. X    register long        fd,
  2387. X                error;
  2388. X    register struct message *msg = mtod(m, struct message *);
  2389. X    register struct a {
  2390. X        long    fd,
  2391. X            command,
  2392. X            arg;
  2393. X    } *uap = (struct a *)u.u_ap;
  2394. X    register struct file    *fp;
  2395. X
  2396. X    if (uap->command == F_DUPFD) {
  2397. X        fp = u.u_ofile[ uap->fd ];
  2398. X        fd = ufalloc(uap->arg);
  2399. X        if (fd < 0)
  2400. X            return(-1);
  2401. X        remote_info[ (int)fp->f_data ].r_nfile++;
  2402. X        dupit(fd, fp, u.u_pofile[uap->fd]);
  2403. X        msg->m_args[ 1 ] = htonl(fd);
  2404. X        msg->m_syscall = htons(RSYS_dup);
  2405. X    }
  2406. X    else {
  2407. X        msg->m_args[ 1 ] = htonl(uap->command);
  2408. X        msg->m_args[ 2 ] = htonl(uap->arg);
  2409. X        m->m_len += sizeof(long);
  2410. X    }
  2411. X
  2412. X    /*
  2413. X     * Now send it
  2414. X     */
  2415. X    error = rmt_msgfin(sysindex, m, 0);
  2416. X    if (error && uap->command == F_DUPFD)
  2417. X        rmt_deallocfd(fd);
  2418. X
  2419. X    return(error);
  2420. X}
  2421. X
  2422. X/*
  2423. X * Remote flock()
  2424. X */
  2425. Xrmt_flock (sysindex, m)
  2426. X    int    sysindex;
  2427. X    struct mbuf    *m;
  2428. X{
  2429. X    struct message *msg = mtod(m, struct message *);
  2430. X    struct a {
  2431. X        long    fd;
  2432. X        long    operation;
  2433. X    } *uap = (struct a *)u.u_ap;
  2434. X
  2435. X    msg->m_args[ 1 ] = htonl(uap->operation);
  2436. X    /*
  2437. X     * Now send it.
  2438. X     */
  2439. X    return( rmt_msgfin(sysindex, m, 0) );
  2440. X}
  2441. X
  2442. X/*
  2443. X * Remote ioctl()
  2444. X */
  2445. X
  2446. Xrmt_ioctl (sysindex, m, request, argp)
  2447. X    int    sysindex,
  2448. X        request;
  2449. X    struct mbuf    *m;
  2450. X    char    *argp;
  2451. X{
  2452. X
  2453. X    /*
  2454. X     * for now always fail.
  2455. X     */
  2456. X    return(EINVAL);
  2457. X}
  2458. X
  2459. X/*
  2460. X * Remote lseek()
  2461. X */
  2462. Xrmt_lseek (sysindex, m)
  2463. X    long    sysindex;
  2464. X    struct mbuf    *m;
  2465. X{
  2466. X    struct message    *msg = mtod(m, struct message *);
  2467. X    struct a {
  2468. X        long    fd,
  2469. X            offset,
  2470. X            whence;
  2471. X    } *uap = (struct a *)u.u_ap;
  2472. X    register long    flags = RFLG_INFO;
  2473. X    register long    twhence = uap->whence;
  2474. X    register long    error;
  2475. X    register struct file    *fp = u.u_ofile[ uap->fd ];
  2476. X
  2477. X    /*
  2478. X     * As a special case for the sake of speed, L_INCR and L_SET can be
  2479. X     * done locally and then the message can be sent as
  2480. X     * info only (no reply).
  2481. X     */
  2482. X    switch (twhence) {
  2483. X    case L_INCR:
  2484. X        /*
  2485. X         * Very special case: lseek(fd, 0, L_INCR) is a noop.
  2486. X         */
  2487. X        if (uap->offset == 0) {
  2488. X            m_free(m);
  2489. X            u.u_r.r_off = fp->f_offset;
  2490. X            return(0);
  2491. X        }
  2492. X        fp->f_offset += uap->offset;
  2493. X        break;
  2494. X    case L_XTND:
  2495. X        flags = 0;
  2496. X        break;
  2497. X    case L_SET:
  2498. X        fp->f_offset = uap->offset;
  2499. X        break;
  2500. X    default:
  2501. X        m_free(m);
  2502. X        u.u_error = EINVAL;
  2503. X        return(0);
  2504. X    }
  2505. X    msg->m_args[ 1 ] = htonl(uap->offset);
  2506. X    msg->m_args[ 2 ] = htonl(twhence);
  2507. X    m->m_len += sizeof(long);
  2508. X    if (flags == RFLG_INFO)
  2509. X        msg->m_syscall = htons(RSYS_qlseek);
  2510. X
  2511. X    /*
  2512. X     * Now send it.
  2513. X     */
  2514. X    error = rmt_msgfin(sysindex, m, flags);
  2515. X    if (flags != RFLG_INFO)
  2516. X        fp->f_offset = u.u_r.r_val1;
  2517. X    else
  2518. X        u.u_r.r_off = fp->f_offset;
  2519. X    return( error );
  2520. X}
  2521. X
  2522. X/*
  2523. X * Remote mknod()
  2524. X */
  2525. Xrmt_mknod (sysindex, m, mode, dev)
  2526. X    long    sysindex,
  2527. X        mode, dev;
  2528. X    struct mbuf    *m;
  2529. X{
  2530. X    struct message    *msg = mtod(m, struct message *);
  2531. X    struct a {
  2532. X        char    *path;
  2533. X        long    mode,
  2534. X            dev;
  2535. X    } *uap = (struct a *)u.u_ap;
  2536. X
  2537. X    msg->m_args[ 0 ] = htonl(uap->mode);
  2538. X    msg->m_args[ 1 ] = htonl(uap->dev);
  2539. X    msg->m_args[ 2 ] = htonl(u.u_cmask);
  2540. X
  2541. X    /*
  2542. X     * Now send it.
  2543. X     */
  2544. X    return( rmt_msgfin(sysindex, m, 0) );
  2545. X}
  2546. X
  2547. Xrmt_noop() {    return;    }
  2548. X
  2549. X/*
  2550. X * Remote mkdir() and rmdir() and unlink() and fsync() and close()
  2551. X */
  2552. Xrmt_onearg (sysindex, m)
  2553. X    int    sysindex;
  2554. X    struct mbuf    *m;
  2555. X{
  2556. X    struct message    *msg = mtod(m, struct message *);
  2557. X    short    syscall = ntohs(msg->m_syscall);
  2558. X    long    error;
  2559. X
  2560. X    if (syscall == RSYS_close) {
  2561. X        struct a {
  2562. X            long    fd;
  2563. X        } *uap = (struct a *)u.u_ap;
  2564. X        rmt_deallocfd(uap->fd);
  2565. X        m->m_len = R_MINRMSG + sizeof(long);
  2566. X    }
  2567. X    else if (syscall == RSYS_fsync)
  2568. X        m->m_len = R_MINRMSG + sizeof(long);
  2569. X    else
  2570. X        msg->m_args[ 0 ] = htonl(u.u_cmask);
  2571. X
  2572. X    error = rmt_msgfin(sysindex, m, remote_syscall[ syscall ].sys_flag);
  2573. X    return(error);
  2574. X}
  2575. SHAREOF
  2576. chmod 444 remote/usr.sys.remote/rmt_syscall2.c
  2577.  
  2578.