LaunchOptions::LaunchOptions() : wait(false), #if defined(OS_WIN) start_hidden(false), handles_to_inherit(NULL), inherit_handles(false), as_user(NULL), empty_desktop_name(false), job_handle(NULL), stdin_handle(NULL), stdout_handle(NULL), stderr_handle(NULL), force_breakaway_from_job_(false) #else clear_environ(false), fds_to_remap(NULL), maximize_rlimits(NULL), new_process_group(false) #if defined(OS_LINUX) , clone_flags(0) , allow_new_privs(false) #endif // OS_LINUX #if defined(OS_CHROMEOS) , ctrl_terminal_fd(-1) #endif // OS_CHROMEOS #endif // !defined(OS_WIN) { } LaunchOptions::~LaunchOptions() { } LaunchOptions LaunchOptionsForTest() { LaunchOptions options; #if defined(OS_LINUX) // To prevent accidental privilege sharing to an untrusted child, processes // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this // new child will be used for testing only. options.allow_new_privs = true; #endif return options; } } // namespace base
int main(int argc, char **argv) { int msgfd; struct stat statBuf; Port_t port; char *msg; int sockfd, newsockfd; socklen_t addrlen = 0; union sockaddr_u their_addr; if (argc != 3) { fprintf(stderr, "Usage: portmsg file port\n"); return 1; } port = atoi(argv[2]); if (port == 0) { fprintf(stderr, "error: bad port number [%s]\n", argv[2]); return 1; } if ((msgfd = open(argv[1], O_RDONLY)) < 0) { fprintf(stderr, "error: cannot open message file [%s]: %s\n", argv[1], strerror(errno)); return 1; } /* read the message */ fstat(msgfd, &statBuf); if (statBuf.st_size <= 0) { fprintf(stderr, "error: message file [%s] is empty\n", argv[1]); return 1; } msg = (char *) malloc(statBuf.st_size); if (read(msgfd, msg, statBuf.st_size) != statBuf.st_size) { fprintf(stderr, "error: cannot read message file [%s]\n", argv[1]); return 1; } /* become a daemon */ switch (fork()) { case -1: perror("can't fork"); return 1; case 0: break; default: return 0; } #ifdef HAVE_SETSID if (setsid() < 0) perror("Unable to create new session id (Harmless)"); #else if (new_process_group() < 0) perror("Unable to set new process group (Probably harmless)"); #endif #ifdef USE_TIOCNOTTY if ((fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(fd, TIOCNOTTY, NULL); close(fd); } #endif install_sig_handler(SIGCHLD, wait_on_child); if ((sockfd = make_socket(port, SOCK_STREAM, NULL, NULL, host_ip)) < 0) { perror("can't make socket"); return 1; } main_again: if (connections > MAX_CONNECTIONS) { sleep(1); goto main_again; } addrlen = sizeof(their_addr); newsockfd = accept(sockfd, &their_addr.addr, &addrlen); if (newsockfd < 0) { if (errno == EINTR) goto main_again; perror("Couldn't accept connection"); return 1; } connections++; switch (fork()) { case -1: perror("server can't fork"); return 1; case 0: /* child process */ install_sig_handler(SIGPIPE, lostconn); ignore_signal(SIGCHLD); send(newsockfd, msg, statBuf.st_size, 0); sleep(5); closesocket(newsockfd); break; default: closesocket(newsockfd); goto main_again; } return 0; }
int main(void) { char inputBuffer[MAX_LINE]; /** buffer to hold the command entered **/ int background; /** equals 1 if a command is followed by '&' **/ int respawnable; /** igual a 1 si al comando le sigue '#' **/ char *args[MAX_LINE / 2]; /** command line (of 256) has max of 128 arguments **/ // probably useful variables: int pid_fork, pid_wait; /** pid for created and waited process **/ int status; /** status returned by wait **/ enum status status_res; /** status processed by analyze_status() **/ int info; /** info processed by analyze_status() **/ ignore_terminal_signals(); /** Ignora las señales del terminal **/ /** Asociamos el manejador a la señal SIGCHLD y creamos la lista de trabajos **/ signal(SIGCHLD, manejador); lista_trabajos = new_list("Lista trabajos"); /** Program terminates normally inside get_command() after ^D is typed **/ while(1) { printf("\nCOMMAND->"); fflush(stdout); /** get next command **/ get_command(inputBuffer, MAX_LINE, args, &background, &respawnable); // if empty command if(args[0] == NULL) { continue; } /** Comando interno CD **/ if(strcmp(args[0], "cd") == 0 && args[1] != NULL) { chdir(args[1]); continue; } /** Comando interno historial **/ if(strcmp(args[0], "historial") == 0) { continue; } /** Comando interno JOBS (HECHO) **/ if(strcmp(args[0], "jobs") == 0) { if(empty_list(lista_trabajos)) { printf("La lista de tareas está vacía\n"); } else { print_job_list(lista_trabajos); } continue; } /** Comando interno BG (HECHO) **/ if(strcmp(args[0], "bg") == 0) { if(args[1] == NULL) { printf("No le has pasado ningún argumento al comando \n"); } else { int index = atoi(args[1]); // Convertimos el indice pasado a un entero bgCommand(index); // Invocamos al comando FG } continue; } /** Comando interno FG (HECHO) **/ if(strcmp(args[0], "fg") == 0) { int index = 1; // Por defecto a la primera tarea de la lista if(args[1] != NULL) { index = atoi(args[1]); // Si no es nulo, lo aplicaremos al correspondiente } fgCommand(index); // Invocamos al comando FG continue; } // the steps are: // (1) fork a child process using fork() pid_fork = fork(); if(pid_fork < 0) { // Caso de error printf("Error. The system wasn able to spawn a new process. Exiting...\n"); exit(-1); } else if(pid_fork == 0) { // Proceso hijo /** Nuevo identificador de grupo de procesos para el hijo, asociacion del terminal y señales a default **/ pid_t mypid = getpid(); new_process_group(mypid); // Metemos al hijo en un nuevo grupo if(!background && !respawnable) { // Le asignamos el terminal set_terminal(mypid); } // Restauramos las señales que reciben del terminal restore_terminal_signals(); // (2) the child process will invoke execvp() execvp(args[0], args); // Solo llegará aquí si no se ha producido el cambio de imagen printf("Error. Command not found: %s\n", args[0]); exit(-1); // Padre } else { /** Nuevo identificador de grupo de procesos para el hijo **/ new_process_group(pid_fork); // El padre se va a un nuevo grupo de trabajo /** Si el programa está en background o es respawnable **/ if(background || respawnable) { /** BLoqueamos la señal SIGCHLD, añadimos el trabajo a la lista(background) y desbloqueamos la señal **/ block_SIGCHLD(); job *aux; // Creamos un nuevo nodo para agregarlo a la lista if(background) { aux = new_job(pid_fork, args[0], args, BACKGROUND); } else if(respawnable) { aux = new_job(pid_fork, args[0], args, RESPAWNABLE); } // Añadimos ese nodo a la lista creada anteriormente add_job(lista_trabajos, aux); unblock_SIGCHLD(); printf("Background job running... pid: %d, command: %s. \n", pid_fork, args[0]); /** Si no, es por que está en foreground **/ } else { /** * Wait con detección de suspension y recuperación del terminal * Con el WUNTRACED se comprueba también si el hijo se suspende **/ set_terminal(pid_fork); // Redundante pid_t wait_pid = waitpid(pid_fork, &status, WUNTRACED); set_terminal(getpid()); /** * pid_fork = waitpid(pid_fork, &status, 0); * esta instruccion ya no es necesaria porque hacemos el wait_pid **/ int info; // Le pasamos la variable "status" que nos acaba de pasar el wait enum status st = analyze_status(status, &info); /** * Si sale del bloqueo debido a la suspensión del estado * lo metemos en la lista de tareas para poder llevar un * seguimiento de los procesos suspendidos **/ if(st == SUSPENDED) { /** BLoqueamos la señal SIGCHLD, añadimos el trabajo a la lista (suspendido) y desbloqueamos la señal **/ block_SIGCHLD(); // Creamos un nuevo nodo para agregarlo a la lista job *aux = new_job(pid_fork, args[0], args, STOPPED); // Añadimos ese nodo a la lista creada anteriormente add_job(lista_trabajos, aux); unblock_SIGCHLD(); } // (4) Shell shows a status message for processed command printf("Foreground pid: %d, command: %s, status: %s, info: %d. \n", wait_pid, args[0], status_strings[st], info); } } // (5) loop returns to get_commnad() function } // end while }