/*===========================================================================* * do_sigaction * *===========================================================================*/ PUBLIC int do_sigaction() { int r; struct sigaction svec; struct sigaction *svp; if (sig_nr == SIGKILL) return(OK); if (sig_nr < 1 || sig_nr > _NSIG) return (EINVAL); svp = &mp->mp_sigact[sig_nr]; if ((struct sigaction *) sig_osa != (struct sigaction *) NULL) { r = sys_copy(MM_PROC_NR,D, (phys_bytes) svp, who, D, (phys_bytes) sig_osa, (phys_bytes) sizeof(svec)); if (r != OK) return(r); } if ((struct sigaction *) sig_nsa == (struct sigaction *) NULL) return(OK); /* Read in the sigaction structure. */ r = sys_copy(who, D, (phys_bytes) sig_nsa, MM_PROC_NR, D, (phys_bytes) &svec, (phys_bytes) sizeof(svec)); if (r != OK) return(r); if (svec.sa_handler == SIG_IGN) { sigaddset(&mp->mp_ignore, sig_nr); sigdelset(&mp->mp_sigpending, sig_nr); sigdelset(&mp->mp_catch, sig_nr); } else { sigdelset(&mp->mp_ignore, sig_nr); if (svec.sa_handler == SIG_DFL) sigdelset(&mp->mp_catch, sig_nr); else sigaddset(&mp->mp_catch, sig_nr); } mp->mp_sigact[sig_nr].sa_handler = svec.sa_handler; sigdelset(&svec.sa_mask, SIGKILL); mp->mp_sigact[sig_nr].sa_mask = svec.sa_mask; mp->mp_sigact[sig_nr].sa_flags = svec.sa_flags; mp->mp_sigreturn = (vir_bytes) sig_ret; return(OK); }
/*===========================================================================* * do_exec * *===========================================================================*/ PUBLIC int do_exec() { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside MM, and then to the new core image. */ register struct mproc *rmp; struct mproc *sh_mp; int m, r, fd, ft, sn; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ static char name_buf[PATH_MAX]; /* the name of the file to exec */ char *new_sp, *basename; vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp; phys_bytes tot_bytes; /* total space for program, including gap */ long sym_bytes; vir_clicks sc; struct stat s_buf; vir_bytes pc; /* Do some validity checks. */ rmp = mp; stk_bytes = (vir_bytes) stack_bytes; if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */ if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL); /* Get the exec file name and see if the file is executable. */ src = (vir_bytes) exec_name; dst = (vir_bytes) name_buf; r = sys_copy(who, D, (phys_bytes) src, MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len); if (r != OK) return(r); /* file name not in user data segment */ tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ. */ fd = allowed(name_buf, &s_buf, X_BIT); /* is file executable? */ if (fd < 0) return(fd); /* file was not executable */ /* Read the file header and extract the segment sizes. */ sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, &tot_bytes, &sym_bytes, sc, &pc); if (m < 0) { close(fd); /* something wrong with header */ return(ENOEXEC); } /* Fetch the stack from the user before destroying the old core image. */ src = (vir_bytes) stack_ptr; dst = (vir_bytes) mbuf; r = sys_copy(who, D, (phys_bytes) src, MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes); if (r != OK) { close(fd); /* can't fetch stack (e.g. bad virtual addr) */ return(EACCES); } /* Can the process' text be shared with that of one already running? */ sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime); /* Allocate new memory and release old memory. Fix map and tell kernel. */ r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes); if (r != OK) { close(fd); /* insufficient core or program too big */ return(r); } /* Save file identification to allow it to be shared. */ rmp->mp_ino = s_buf.st_ino; rmp->mp_dev = s_buf.st_dev; rmp->mp_ctime = s_buf.st_ctime; /* Patch up stack and copy it from MM to new core image. */ vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT; vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT; vsp -= stk_bytes; patch_ptr(mbuf, vsp); src = (vir_bytes) mbuf; r = sys_copy(MM_PROC_NR, D, (phys_bytes) src, who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes); if (r != OK) panic("do_exec stack copy err", NO_NUM); /* Read in text and data segments. */ if (sh_mp != NULL) { lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */ } else { load_seg(fd, T, text_bytes); } load_seg(fd, D, data_bytes); #if (SHADOWING == 1) if (lseek(fd, (off_t)sym_bytes, SEEK_CUR) == (off_t) -1) ; /* error */ if (relocate(fd, (unsigned char *)mbuf) < 0) ; /* error */ pc += (vir_bytes) rp->mp_seg[T].mem_vir << CLICK_SHIFT; #endif close(fd); /* don't need exec file any more */ /* Take care of setuid/setgid bits. */ if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */ if (s_buf.st_mode & I_SET_UID_BIT) { rmp->mp_effuid = s_buf.st_uid; tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid); } if (s_buf.st_mode & I_SET_GID_BIT) { rmp->mp_effgid = s_buf.st_gid; tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid); } } /* Save offset to initial argc (for ps) */ rmp->mp_procargs = vsp; /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */ for (sn = 1; sn <= _NSIG; sn++) { if (sigismember(&rmp->mp_catch, sn)) { sigdelset(&rmp->mp_catch, sn); rmp->mp_sigact[sn].sa_handler = SIG_DFL; sigemptyset(&rmp->mp_sigact[sn].sa_mask); } } rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */ rmp->mp_flags |= ft; /* turn it on for separate I & D files */ new_sp = (char *) vsp; tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */ /* System will save command line for debugging, ps(1) output, etc. */ basename = strrchr(name_buf, '/'); if (basename == NULL) basename = name_buf; else basename++; sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc); return(OK); }
int semaphore_entry(void) { /* para evitar que la función modifique los valores del mensaje recibido, * creamos variables locales de manera de evitar tener que acceder * al mensaje para armar la respuesta, es más ineficiente, pero... */ int return_val; sem_t sema; sem_t *semaux; int pshared, oflags, permission, initial, value_now, argc, phsared; char name[MAX_NAME]; #ifdef DEBUG /* int i; char *m1;*/ printf("en el semaphore.c\n");/* for (i = 0; i < 100; i++) { if ((m1 = malloc(128)) == NULL) { printf("FALLO MALLOC en la iteracion %d\n", i); break; } strcpy(m1, "malloc\n"); printf("i = %d m1 = %d m1 = %s\n", i, (int)m1, m1); }*/ #endif sema = mensaje_semaforo; oflags = mensaje_oflag; permission = mensaje_permisos; initial = mensaje_valInicial; value_now = mensaje_valActual; argc = mensaje_cantArg; pshared = mensaje_pshared; sys_copy (who, D, (phys_bytes) mensaje_nombre, FS_PROC_NR, D, (phys_bytes) name, (phys_bytes) MAX_NAME); name[MAX_NAME - 1] = '\0'; switch(mensaje_funcion) { case SEM_OPEN: if (argc == 4) { #ifdef DEBUG printf("SEMOPEN name: %s, oflags: %d, permission: %d, initial: %d\n", name, oflags, permission, initial); #endif semaux = sem_open(name, oflags, permission, initial); } else { #ifdef DEBUG printf("SEMOPEN name: %s, oflags: %d\n", name, oflags); #endif semaux = sem_open(name, oflags); } answer(*semaux,0,0,1); break; case SEM_CLOSE: return_val = sem_close(&sema); answer(return_val,sema,0,2); break; case SEM_INIT: return_val = sem_init(&sema, pshared, initial); answer(return_val,sema,0,2); break; case SEM_WAIT: return_val = sem_wait(&sema); answer(return_val,sema,0,2); break; case SEM_POST: return_val = sem_post(&sema); answer(return_val,sema,0,2); break; case SEM_ULINK: return_val = sem_unlink(name); answer(return_val,0,0,1); break; case SEM_GETVAL: return_val = sem_getvalue(&sema, &value_now); answer(return_val,sema,value_now,3); break; case SEM_TRYWAIT: return_val = sem_trywait(&sema); answer(return_val,sema,0,2); break; case SEM_DESTROY: return_val = sem_destroy(&sema); answer(return_val,sema,0,2); break; case SEM_TIMEDWAIT: return_val = no_func(); answer(return_val,0,0,1); break; } #ifdef DEBUG printf("fin de semaphore.c\n"); #endif if (return_val != 0) return (errno); return(OK); }
/*===========================================================================* * do_fork * *===========================================================================*/ PUBLIC int do_fork() { /* The process pointed to by 'mp' has forked. Create a child process. */ register struct mproc *rmp; /* pointer to parent */ register struct mproc *rmc; /* pointer to child */ int i, child_nr, t; phys_clicks prog_clicks, child_base; phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */ /* If tables might fill up during FORK, don't even start since recovery half * way through is such a nuisance. */ rmp = mp; if (procs_in_use == NR_PROCS) return(EAGAIN); if (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN); /* Determine how much memory to allocate. Only the data and stack need to * be copied, because the text segment is either shared or of zero length. */ prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len; prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT; if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM); /* Create a copy of the parent's core image for the child. */ child_abs = (phys_bytes) child_base << CLICK_SHIFT; parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT; i = sys_copy(ABS, 0, parent_abs, ABS, 0, child_abs, prog_bytes); if (i < 0) panic("do_fork can't copy", i); /* Find a slot in 'mproc' for the child process. A slot must exist. */ for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++) if ( (rmc->mp_flags & IN_USE) == 0) break; /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ child_nr = (int)(rmc - mproc); /* slot number of the child */ procs_in_use++; *rmc = *rmp; /* copy parent's process slot to child's */ rmc->mp_parent = who; /* record child's parent */ rmc->mp_flags &= (IN_USE|SEPARATE); /* inherit only these flags */ /* A separate I&D child keeps the parents text segment. The data and stack * segments must refer to the new copy. */ if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base; rmc->mp_seg[D].mem_phys = child_base; rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); rmc->mp_exitstatus = 0; rmc->mp_sigstatus = 0; /* Find a free pid for the child and put it in the table. */ do { t = 0; /* 't' = 0 means pid still free */ next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PID + 1); for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) { t = 1; break; } rmc->mp_pid = next_pid; /* assign pid to child */ } while (t); /* Tell kernel and file system about the (now successful) FORK. */ sys_fork(who, child_nr, rmc->mp_pid); tell_fs(FORK, who, child_nr, rmc->mp_pid); /* Report child's memory map to kernel. */ sys_newmap(child_nr, rmc->mp_seg); /* Reply to child to wake it up. */ setreply(child_nr, 0); return(next_pid); /* child's pid */ }