Exemplo n.º 1
0
/* JJJ Shouldn't the check just be that egid/euid does not match
   gid/uid, since euif/egid might be set, but not to root? -jj */
int 
setgroups(int gidsetlen, const gid_t *gidset)
{
  int i;
  int j;

  OSCALLENTER(OSCALL_setgroups);
  if (getuid() == 0 || geteuid() == 0) {
    if (gidsetlen > NGROUPS || gidsetlen < 0) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_setgroups);
      return -1;
    }
    for (i = 0; i < gidsetlen; i++) {
      /* make sure we can touch all the gidset 
       * if we failed we could return errno EFAULT */
      j |= gidset[i];
    }

    for (i = 0; i < gidsetlen; i++) {
      __current->groups[i] = gidset[i];
    }
    __current->groups[i] = GROUP_END;
    OSCALLEXIT(OSCALL_setgroups);
    return 0;
  } else {
    errno = EPERM;
    OSCALLEXIT(OSCALL_setgroups);
    return -1;
  }
}
Exemplo n.º 2
0
int 
setegid(gid_t egid) {
  struct Capability cap;

  OSCALLENTER(OSCALL_setegid);

  if (__current->egid == egid)
    return 0;

  /* Layout the desired capability */
  cap.c_perm = CL_DUP | CL_W;
  cap.c_valid = 1;
  cap.c_isptr = 0;
  cap.c_len = egid ? 3 : 1;
  cap.c_name[0] = 2;
  cap.c_name[1] = egid >> 8;
  cap.c_name[2] = egid & 0xFF;

  /* Try to forge the new gid capability with CAP_GID */
  if (sys_self_forge(CAP_GID, CAP_EGID, &cap) < 0) {
    errno = EPERM;
    OSCALLEXIT(OSCALL_setegid);
    return -1;
  }

  __current->egid = egid;
  OSCALLEXIT(OSCALL_setegid);
  return 0;
}
Exemplo n.º 3
0
Arquivo: mmap.c Projeto: aunali1/exopc
int msync(void *addr, size_t len, int flags) {
  struct mmap_ustruct *mus;
  struct Mmap *m;
  void *nextaddr;
  size_t nextlen;

  OSCALLENTER(OSCALL_msync);
  if (((u_int)addr & PGMASK) || len < 0) {
    errno = EINVAL;
    OSCALLEXIT(OSCALL_msync);
    return -1;
  }
  if (len == 0) {
    OSCALLEXIT(OSCALL_msync);
    return 0;
  }

  nextlen = len;

  do {
    mus = (struct mmap_ustruct *)mregion_get_ustruct(addr);
    if (!mus) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_msync);
      return -1;
    }
    m = &(mus->m);

    if (addr+len > m->mmap_addr+m->mmap_len)
      len -= addr+len - (m->mmap_addr+m->mmap_len);

    msync_mark_bc(m, addr, (u_int)addr + len);
    msync_set_modtimes(m->mmap_filp);

    nextaddr = addr+len;
    nextlen -= len;
    addr = nextaddr;
    len = nextlen;
  } while (len > 0);
  
  OSCALLEXIT(OSCALL_msync);
  return 0;
}
Exemplo n.º 4
0
mode_t 
umask(mode_t numask) {
  mode_t ret;

  OSCALLENTER(OSCALL_umask);
  ret = __current->umask;
  __current->umask = numask;
  OSCALLEXIT(OSCALL_umask);
  return ret;
}
Exemplo n.º 5
0
/* HBXX not 100% of correctness, excerpt from man page:
   The issetugid() function returns 1 if the process was made setuid or set-
   gid as the result of the last execve() system call.  Otherwise it returns
   0.
   */
int 
issetugid(void) {
  int r;

  OSCALLENTER(OSCALL_issetugid);
  r = ((__current->egid == 0 && __current->gid != 0) || 
       (__current->euid == 0 && __current->uid != 0));
  OSCALLEXIT(OSCALL_issetugid);
  return r;
}
Exemplo n.º 6
0
/*
 * Copyright (C) 1997 Massachusetts Institute of Technology 
 *
 * This software is being provided by the copyright holders under the
 * following license. By obtaining, using and/or copying this software,
 * you agree that you have read, understood, and will comply with the
 * following terms and conditions:
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose and without fee or royalty is
 * hereby granted, provided that the full text of this NOTICE appears on
 * ALL copies of the software and documentation or portions thereof,
 * including modifications, that you make.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO
 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
 * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR
 * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR
 * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY
 * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT
 * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR
 * DOCUMENTATION.
 *
 * The name and trademarks of copyright holders may NOT be used in
 * advertising or publicity pertaining to the software without specific,
 * written prior permission. Title to copyright in this software and any
 * associated documentation will at all times remain with copyright
 * holders. See the file AUTHORS which should have accompanied this software
 * for a list of all copyright holders.
 *
 * This file may be derived from previously copyrighted software. This
 * copyright applies only to those changes made by the copyright
 * holders listed in the AUTHORS file. The rest of this file is covered by
 * the copyright notices, if any, listed below.
 */

#include <exos/callcount.h>
#include <exos/uwk.h>
#include <xok/sysinfo.h>
#include <errno.h>
#include <sys/time.h>

#define DID_TIMEOUT 1
#define DID_SIGNAL 2
#define WK_SELECT_SZ 1024
#undef RATE
#define RATE (__sysinfo.si_rate*1000) /* nanoseconds per tick */
int
nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
  struct wk_term t[WK_SELECT_SZ];
  int next;
  unsigned long long absolute_ticks = 0;  

  OSCALLENTER(OSCALL_nanosleep);
  if (rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000) {
    errno = EINVAL;
    OSCALLEXIT(OSCALL_nanosleep);
    return -1;
  }

  absolute_ticks = ((1000000000/RATE) * rqtp->tv_sec) +
    (rqtp->tv_nsec + RATE - 1)/RATE + __sysinfo.si_system_ticks;

  next = 0;
  next = wk_mktag(next, t, DID_TIMEOUT);
  next += wk_mksleep_pred(&t[next], absolute_ticks);
  next = wk_mkop(next, t, WK_OR);
  next = wk_mktag(next, t, DID_SIGNAL);
  next += wk_mksig_pred(&t[next]);
  wk_waitfor_pred(t, next);

  if (rmtp) {
    unsigned long long curticks = __sysinfo.si_system_ticks;
    if (curticks > absolute_ticks) curticks = absolute_ticks;
    rmtp->tv_sec = ((absolute_ticks - curticks)*RATE)/1000000000;
    rmtp->tv_nsec = ((absolute_ticks - curticks)*RATE) % 1000000000;
  }

  if (UAREA.u_pred_tag == DID_TIMEOUT) {
    OSCALLEXIT(OSCALL_nanosleep);
    return 0;
  }
  /* it is ok to return EINTR even if we are interrupted by a restartable signal */
  errno = EINTR;
  OSCALLEXIT(OSCALL_nanosleep);
  return -1;
}
Exemplo n.º 7
0
int 
setuid(uid_t uid) {
  struct Capability cap;

  OSCALLENTER(OSCALL_setuid);

  /* Layout the desired capability */
  cap.c_perm = CL_ALL;
  cap.c_valid = 1;
  cap.c_isptr = 0;
  cap.c_len = uid ? 3 : 1;
  cap.c_name[0] = 1;
  cap.c_name[1] = uid >> 8;
  cap.c_name[2] = uid & 0xFF;

  /* Try to forge the new uid capability with CAP_EUID */
  if (sys_self_forge(CAP_EUID, CAP_SCRATCH, &cap) < 0) {
    /* Couldn't forge, are we just blowing away the euid? */
    if (uid == __current->uid) {
      sys_self_forge(CAP_UID, CAP_EUID, &__curenv->env_clist[CAP_UID]);
      __current->euid = uid;
      __current->fsuid = uid;
      OSCALLEXIT(OSCALL_setuid);
      return 0;
    } else {
      errno = EPERM;
      OSCALLEXIT(OSCALL_setuid);
      return -1;
    }
  }

  /* CAP_SCRATCH is now a token for `cap', move this into euid and uid */
  /* These can't fail since we just forged `cap' into CAP_SCRATCH */
  sys_self_forge(CAP_SCRATCH, CAP_UID, &cap);
  sys_self_forge(CAP_SCRATCH, CAP_EUID, &cap);
  __current->uid = uid;
  __current->euid = uid;
  __current->fsuid = uid;
  OSCALLEXIT(OSCALL_setuid);
  return 0;
}
Exemplo n.º 8
0
int 
setgid(gid_t gid) {
  struct Capability cap;

  OSCALLENTER(OSCALL_setgid);

  /* Layout the desired capability */
  cap.c_perm = CL_DUP | CL_W;
  cap.c_valid = 1;
  cap.c_isptr = 0;
  cap.c_len = gid ? 3 : 1;
  cap.c_name[0] = 2;
  cap.c_name[1] = gid >> 8;
  cap.c_name[2] = gid & 0xFF;

  /* Try to forge the new gid capability with CAP_EGID and CAP_EUID */
  if (sys_self_forge(CAP_EGID, CAP_SCRATCH, &cap) < 0  &&
      sys_self_forge(CAP_EUID, CAP_SCRATCH, &cap) < 0) {
    /* Couldn't forge, Use CAP_GID only if we are setting egid back to gid */
    if (gid == __current->gid) {
      sys_self_forge(CAP_GID, CAP_EGID, &__curenv->env_clist[CAP_GID]);
      __current->egid = gid;
      OSCALLEXIT(OSCALL_setgid);
      return 0;
    } else {
      errno = EPERM;
      OSCALLEXIT(OSCALL_setgid);
      return -1;
    }
  }

  /* CAP_SCRATCH is now a token for `cap', move this into euid and uid */
  /* These can't fail since we know CAP_SCRATCH dominates/equals `cap' */
  sys_self_forge(CAP_SCRATCH, CAP_GID, &cap);
  sys_self_forge(CAP_SCRATCH, CAP_EGID, &cap);
  __current->gid = gid;
  __current->egid = gid;
  OSCALLEXIT(OSCALL_setgid);
  return 0;
}
Exemplo n.º 9
0
int 
getgroups(int gidsetlen, gid_t gidset[])
{
  int i;
  
  OSCALLENTER(OSCALL_getgroups);
  if (gidsetlen == 0) {
    /* just wants to know how many */
    for (i = 0; __current->groups[i] != GROUP_END ; i++);
  } else {
    for (i = 0; __current->groups[i] != GROUP_END ; i++)
      gidset[i] = __current->groups[i];
  }
  OSCALLEXIT(OSCALL_getgroups);
  return(i);
}
Exemplo n.º 10
0
long
fpathconf(int fd, int name) {
    OSCALLENTER(OSCALL_fpathconf);
    return pathconf0(name);
    OSCALLEXIT(OSCALL_fpathconf);
}
Exemplo n.º 11
0
long
pathconf(const char *path, int name) {
    OSCALLENTER(OSCALL_pathconf);
    return pathconf0(name);
    OSCALLEXIT(OSCALL_pathconf);
}
Exemplo n.º 12
0
Arquivo: mmap.c Projeto: aunali1/exopc
int munmap(void *addr, size_t len) {
  struct Mmap *m;
  struct mmap_ustruct *mus;
  void *nextaddr;
  size_t nextlen;

  OSCALLENTER(OSCALL_munmap);
  /* page-ify */
  len += (((u_int)addr) & PGMASK);
  addr = (void*)PGROUNDDOWN((u_int)addr);
  len = PGROUNDUP(len);
  /* impossible to do what man page says! */
#if 0
  if ((((u_int)addr) & PGMASK) || len < 0) {
    errno = EINVAL;
    OSCALLEXIT(OSCALL_munmap);
    return -1;
  }
#endif
  if (len == 0) {
    OSCALLEXIT(OSCALL_munmap);
    return 0;
  }

  nextlen = len;

  do {
    /* get info on the to-be-freed region */
    mus = (struct mmap_ustruct *)mregion_get_ustruct(addr);
    if (!mus) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_munmap);
      return -1;
    }
    m = &(mus->m);

    if (addr+len > m->mmap_addr+m->mmap_len)
      len -= addr+len - (m->mmap_addr+m->mmap_len);

    /* something strange, shouldn't happen */
    if (addr >= m->mmap_addr+m->mmap_len ||
	addr+len <= m->mmap_addr) {
      OSCALLEXIT(OSCALL_munmap);
      return 0;
    }

    /* if completely freed */
    if (addr <= m->mmap_addr && len >= m->mmap_len) {
      __vm_free_region((u_int)m->mmap_addr, m->mmap_len,
		       CAP_ROOT); /* XXX - error check */
      __free(m->mmap_addr); /* if wasn't __malloc'd then this will do nothing */
      LIST_REMOVE(m, mmap_link);
      if (m->mmap_filp) {
	lock_filp(m->mmap_filp);
	filp_refcount_dec(m->mmap_filp);
	if (filp_refcount_get(m->mmap_filp) == 0) {
	  unlock_filp(m->mmap_filp);
	  close_filp(m->mmap_filp);
	} else
	  unlock_filp(m->mmap_filp);
      }
      exos_pinned_free(mus);
      /* retore original handler to region */
      if (mregion_alloc(addr, len, mus->oldmru) < 0) {
	errno = EINVAL;
	OSCALLEXIT(OSCALL_munmap);
	return -1;
      }
    } /* if the end is freed */
    else if (addr > m->mmap_addr && addr+len >= m->mmap_addr+m->mmap_len) {
      m->mmap_len = addr-m->mmap_addr;
      __vm_free_region((u_int)addr, len, CAP_ROOT); /* XXX - error check */
      __free2(addr, 0); /* if wasn't __malloc'd then this will do nothing */
      /* retore original handler to region */
      if (mregion_alloc(addr, len, mus->oldmru) < 0) {
	errno = EINVAL;
	OSCALLEXIT(OSCALL_munmap);
	return -1;
      }
    } /* if the beginning is freed */
    else if (addr <= m->mmap_addr && addr+len < m->mmap_addr+m->mmap_len) {
      __vm_free_region((u_int)addr, len, CAP_ROOT); /* XXX - error check */
      __free2(m->mmap_addr, addr+len - m->mmap_addr);
      m->mmap_len = m->mmap_addr+m->mmap_len - (addr+len);
      m->mmap_addr = addr+len;
      /* retore original handler to region */
      if (mregion_alloc(addr, len, mus->oldmru) < 0) {
	errno = EINVAL;
	OSCALLEXIT(OSCALL_munmap);
	return -1;
      }
    } /* if the middle is freed */
    else {
      __vm_free_region((u_int)addr, len, CAP_ROOT); /* XXX - error check */
      /* retore original handler to region */
      if (mregion_alloc(addr, len, mus->oldmru) < 0) {
	errno = EINVAL;
	OSCALLEXIT(OSCALL_munmap);
	return -1;
      }
      assert(0); /* XXX - too much trouble right now */
    }

    nextaddr = addr+len;
    nextlen -= len;
    addr = nextaddr;
    len = nextlen;
  } while (len > 0);

  OSCALLEXIT(OSCALL_munmap);
  return 0;
}
Exemplo n.º 13
0
Arquivo: mmap.c Projeto: aunali1/exopc
void *mmap (void *addr, size_t len, int prot, int flags, int fd,
	    off_t offset)
{

  u_int pageoff;
  caddr_t ret;
  off_t pos = offset;
  size_t size = len;
  struct Mmap *m;
  struct stat sb;
  struct file *filp;
  struct mmap_ustruct *mus;

  OSCALLENTER(OSCALL_mmap);
  if (!mmap_inited) mmap_init();

  /* if given a bad fd then return */
  if (fd != -1 && fstat (fd, &sb) < 0) {
    errno = EINVAL;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t )-1;
  }

  if ((flags & MAP_COPY) && (flags & MAP_ANON)) flags &= ~MAP_COPY;

  /* OpenBSD 2.1 code */
  /*
   * Align the file position to a page boundary,
   * and save its page offset component.
   */
  pageoff = (pos & PGMASK);
  pos -= pageoff;

  /* Adjust size for rounding (on both ends). */
  size += pageoff;	/* low end... */
  size = PGROUNDUP(size); /* hi end */

  /* Do not allow mappings that cause address wrap... */
  if ((ssize_t)size < 0) {
    errno = EINVAL;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t)-1;
  }

  /*
   * Check for illegal addresses.  Watch out for address wrap...
   */
  if (flags & MAP_FIXED) {
    /*
     * The specified address must have the same remainder
     * as the file offset taken modulo NBPG, so it
     * should be aligned after adjustment by pageoff.
     */
    addr -= pageoff;
    if ((u_int)addr & PGMASK) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
    /* Address range must be all in user VM space. */
    if (UTOP > 0 && (u_int)addr + size > UTOP) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
    if ((u_int)addr > (u_int)addr + size) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  }

  if ((flags & MAP_ANON) == 0) {
    if (fd < 0 || fd > NR_OPEN || __current->fd[fd] == NULL) {
      errno = EBADF;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }

    /*
     * XXX hack to handle use of /dev/zero to map anon
     * memory (ala SunOS).
     */
    if (S_ISCHR(__current->fd[fd]->f_mode) &&
	mmap_iszerodev(__current->fd[fd]->f_dev)) {
      flags |= MAP_ANON;
      goto is_anon;
    }

    /*
     * Only files and cdevs are mappable, and cdevs does not
     * provide private mappings of any kind.
     */
    if (!S_ISREG(__current->fd[fd]->f_mode) &&
	(!S_ISCHR(__current->fd[fd]->f_mode) ||
	 (flags & (MAP_PRIVATE|MAP_COPY)))) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }

    /*
     * Ensure that file and memory protections are
     * compatible.  Note that we only worry about
     * writability if mapping is shared; in this case,
     * current and max prot are dictated by the open file.
     * XXX use the vnode instead?  Problem is: what
     * credentials do we use for determination?
     * What if proc does a setuid?
     */
    if (((__current->fd[fd]->f_flags & O_ACCMODE) == O_WRONLY) &&
	(prot & PROT_READ)) {
      errno = EACCES;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }

    /*
     * If we are sharing potential changes (either via MAP_SHARED
     * or via the implicit sharing of character device mappings),
     * and we are trying to get write permission although we
     * opened it without asking for it, bail out.
     */
    if (((flags & MAP_SHARED) != 0 || S_ISCHR(__current->fd[fd]->f_mode)) &&
	((__current->fd[fd]->f_flags & O_ACCMODE) == O_RDONLY) &&
	(prot & PROT_WRITE) != 0) {
      errno = EACCES;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  } else {
    /*
     * (flags & MAP_ANON) == TRUE
     * Mapping blank space is trivial.
     */
    if (fd != -1) {
      errno = EINVAL;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  is_anon:
    pos = 0;
  }

  if (size == 0) {
    OSCALLEXIT(OSCALL_mmap);
    return addr; 
  }

  if (fd >= 0)
    filp = __current->fd[fd];
  else
    filp = NULL;

  if ((flags & MAP_FIXED) == 0) {
    addr = __malloc(size);
    if (addr == NULL) {
      __free(addr);
      errno = ENOMEM;
      OSCALLEXIT(OSCALL_mmap);
      return (caddr_t)-1;
    }
  }

  mus = exos_pinned_malloc(sizeof(*mus));
  if (mus == NULL) {
    if ((flags & MAP_FIXED) == 0) __free(addr);
    errno = ENOMEM;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t)-1;
  }

  m = &(mus->m);
  m->mmap_addr = addr;
  m->mmap_len = size;
  m->mmap_prot = prot;
  m->mmap_flags = flags;
  m->mmap_offset = pos;
  m->mmap_filp = filp;
  m->mmap_dev = ((fd != -1) ? sb.st_dev : 0);
  LIST_INSERT_HEAD (&mmap_list, m, mmap_link);

  mus->mru.handler = mmap_fault_handler;
  mus->oldmru = mregion_get_ustruct(addr); /* XXX - check return value */

  if (__vm_free_region((u_int)addr, size, 0) < 0 ||
      mregion_alloc(addr, size, (struct mregion_ustruct*)mus) != 0) {
    if ((flags & MAP_FIXED) == 0) __free(addr);
    exos_pinned_free(mus);
    errno = ENOMEM;
    OSCALLEXIT(OSCALL_mmap);
    return (caddr_t)-1;
  }

  if (filp) {
    lock_filp(filp);
    filp_refcount_inc(filp);
    unlock_filp(filp);
  }

  if (flags & MAP_COPY)
    ret = __mmap(addr, size, prot, flags, fd, pos, 0, __envid);
  else
    ret = addr + pageoff;

  OSCALLEXIT(OSCALL_mmap);
  return ret;
}
Exemplo n.º 14
0
gid_t 
getegid(void) {
    OSCALLENTER(OSCALL_getegid);
    OSCALLEXIT(OSCALL_getegid);
    return (__current->egid);
}
Exemplo n.º 15
0
int
select(int width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
	   struct timeval *timeout)
{
  unsigned int wait_ticks = 0;  
  int fd;
#define WK_SELECT_SZ 1024
  struct wk_term t[WK_SELECT_SZ];  
  int next;
  int total = 0;
  fd_set newreadfds, newwritefds, newexceptfds;
#define DID_FDREADY 1		
#define DID_TIMEOUT 2
#define DID_SIGNAL 3
  struct file *filp;
  int had_prev_term;

  OSCALLENTER(OSCALL_select);
  width = MIN (width+1, NR_OPEN);

  /* make sure that all fd's set to be polled are valid fd's */

  for (fd = 0; fd < width; fd++) {
    if ((readfds && FD_ISSET (fd, readfds)) || 
	(writefds && FD_ISSET (fd, writefds)) ||
	(exceptfds && FD_ISSET (fd, exceptfds))) {
      CHECKFD(fd, OSCALL_select);
      assert (CHECKOP (__current->fd[fd], select));
      assert (CHECKOP (__current->fd[fd], select_pred));
    }
  }

  FD_ZERO(&newreadfds);
  FD_ZERO(&newwritefds);
  FD_ZERO(&newexceptfds);

  /* Our basic algorithm is poll the fd's once. If any fd's are found
     ready return. Otherwise sleep until one of them might be ready
     and repeat the process. In practice we don't expect to go
     through this loop more than once, but theoretically we could
     wakeup for some reason other than haveing fd's ready. Am I just
     being paranoid? */

  /* Note: we can _definitely_ go thru this loop more than once, because
     in some cases (e.g., TCP), we can only sleep on an "indication" that
     select might pass (e.g., a packet arrived).  We have to then call
     select to find out if it does in fact make the socket ready, and rebuild
     the sleep predicate otherwise. */

  do {

    had_prev_term = 0;

    /* do a poll on the fd's. We want to make sure that we do this
       before sleeping so on the first time through the do loop we
       avoid descheduling and having to wait till we're re-scheduled
       before noticing that there're fd's ready. */

    for (fd = 0; fd < width; fd++) {
      if (readfds && FD_ISSET (fd, readfds))
	if (DOOP (__current->fd[fd], select, (__current->fd[fd], SELECT_READ))) {
	  total++;
	  FD_SET (fd, &newreadfds);
	}
      if (writefds && FD_ISSET (fd, writefds))
	if (DOOP (__current->fd[fd], select, (__current->fd[fd], SELECT_WRITE))) {
	  total++;
	  FD_SET (fd, &newwritefds);
	}	
      if (SELECT_EXCEPT_CONDITIONS && exceptfds && FD_ISSET (fd, exceptfds))
	if (DOOP (__current->fd[fd], select, (__current->fd[fd], SELECT_EXCEPT))) {
	  total++;
	  FD_SET (fd, &newexceptfds);
	}	
    }

    /* ok, we found some fd's that we need to report. Replace the
       fdsets the user passed in with fdsets containing which
       fd's are ready and return the total number of fd's ready. */

    if (total) {
      if (readfds)
	copyfds (readfds, &newreadfds, width);
      if (writefds)
	copyfds (writefds, &newwritefds, width);
      if (exceptfds)
	copyfds (exceptfds, &newexceptfds, width);
      /* XXX */
      OSCALLEXIT(OSCALL_select);
      return total;
    }

    /* if the user is just polling, handle that now before going through
       all the work to construct a predicate */

    if (timeout) {
      wait_ticks = ((1000000/RATE) * timeout->tv_sec) +
	(timeout->tv_usec + RATE - 1)/RATE;
      if (!wait_ticks)
	{
	  if (readfds) FD_ZERO(readfds);
	  if (writefds) FD_ZERO(writefds);
	  if (exceptfds) FD_ZERO(exceptfds);
	  OSCALLEXIT(OSCALL_select);
	  return 0;
	}
    }

    /* now construct a wakeup-predicate that will wake us when something
       interesting happens on these fd's. We call each fd's select_pred
       operation which returns a clause of the final predicate. All
       clauses are combined into one large predicate that we'll sleep on. */

    next = 0;
    had_prev_term = 0;
    next = wk_mktag (next, t, DID_FDREADY);
    for (fd = 0; fd < width; fd++) {
      filp = __current->fd[fd];
      if (readfds && FD_ISSET (fd, readfds)) {
	if (had_prev_term)
	  next = wk_mkop (next, t, WK_OR);	
	next += DOOP (filp,select_pred,(filp,SELECT_READ,&t[next]));
	had_prev_term = 1;
      }
	  
      if (writefds && FD_ISSET (fd, writefds)) {
	if (had_prev_term)
	  next = wk_mkop (next, t, WK_OR);	
	next += DOOP (filp,select_pred,(filp,SELECT_WRITE,&t[next]));	
	had_prev_term = 1;
      }

      if (SELECT_EXCEPT_CONDITIONS && exceptfds && FD_ISSET (fd, exceptfds)) {
	if (had_prev_term)
	  next = wk_mkop (next, t, WK_OR);	
	next += DOOP (filp,select_pred,(filp,SELECT_EXCEPT,&t[next]));	
	had_prev_term = 1;
      }
    }
    /* slap on a final term to wake us when the timeout occurrs, if there
       is one */

    if (timeout) {
      if (had_prev_term)
	next = wk_mkop (next, t, WK_OR);
      next = wk_mktag (next, t, DID_TIMEOUT);
      next += wk_mksleep_pred (&t[next], wait_ticks + __sysinfo.si_system_ticks);
      had_prev_term = 1;
    }

    /* we need to wakeup if a signal comes in */
    if (had_prev_term) {
       next = wk_mkop (next, t, WK_OR);
    }
    next = wk_mktag (next, t, DID_SIGNAL);
    next += wk_mksig_pred (&t[next]);
    had_prev_term = 1;
    
    /* wait for predicate to evaluate to true */
    wk_waitfor_pred (t, next);

    /* u_pred_tag is set to the piece of the predicate that caused
       us to wake up */

    if (UAREA.u_pred_tag == DID_TIMEOUT) {
      if (readfds) FD_ZERO(readfds);
      if (writefds) FD_ZERO(writefds);
      if (exceptfds) FD_ZERO(exceptfds);
      OSCALLEXIT(OSCALL_select);
      return 0;
    }
    if (UAREA.u_pred_tag == DID_SIGNAL) {
      //kprintf("%d select interrupted by signal\n",getpid());
      errno = EINTR;
      OSCALLEXIT(OSCALL_select);
      return -1;
    }
  
  } while (1);
}
Exemplo n.º 16
0
/* everything is based on this exec, we have an extra flag
   (_EXEC_EXECONLY) to differentiate between the exec and fork_exec
   families.  the difference is that the latter forks and then execs
   the process thereby returning in the parent
   */
static int
fork_execve0(const char *path, char *const argv[], char * const envptr[],
	     int fd, u_int flags)
{
  u_int k = 0;
  int target_cpu = 0;
  struct Uenv cu;
  int NewPid = 0;
  int envid = 0; /* XXX -- init to supress warning */
  char **old_argv = (char **)argv;
  int r, exec_format;
  struct Env e;

  OSCALLENTER(OSCALL_execve);
  /* verify executable permission */
  if (!(flags & _EXEC_USE_FD) && access(path, X_OK) == -1) {
    /* access will set errno */
    r = -errno;
    goto err;
  }

  if (!(envid = sys_env_alloc (0, &r))) {
    fprintf(stderr,"could not sys_env_alloc\n");
    r = -ENOEXEC;
    goto err;
  }

  e = __envs[envidx(envid)];
  if ((exec_format = fork_execve0_part2(path, argv, envptr, &e, fd, flags)) < 0)
    goto err_env_free;

  /* write environment */
  if ((r = sys_wrenv (k, envid, &e)) < 0) {
    kprintf ("sys_wrenv failed\n");
    r = -ENOEXEC;
    goto err;
  }

  if (ExecuteOnExecHandlers(k, envid, flags & _EXEC_EXECONLY) == -1) {
    fprintf(stderr,"cleanup code not done yet\n");
    assert(-1);
  }

#ifdef PROCESS_TABLE
  if (flags & _EXEC_EXECONLY) {
    /* because true exec */
    NewPid = getpid();
  
    dlockputs(__PROCD_LD,"fork_execve0 get lock ");
    EXOS_LOCK(PROCINFO_LOCK);
    dlockputs(__PROCD_LD,"... got lock\n");
    EnterCritical (); 

    ProcChangeEnv(NewPid,envid);
    
    EXOS_UNLOCK(PROCINFO_LOCK);
    dlockputs(__PROCD_LD,"fork_execve0 release lock\n");
    ExitCritical (); 

  } else {
    /* because we are forking */
    NewPid = AllocateFreePid (envid);
  }

  cu = UAREA;
  if (!execonly) {
    AddProcEntry (&cu, (char *)path, (char **)argv, NewPid, UAREA.pid);
    if ((cu.parent_slot = GetChildSlot (NewPid)) < 0) {
      r = -ENOEXEC;
      goto err_env_free;
    }
  } else {
    /* TO TOM: what do we do this for?
    strncpy (UAREA.name, (char*)(((u_int)argv[0]) + ARGV_START_LOCAL - ARGV_START),
	     U_NAMEMAX-1);
    UAREA.name[U_NAMEMAX-1] = '\0'; */
  }
  /* XXX -- on an exec we'll forget to unref our children's pids */
  /* TO TOM: shouldnt this clearchildinfo be at the top */
  ClearChildInfo (&cu);
#else
#ifdef PROCD
  if (flags & _EXEC_EXECONLY) 
  {
    NewPid = getpid();
    /* only register us if we are of the right format */ 
    if (exec_format == EXEC_EXOS_AOUT)
      proc_exec(envid);
  } else {
    NewPid = proc_fork(envid);
  }
  cu = UAREA;
  //kprintf("NewPid %d envid: %d %s proc_%s: (%d) -> %d\n",
	    //NewPid,__envid,execonly ? "exec" : "fork",path,envid,NewPid);
#else
  NewPid = envid;
#endif /* PROCD */
#endif /* PROCESS_TABLE */

  strncpy (cu.name, path, U_NAMEMAX-1);
  cu.name[U_NAMEMAX-1] = '\0';
  cu.u_fpu = 0;
  cu.u_in_critical = 0;
  cu.u_status = U_RUN;
  cu.u_entprologue = e.env_tf.tf_eip;
  cu.u_entepilogue = e.env_tf.tf_eip;
  cu.u_entfault = 0;
  cu.u_entipc1 = 0;
  cu.u_entipc2 = 0;
  cu.u_ppc = 0;
#ifdef PROCESS_TABLE
  cu.u_chld_state_chng = 0;
#endif /* PROCESS_TABLE */
  cu.u_next_timeout = 0;
  cu.u_in_pfault = 0;
  cu.u_donate = -1;
  cu.u_yield_count = 0;
  cu.u_epilogue_count = 0;
  cu.u_epilogue_abort_count = 0;

  STOPP(misc,step7);
  ISTART(misc,step8);

  cu.u_start_kern_call_counting = 0;

  if ((r = sys_wru (0, envid, &cu)) < 0) {
    fprintf (stderr,"sys_wru failed\n");
    r = -ENOEXEC;
    goto err_env_free;
  }

  target_cpu = 0;

#ifdef __SMP__
  if (strncmp(path,"_cpu",4)==0 && strlen(path)>4) 
  {
    target_cpu = path[4]-'0';
    if (target_cpu<0 || target_cpu>sys_get_num_cpus()-1) 
      target_cpu = 0;
  }
#endif

  /* we can't do this until all the child state is setup */
  if ((r = sys_quantum_alloc (k, -1, target_cpu, envid)) < 0) {
    fprintf (stderr,"could not alloc quantum\n");
    r = -ENOEXEC;
    goto err_env_free;
  }

  /* if we're doing a true unix exec and not a combined fork/spawn
     we need to destroy ourselves since our child should have
     replaced us. */

  if (flags & _EXEC_EXECONLY) 
  {
    /* if not an exos format, should not expect normal child behaviors, so we
     * just quit from procd to avoid any hanging...
     */
    if (exec_format == EXEC_SIMPLE)
      proc_exit(0);

    /* we die anyways, so free quantum and env */
    ProcessFreeQuanta(__envid);
    sys_env_free (0, __envid);
  }

  if (old_argv != argv) __free((char**)argv);
  OSCALLEXIT(OSCALL_execve);
  return (NewPid);

err_env_free:
  ProcessFreeQuanta(__envid);
  sys_env_free (k, envid);

err:
  if (old_argv != argv) __free((char**)argv);
  errno = -r;
  OSCALLEXIT(OSCALL_execve);
  return -1;
}