Advertisement
VisualPaul

Untitled

Oct 20th, 2015
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.20 KB | None | 0 0
  1. #include "types.h"
  2. #include "param.h"
  3. #include "memlayout.h"
  4. #include "mmu.h"
  5. #include "proc.h"
  6. #include "defs.h"
  7. #include "x86.h"
  8. #include "elf.h"
  9.  
  10. static int _exec(char *path, char **argv, int recur_limit);
  11. static int _check_shebang(struct inode *ip);
  12.  
  13. int
  14. exec(char *path, char **argv)
  15. {
  16.   _exec(path, argv, 5);
  17. }
  18.  
  19. static int
  20. _exec(char *path, char **argv, int recur_limit)
  21. {
  22.   char *s, *last;
  23.   int i, off;
  24.   uint argc, sz, sp, ustack[3+MAXARG+1];
  25.   struct elfhdr elf;
  26.   struct inode *ip;
  27.   struct proghdr ph;
  28.   pde_t *pgdir, *oldpgdir;
  29.  
  30.   if (--recur_limit)
  31.     goto bad;
  32.  
  33.   if((ip = namei(path)) == 0)
  34.     return -1;
  35.   ilock(ip);
  36.   pgdir = 0;
  37.  
  38.   // Check ELF header
  39.   if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
  40.     goto bad_elf;
  41.   if(elf.magic != ELF_MAGIC)
  42.     goto bad_elf;
  43.  
  44.   if((pgdir = setupkvm()) == 0)
  45.     goto bad;
  46.  
  47.   // Load program into memory.
  48.   sz = 0;
  49.   for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
  50.     if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
  51.       goto bad;
  52.     if(ph.type != ELF_PROG_LOAD)
  53.       continue;
  54.     if(ph.memsz < ph.filesz)
  55.       goto bad;
  56.     if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
  57.       goto bad;
  58.     if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
  59.       goto bad;
  60.   }
  61.   iunlockput(ip);
  62.   ip = 0;
  63.  
  64.   // Allocate two pages at the next page boundary.
  65.   // Make the first inaccessible.  Use the second as the user stack.
  66.   sz = PGROUNDUP(sz);
  67.   if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
  68.     goto bad;
  69.   clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
  70.   sp = sz;
  71.  
  72.   // Push argument strings, prepare rest of stack in ustack.
  73.   for(argc = 0; argv[argc]; argc++) {
  74.     if(argc >= MAXARG)
  75.       goto bad;
  76.     sp = (sp - (strlen(argv[argc]) + 1)) & ~3;
  77.     if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
  78.       goto bad;
  79.     ustack[3+argc] = sp;
  80.   }
  81.   ustack[3+argc] = 0;
  82.  
  83.   ustack[0] = 0xffffffff;  // fake return PC
  84.   ustack[1] = argc;
  85.   ustack[2] = sp - (argc+1)*4;  // argv pointer
  86.  
  87.   sp -= (3+argc+1) * 4;
  88.   if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
  89.     goto bad;
  90.  
  91.   // Save program name for debugging.
  92.   for(last=s=path; *s; s++)
  93.     if(*s == '/')
  94.       last = s+1;
  95.   safestrcpy(proc->name, last, sizeof(proc->name));
  96.  
  97.   // Commit to the user image.
  98.   oldpgdir = proc->pgdir;
  99.   proc->pgdir = pgdir;
  100.   proc->sz = sz;
  101.   proc->tf->eip = elf.entry;  // main
  102.   proc->tf->esp = sp;
  103.   switchuvm(proc);
  104.   freevm(oldpgdir);
  105.   return 0;
  106.  
  107.  bad:
  108.   if(pgdir)
  109.     freevm(pgdir);
  110.   if(ip)
  111.     iunlockput(ip);
  112.   return -1;
  113.  bad_elf:
  114.   if (_check_shebang(ip)) {
  115.     return _exec_shebang(path, argv, ip, recur_limit);
  116.   } else {
  117.     goto bad;
  118.   }
  119. }
  120.  
  121. static int
  122. _check_sheband(struct inode *ip)
  123. {
  124.   char shebang[2];
  125.   readi(ip, shebang, 0, 2);
  126.   return shebang[0] == '#' && shebang[1] == '!';
  127. }
  128.  
  129. static int
  130. _exec_shebang(char *path, char **argv, struct inode *ip, int recur_limit)
  131. {
  132.   char *shell_path;
  133.   int i, shell_path_len;
  134.  
  135.   shell_path = kalloc();
  136.   shell_path_len = read(ip, shell_path, 2, 4095);
  137.   for (i = 0; i < shell_path_len; ++i) {
  138.     if (shell_path[i] = '\n')
  139.       break;
  140.   }
  141.   shell_path[i] = 0;
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement