Exemple #1
0
/* 
In the event of prev naming a file, not a link (so that there is no last link),
prev[0] == '\0'.

Also searchs for the ${PROFILE_BIN_DIR}, which is the *first* directory on the
link chain containing a readable file "is-profile-bin". If this is not found,
profile_bin_dir[0] == 0.
*/
static int follow_links(char *prev, char *profile_bin_dir, size_t n) {
    int no_links = 1;
    char *cur = malloc(n), *next = malloc(n), *basename;
    profile_bin_dir[0] = '\0';
    hit_strlcpy(cur, prev, n);
    for (;;) {
        /* look for "is-profile-bin" marker */
        if (profile_bin_dir[0] == '\0') {

            splitpath(cur, &basename);
            if (basename != cur) {
                hit_strlcpy(profile_bin_dir, cur, n);
                hit_strlcat(profile_bin_dir, "/is-profile-bin", n);
                if (access(profile_bin_dir, R_OK) == 0) {
                    hit_strlcpy(profile_bin_dir, cur, n);
                } else {
                    profile_bin_dir[0] = '\0';
                }
                basename[-1] = '/'; /* reassemble the path */
            }
        }
        if (resolvelink(cur, next, n) == -1) break;
        no_links = 0;
        hit_strlcpy(prev, cur, n);
        hit_strlcpy(cur, next, n);
    }
    free(cur);
    free(next);
    if (no_links) {
        prev[0] = '\0';
    }
    return (errno == EINVAL) ? 0 : -1;
}
Exemple #2
0
int
exec(char *path, char **argv)
{
  char *s, *last;
  int i, off;
  uint argc, sz, sp, ustack[3+MAXARG+1];
  struct elfhdr elf;
  struct inode *ip, *link;
  struct proghdr ph;
  pde_t *pgdir, *oldpgdir;

  if((ip = namei(path)) == 0)
    return -1;
  ilock(ip);
  if(ip->type == T_SYMLINK){
    if((link = resolvelink(ip)) == 0){
      iunlockput(ip);
      return -1;
    }
    ip = link;
  }
  pgdir = 0;

  // Check ELF header
  if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
    goto bad;
  if(elf.magic != ELF_MAGIC)
    goto bad;

  if((pgdir = setupkvm(kalloc)) == 0)
    goto bad;

  // Load program into memory.
  sz = 0;
  for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
    if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
      goto bad;
    if(ph.type != ELF_PROG_LOAD)
      continue;
    if(ph.memsz < ph.filesz)
      goto bad;
    if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
      goto bad;
    if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
      goto bad;
  }
  iunlockput(ip);
  ip = 0;

  // Allocate two pages at the next page boundary.
  // Make the first inaccessible.  Use the second as the user stack.
  sz = PGROUNDUP(sz);
  if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
    goto bad;
  clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
  sp = sz;

  // Push argument strings, prepare rest of stack in ustack.
  for(argc = 0; argv[argc]; argc++) {
    if(argc >= MAXARG)
      goto bad;
    sp = (sp - (strlen(argv[argc]) + 1)) & ~3;
    if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
      goto bad;
    ustack[3+argc] = sp;
  }
  ustack[3+argc] = 0;

  ustack[0] = 0xffffffff;  // fake return PC
  ustack[1] = argc;
  ustack[2] = sp - (argc+1)*4;  // argv pointer

  sp -= (3+argc+1) * 4;
  if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
    goto bad;

  // Save program name for debugging.
  for(last=s=path; *s; s++)
    if(*s == '/')
      last = s+1;
  safestrcpy(proc->name, last, sizeof(proc->name));

  // Commit to the user image.
  oldpgdir = proc->pgdir;
  proc->pgdir = pgdir;
  proc->sz = sz;
  proc->tf->eip = elf.entry;  // main
  proc->tf->esp = sp;
  switchuvm(proc);
  freevm(oldpgdir);
  return 0;

 bad:
  if(pgdir)
    freevm(pgdir);
  if(ip)
    iunlockput(ip);
  return -1;
}