home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ENTERPRS / CPM / UTILS / S / UZI.ARK / SCALL2.C < prev    next >
Text File  |  1988-11-30  |  13KB  |  666 lines

  1. /**************************************************
  2. UZI (Unix Z80 Implementation) Kernel:  scall2.c
  3. ***************************************************/
  4.  
  5.  
  6. /*LINTLIBRARY*/
  7. #include "unix.h"
  8. #include "extern.h"
  9.  
  10.  
  11. /* Getpid() */
  12.  
  13. _getpid()
  14. {
  15.     return(udata.u_ptab->p_pid);
  16. }
  17.  
  18. /* Getppid() */
  19.  
  20. _getppid()
  21. {
  22.     return(udata.u_ptab->p_pptr->p_pid);
  23. }
  24.  
  25.  
  26. /* Getuid() */
  27.  
  28. _getuid()
  29. {
  30.     return(udata.u_ptab->p_uid);
  31. }
  32.  
  33.  
  34. _getgid()
  35. {
  36.     return(udata.u_gid);
  37. }
  38.  
  39.  
  40. /*********************************
  41. setuid(uid)
  42. int uid;
  43. ***********************************/
  44.  
  45. #define uid (int)udata.u_argn
  46.  
  47. _setuid()
  48. {
  49.     if (super() || udata.u_ptab->p_uid == uid)
  50.     {
  51.     udata.u_ptab->p_uid = uid;
  52.     udata.u_euid = uid;
  53.     return(0);
  54.     }
  55.     udata.u_error = EPERM;
  56.     return(-1);
  57. }
  58.  
  59. #undef uid
  60.  
  61.  
  62.  
  63. /*****************************************
  64. setgid(gid)
  65. int gid;
  66. ****************************************/
  67.  
  68. #define gid (int16)udata.u_argn
  69.  
  70. _setgid()
  71. {
  72.     if (super() || udata.u_gid == gid)
  73.     {
  74.     udata.u_gid = gid;
  75.     udata.u_egid = gid;
  76.     return(0);
  77.     }
  78.     udata.u_error = EPERM;
  79.     return(-1);
  80. }
  81.  
  82. #undef gid;
  83.  
  84.  
  85.  
  86. /***********************************
  87. time(tvec)
  88. int tvec[];
  89. **************************************/
  90.  
  91. #define tvec (int *)udata.u_argn
  92.  
  93. _time()
  94. {
  95.     rdtime(tvec);  /* In machdep.c */
  96.     return(0);
  97. }
  98.  
  99. #undef tvec
  100.  
  101.  
  102. /**************************************
  103. stime(tvec)
  104. int tvec[];
  105. **********************************/
  106.  
  107. #define tvec (int *)udata.u_argn
  108.  
  109. _stime()
  110. {
  111. /*
  112.     ifnot (super())
  113.     {
  114.     udata.u_error = EPERM;
  115.     return(-1);
  116.     }
  117.     sttime(tvec);
  118.     return(0);
  119. */
  120.  
  121.     udata.u_error = EPERM;
  122.     return(-1);
  123. }
  124.  
  125. #undef tvec
  126.  
  127.  
  128.  
  129. /********************************************
  130. times(buf)
  131. char *buf;
  132. **********************************************/
  133.  
  134. #define buf (char *)udata.u_argn
  135.  
  136. _times()
  137. {
  138.     ifnot (valadr(buf,6*sizeof(time_t)))
  139.     return(-1);
  140.  
  141.     di();
  142.     bcopy(&udata.u_utime, buf, 4*sizeof(time_t));
  143.     bcopy(&ticks, buf + 4*sizeof(time_t), sizeof(time_t));
  144.     ei();
  145.     return(0);
  146. }
  147.  
  148. #undef buf
  149.  
  150.  
  151.  
  152. /* User's execve() call. All other flavors are library routines. */
  153.  
  154. /*****************************************
  155. execve(name, argv, envp)
  156. char *name;
  157. char *argv[];
  158. char *envp[];
  159. *****************************************/
  160.  
  161. #define name (char *)udata.u_argn2
  162. #define argv (char **)udata.u_argn1
  163. #define envp (char **)udata.u_argn
  164.  
  165. _execve()
  166. {
  167.     register inoptr ino;
  168.     register char *buf;
  169.     inoptr n_open();
  170.     char *bread();
  171.     blkno_t bmap();
  172.  
  173.     ifnot (ino = n_open(name,NULLINOPTR))
  174.     return(-1);
  175.  
  176.     if (ino->c_node.i_size.o_blkno >= ((uint16)(&udata)/512))
  177.     {
  178.     udata.u_error = ENOMEM;
  179.     goto nogood;
  180.     }
  181.  
  182.     ifnot ( (getperm(ino) & OTH_EX) &&
  183.         (ino->c_node.i_mode & F_REG) &&
  184.         (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)) )
  185.     {
  186.     udata.u_error = EACCES;
  187.     goto nogood;
  188.     }
  189.  
  190.     setftime(ino, A_TIME);
  191.  
  192.     /* Gather the arguments, and put them on the root device */
  193.     /* Put environment on another block */
  194.     if (wargs(argv, 0) || wargs(envp, 1))
  195.     goto nogood;
  196.  
  197.     /* Read in the first block of the new program */
  198.     buf = bread( ino->c_dev, bmap(ino, 0, 1), 0);
  199.  
  200.     if ((*buf & 0xff) != EMAGIC)
  201.     {
  202.     udata.u_error = ENOEXEC;
  203.     goto nogood2;
  204.     }
  205.  
  206.     /* Here, check the setuid stuff. No other changes need be made in
  207.     the user data */
  208.     if (ino->c_node.i_mode & SET_UID)
  209.     udata.u_euid = ino->c_node.i_uid;
  210.  
  211.     if (ino->c_node.i_mode & SET_GID)
  212.     udata.u_egid = ino->c_node.i_gid;
  213.  
  214.     bcopy(buf,PROGBASE,512);
  215.     bfree(buf, 0);
  216.  
  217.     /* At this point, we are committed to reading in and executing
  218.     the program. We switch to a local stack, and pass to it
  219.     the necessary parameter: ino */
  220.  
  221.     udata.u_ino = ino;     /* Termorarily stash these here */
  222.  
  223.     tempstk();
  224.     exec2();   /* Never returns */
  225.  
  226. nogood2:
  227.     bfree(buf, 0);
  228. nogood:
  229.     i_deref(ino);
  230.     return(-1);
  231.  
  232. }
  233.  
  234. #undef name
  235. #undef argv
  236. #undef envp
  237.  
  238.  
  239. exec2()
  240. {
  241.     register blkno_t blk;
  242.     register char **argv;
  243.     register char **envp;
  244.     register int (**sp)();
  245.     int argc;
  246.     char *rargs();
  247.     register char *progptr;
  248.     char *buf;
  249.     blkno_t pblk;
  250.     blkno_t bmap();
  251.     char *bread();
  252.  
  253.     /* Read in the rest of the program */
  254.     progptr = PROGBASE+512;
  255.     for (blk = 1; blk <= udata.u_ino->c_node.i_size.o_blkno; ++blk)
  256.     {
  257.     pblk = bmap(udata.u_ino, blk, 1);
  258.     if (pblk != -1)
  259.     {
  260.         buf = bread( udata.u_ino->c_dev, pblk, 0);
  261.         bcopy(buf, progptr, 512);
  262.         bfree(buf, 0);
  263.     }
  264.     progptr += 512;
  265.     }
  266.     i_deref(udata.u_ino);
  267.  
  268.     /* Zero out the free memory */
  269.     bzero(progptr,(uint16)((char *)&udata - progptr));
  270.     udata.u_break = progptr;
  271.  
  272.  
  273.     /* Read back the arguments and the environment */
  274.     argv = (char **)rargs((char *)&udata, 0, &argc);
  275.     envp = (char **)rargs((char *)argv, 1, NULL);
  276.  
  277.     /* Fill in udata.u_name */
  278.     bcopy(*argv,udata.u_name,8);
  279.  
  280.     /* Turn off caught signals */
  281.     for (sp= udata.u_sigvec; sp < (udata.u_sigvec+NSIGS); ++sp)
  282.     if (*sp != SIG_IGN)
  283.         *sp = SIG_DFL;
  284.  
  285.     /* Shove argc and the address of argv just below envp */
  286.     *(envp - 1) = (char *)argc;
  287.     *(envp - 2) = (char *)argv;
  288.  
  289.     /* Go jump into the program, first setting the stack */
  290.     doexec((int16 *)(udata.u_isp = envp - 2));
  291.  
  292. }
  293.  
  294.  
  295. wargs(argv,blk)
  296. char **argv;
  297. int blk;
  298. {
  299.     register char *ptr;    /* Address of base of arg strings in user space */
  300.     register int n;
  301.     struct s_argblk *argbuf;
  302.     register char *bufp;
  303.     register int j;
  304.     char *zerobuf();
  305.     char *bread();
  306.  
  307.     /* Gather the arguments, and put them on the swap device */
  308.     argbuf = (struct s_argblk *)bread(SWAPDEV, udata.u_ptab->p_swap+blk, 2);
  309.     bufp = argbuf->a_buf;
  310.     for (j=0; argv[j] != NULL; ++j)
  311.     {
  312.     ptr = argv[j];
  313.     do
  314.     {
  315.         *bufp++ = *ptr;
  316.         if (bufp >= argbuf->a_buf+500)
  317.         {
  318.             udata.u_error = E2BIG;
  319.             bfree((char *)argbuf, 1);
  320.             return (1);
  321.         }
  322.     }
  323.     while (*ptr++ != '\0');
  324.     }
  325.  
  326.     argbuf->a_argc = j;  /* Store argc in argbuf. */
  327.     argbuf->a_arglen = bufp - argbuf->a_buf;  /*Store total string size. */
  328.  
  329.     /* Swap out the arguments into the given swap block */
  330.     bfree((char *)argbuf, 1);
  331.  
  332.     return (0);
  333. }
  334.  
  335.  
  336.  
  337. char *
  338. rargs(ptr,blk,cnt)
  339. register char *ptr;
  340. int blk;
  341. int *cnt;
  342. {
  343.     struct s_argblk *argbuf;
  344.     register char **argv;  /* Address of users argv[], just below ptr */
  345.     register int n;
  346.     char *bread();
  347.  
  348.     /* Read back the arguments */
  349.     argbuf = (struct s_argblk *)bread(SWAPDEV,udata.u_ptab->p_swap+blk, 0);
  350.  
  351.     /* Move them into the users address space, at the very top */
  352.     ptr -= argbuf->a_arglen;
  353.     if (argbuf->a_arglen)
  354.     bcopy(argbuf->a_buf, ptr, argbuf->a_arglen);
  355.  
  356.     /* Set argv to point below the argument strings */
  357.     argv = (char **)ptr - (argbuf->a_argc + 1);
  358.  
  359.     /* Set each element of argv[] to point to its argument string */
  360.     argv[0] = ptr;
  361.     for (n=1; n < argbuf->a_argc; ++n)
  362.     argv[n] = argv[n-1] + strlen(argv[n-1]) + 1;
  363.     argv[argbuf->a_argc] = NULL;
  364.  
  365.     if (cnt)
  366.     *cnt = argbuf->a_argc;
  367.  
  368.     bfree((char *)argbuf, 0);
  369.     return (argv);
  370. }
  371.  
  372.  
  373.  
  374. /**********************************
  375. brk(addr)
  376. char *addr;
  377. ************************************/
  378.  
  379. #define addr (char *)udata.u_argn
  380.  
  381. _brk()
  382. {
  383.     char dummy;   /* A thing to take address of */
  384.  
  385.     /* A hack to get approx val of stack ptr. */
  386.     if (addr < PROGBASE || (addr+64) >= (char *)&dummy)
  387.     {
  388.     udata.u_error = ENOMEM;
  389.     return(-1);
  390.     }
  391.     udata.u_break = addr;
  392.     return(0);
  393. }
  394.  
  395. #undef addr
  396.  
  397.  
  398.  
  399. /************************************
  400. sbrk(incr)
  401. uint16 incr;
  402. ***************************************/
  403.  
  404. #define incr (uint16)udata.u_argn
  405.  
  406. _sbrk()
  407. {
  408.     register char *oldbrk;
  409.  
  410.     udata.u_argn += (oldbrk = udata.u_break);
  411.     if (_brk())
  412.     return(-1);
  413.  
  414.     return((int)oldbrk);
  415. }
  416.  
  417. #undef incr
  418.  
  419.  
  420.  
  421. /**************************************
  422. wait(statloc)
  423. int *statloc;
  424. ****************************************/
  425.  
  426. #define statloc (int *)udata.u_argn
  427.  
  428. _wait()
  429. {
  430.     register ptptr p;
  431.     register int retval;
  432.  
  433.     if (statloc > (int *)(&udata))
  434.     {
  435.     udata.u_error = EFAULT;
  436.     return(-1);
  437.     }
  438.  
  439.     di();
  440.     /* See if we have any children. */
  441.     for (p=ptab;p < ptab+PTABSIZE; ++p)
  442.     {
  443.     if (p->p_status && p->p_pptr == udata.u_ptab && p != udata.u_ptab)
  444.         goto ok;
  445.     }
  446.     udata.u_error = ECHILD;
  447.     ei();
  448.     return (-1);
  449.  
  450. ok:
  451.     /* Search for an exited child; */
  452.     for (;;)
  453.     {
  454.     chksigs();
  455.     if (udata.u_cursig)
  456.     {
  457.         udata.u_error = EINTR;
  458.         return(-1);
  459.     }
  460.     di();
  461.     for(p=ptab;p < ptab+PTABSIZE; ++p)
  462.     {
  463.         if (p->p_status == P_ZOMBIE && p->p_pptr == udata.u_ptab)
  464.         {
  465.             if (statloc)
  466.                 *statloc = p->p_exitval;
  467.             p->p_status = P_EMPTY;
  468.             retval = p->p_pid;
  469.  
  470.             /* Add in child's time info */
  471.             /* It was stored on top of p_wait in the childs process
  472.             table entry */
  473.             addtick(&udata.u_cutime, &(p->p_wait));
  474.             addtick(&udata.u_cstime, (char *)(&(p->p_wait)) +
  475.                              sizeof(time_t));
  476.  
  477.             ei();
  478.             return(retval);
  479.         }
  480.     }
  481.     /* Nothing yet, so wait */
  482.     psleep(udata.u_ptab);
  483.     }
  484.  
  485. }
  486.  
  487. #undef statloc
  488.  
  489.  
  490.  
  491. /**************************************
  492. _exit(val)
  493. int16 val;
  494. **************************************/
  495.  
  496. #define val (int16)udata.u_argn
  497.  
  498. __exit()
  499. {
  500.     doexit(val,0);
  501. }
  502.  
  503. #undef val
  504.  
  505.  
  506.  
  507. doexit(val,val2)
  508. int16 val;
  509. int16 val2;
  510. {
  511.     register int16 j;
  512.     register ptptr p;
  513.  
  514.     for (j=0; j < UFTSIZE; ++j)
  515.     {
  516.     ifnot (udata.u_files[j] & 0x80)  /* Portable equivalent of == -1 */
  517.         doclose(j);
  518.     }
  519.  
  520. /*    _sync();  /* Not necessary, but a good idea. */
  521.  
  522.     di();
  523.     udata.u_ptab->p_exitval = (val<<8) | (val2 & 0xff);
  524.  
  525.     /* Set child's parents to init */
  526.     for(p=ptab;p < ptab+PTABSIZE; ++p)
  527.     {
  528.     if (p->p_status && p->p_pptr == udata.u_ptab)
  529.         p->p_pptr = initproc;
  530.     }
  531.     i_deref(udata.u_cwd);
  532.  
  533.     /* Stash away child's execution tick counts in process table,
  534.     overlaying some no longer necessary stuff. */
  535.     addtick(&udata.u_utime,&udata.u_cutime);
  536.     addtick(&udata.u_stime,&udata.u_cstime);
  537.     bcopy(&udata.u_utime, &(udata.u_ptab->p_wait), 2 * sizeof(time_t));
  538.  
  539.     /* Wake up a waiting parent, if any. */
  540.     if (udata.u_ptab != initproc)
  541.     wakeup((char *)udata.u_ptab->p_pptr);
  542.     udata.u_ptab->p_status = P_ZOMBIE;
  543.     ei();
  544.     swapin(getproc());
  545.     panic("doexit:won't exit");
  546. }
  547.  
  548.  
  549. _fork()
  550. {
  551.    return (dofork());
  552. }
  553.  
  554.  
  555.  
  556. _pause()
  557. {
  558.     psleep(0);
  559.     udata.u_error = EINTR;
  560.     return(-1);
  561. }
  562.  
  563.  
  564. /*************************************
  565. signal(sig, func)
  566. int16 sig;
  567. int16 (*func)();
  568. ***************************************/
  569.  
  570. #define sig (int16)udata.u_argn1
  571. #define func (int (*)())udata.u_argn
  572.  
  573. _signal()
  574. {
  575.     int retval;
  576.  
  577.     di();
  578.     if (sig < 1 || sig == SIGKILL || sig >= NSIGS)
  579.     {
  580.     udata.u_error = EINVAL;
  581.     goto nogood;
  582.     }
  583.  
  584.     if (func == SIG_IGN)
  585.     udata.u_ptab->p_ignored |= sigmask(sig);
  586.     else
  587.     {
  588.     if (func != SIG_DFL && ((char *)func < PROGBASE ||
  589.            (struct u_data *)func >= &udata))
  590.     {
  591.         udata.u_error = EFAULT;
  592.         goto nogood;
  593.     }
  594.     udata.u_ptab->p_ignored &= ~sigmask(sig);
  595.     }
  596.     retval = udata.u_sigvec[sig];
  597.     udata.u_sigvec[sig] = func;
  598.     ei();
  599.     return(retval);
  600.  
  601. nogood:
  602.     ei();
  603.     return(-1);
  604. }
  605.  
  606. #undef sig
  607. #undef func
  608.  
  609.  
  610.  
  611. /**************************************
  612. kill(pid, sig)
  613. int16 pid;
  614. int16 sig;
  615. *****************************************/
  616.  
  617. #define pid (int16)udata.u_argn1
  618. #define sig (int16)udata.u_argn
  619.  
  620. _kill()
  621. {
  622.     ptptr p;
  623.  
  624.     if (sig <= 0 || sig > 15)
  625.     goto nogood;
  626.  
  627.     for (p=ptab; p < ptab+PTABSIZE; ++p)
  628.     {
  629.     if (p->p_pid == pid)
  630.     {
  631.         sendsig(p,sig);
  632.         return(0);
  633.     }
  634.     }
  635.  
  636. nogood:
  637.     udata.u_error = EINVAL;
  638.     return(-1);
  639. }
  640.  
  641. #undef pid
  642. #undef sig
  643.  
  644.  
  645.  
  646. /********************************
  647. alarm(secs)
  648. uint16 secs;
  649. *********************************/
  650.  
  651. #define secs (int16)udata.u_argn
  652.  
  653. _alarm()
  654. {
  655.     int retval;
  656.  
  657.     di();
  658.     retval = udata.u_ptab->p_alarm;
  659.     udata.u_ptab->p_alarm = secs;
  660.     ei();
  661.     return(retval);
  662. }
  663.  
  664. #undef secs
  665.  
  666.