Unix Minishell Question Pastebin: http://pastebin.com/v5uU1XbM (Fork begins on l
ID: 3765365 • Letter: U
Question
Unix Minishell Question
Pastebin: http://pastebin.com/v5uU1XbM (Fork begins on line 117)
How can I get an integer value for the status of a background process? My aim is to eventually mimick the "jobs" command in shell which displays something like this for background processes:
jobs:
[0] Running sleep 20 &
[1] Running sleep 15 &
[2] Done sleep 5 &
As of now I can print everything but the status.
Also if you see anything else I may need to fix, it would be greatly appreciated.Thank you
Explanation / Answer
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#include <wait.h>
#define DEFAULT_PROMPT " Log710H2014%>"
#define EXIT_CMD "exit"
#define CD_CMD "cd"
#define JOB_LIST_CMD "aptaches"
#define HOME_ENV_VAR "HOME"
#define NEW_LINE " ************************************************** "
#define BCG_CMD_FLAG "&"
void cd_handler(int argc, char *argv[]);
int lire(char *chaine, int longueur);
char** init_command(int* size,char *str);
int execProg(int *argc, char **argv);
int execProgBg(int *argc, char **argv);
void sigchldHandler(int sig_num);
void aptachesHandler();
void cleanJobList(pid_t *childpid);
struct beanProcess {
pid_t pid;
int job_num;
char *command;
};
void ajoutProcess(struct beanProcess bp);
struct beanProcess beans[20];
int jobCount = 1;
int main() {
signal(SIGCHLD, sigchldHandler);
printf(NEW_LINE);
printf("Bienvenue sur le shell de l'equipe 1");
printf(NEW_LINE);
while(1){
char str[200]="";
printf(DEFAULT_PROMPT);
lire(str, 200);
int commArgsC = 0, bg = 0;
char** comms = init_command(&commArgsC, str);
if(commArgsC == 0){
//printf("Saisie vide, veuillez entrez une commande.");
continue;
}
if(strcmp(comms[commArgsC-1], BCG_CMD_FLAG) == 0){
bg = 1;
comms[commArgsC-1] = 0;
}
if(strcmp(comms[0], CD_CMD) == 0){
cd_handler(commArgsC, comms);
commArgsC = commArgsC -1;
}
else if (strcmp(comms[0], JOB_LIST_CMD) == 0){
aptachesHandler();
}
else if (strcmp(comms[0], EXIT_CMD) == 0){
int beansVide = 1;
for(int i = 0; i < jobCount -1 ; i++){
if(beans[i].pid != 0){
beansVide = 0;
}
}
if(beansVide){
exit(0);
}else{
printf(" Impossible d'arreter le programme, des processus sont encore en cours d'éxécution ");
}
}
else {
if(bg){
execProgBg(&commArgsC, comms);
}
else{
execProg(&commArgsC, comms);
}
}
}
return 0;
}
void cd_handler(int argc, char *argv[]){
char buff[512];
char * directory;
if(argc < 2){
directory = getenv(HOME_ENV_VAR);
}else if (argc == 2){
directory = argv[1];
}else{
exit(1);
}
if (chdir(directory) == -1) {
printf ("Erreur de changement de repertoire actif", strerror (errno));
}else{
if (getcwd(buff, sizeof(buff)) == NULL)
perror("Impossible d'afficher le repertoire courant");
else
printf("le repertoire courant est: %s ", buff);
}
}
char** init_command(int* size, char* str){
char ** res = NULL;
char * p = strtok (str, " ");
int n_spaces = 0;
while (p) {
res = realloc (res, sizeof (char*) * ++n_spaces);
if (res == NULL){
exit (-1);
}
res[n_spaces-1] = p;
p = strtok (NULL, " ");
}
res = realloc (res, sizeof (char*) * (n_spaces+1));
res[n_spaces] = 0;
*size = n_spaces;
return res;
}
int lire(char *chaine, int longueur)
{
char *positionEntree = NULL;
if (fgets(chaine, longueur, stdin) != NULL)
{
positionEntree = strchr(chaine, ' ');
if (positionEntree != NULL)
{
*positionEntree = '';
}
return 1;
}
else
{
return 0;
}
}
int execProg(int *argc, char **argv){
char path[30] = "/bin/";
strcat(path,argv[0]);
printf("Voici le resultat de l'execution de votre commande ");
pid_t pid;
pid = fork();
if (pid < 0) {
perror("Creation de processus avec fork echouee");
exit(-1);
}
else if (pid == 0) {
if(execvp(argv[0], argv) == -1){
perror("execv");
return EXIT_FAILURE;
}
}
else {
struct rusage rusg;
long temp, tempCpu;
wait (NULL);
sleep 20 &
sleep 15 &
getrusage(RUSAGE_CHILDREN, &rusg);
printf(" Statistique de la commande %s: ", argv[0]);
temp = (rusg.ru_utime.tv_sec * 1000) + (rusg.ru_utime.tv_usec / 1000);
tempCpu = (rusg.ru_stime.tv_sec * 1000) + (rusg.ru_stime.tv_usec / 1000);
printf(" Le temps wall-clock (ms): %ld", temp);
printf(" Le temps CPU (ms) %ld", tempCpu);
printf(" NB interruptions volontaires: %ld", rusg.ru_nvcsw);
printf(" NB interruptions involontaires: %ld", rusg.ru_nivcsw);
printf(" NB defaults de pages: %ld", rusg.ru_majflt);
printf(" NB defaults de pages satifaits du noyau : %ld", rusg.ru_minflt);
}
return EXIT_SUCCESS;
}
int execProgBg(int *argc, char **argv){
pid_t pid;
pid = fork();
if (pid < 0) {
perror("Creation de processus avec fork echouee");
return EXIT_FAILURE;
}
else if (pid == 0) {
if(execvp(argv[0], argv) == -1){
perror("execvp");
return EXIT_FAILURE;
}
}
else {
printf("[%d] %d", jobCount, pid);
struct beanProcess bP;
bP.pid = pid;
bP.job_num = jobCount;
bP.command = argv[0];
ajoutProcess(bP);
}
return EXIT_SUCCESS;
}
void sigchldHandler(int sig_num)
{
int status;
pid_t childPid;
childPid = waitpid(-1, &status, WNOHANG);
cleanJobList(&childPid);
}
void ajoutProcess(struct beanProcess bP){
beans[jobCount-1] = bP;
jobCount++;
}
void aptachesHandler(){
for(int i = 0; i < jobCount-1 ; i++){
printf("[%d] %d %s ", beans[i].job_num, beans[i].pid, beans[i].command) ;
}
}
void cleanJobList(pid_t *childpid){
printf("clean performed on %d", *childpid);
for(int i = 0; i < jobCount-1 ; i++){
if(beans[i].pid == *childpid){
beans[i].pid = 0;
beans[i].job_num = 0;
beans[i].command = NULL;
}
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.