I'm trying to create my own shell in C, so far I've gotten it to do everything I need correctly but I'm looking for ways to implement the asynchronous synchronization of when you type & behind a statement or command (also called background), the shell does not wait for the end of the child process but continues to wait for new user commands as the linux shell normally does. I leave my code to see if anyone can help me, I guess I have to do something with the waitpid. Thank you very much in advance.
PS: I also need that when writing & the PID of the process that is generated is shown, just as the unix shell does.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <ctype.h>
#define TAM 1000
void parseo(char *line, char **argv);
char* normalizar(char *str);
int main(void) {
char cad[TAM];
char *argv[TAM];
char *to;
pid_t pid;
int status;
while (1) {
printf("user@PC $: ");
fgets(cad, TAM, stdin);
// Si encontramos un salto de linea (se pulsa enter)
if (cad[strlen(cad) - 1] == '\n')
cad[strlen(cad) - 1] = '#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <ctype.h>
#define TAM 1000
void parseo(char *line, char **argv);
char* normalizar(char *str);
int main(void) {
char cad[TAM];
char *argv[TAM];
char *to;
pid_t pid;
int status;
while (1) {
printf("user@PC $: ");
fgets(cad, TAM, stdin);
// Si encontramos un salto de linea (se pulsa enter)
if (cad[strlen(cad) - 1] == '\n')
cad[strlen(cad) - 1] = '%pre%'; // lo marcamos como final de sentencia
// Si no se escribe nada, se espera
if (strlen(cad) == 0) continue;
// Parseamos lo introducido en el shell
parseo(cad, argv);
// Normalizamos los comandos
normalizar((char*)argv[0]);
// Exit para salir del shell
if (!strcmp(argv[0], "exit")) exit(0);
// Implementación del comando CD
if (!strcmp(argv[0], "cd")){
to = argv[1];
// Retorno al directorio anterior
if(argv[1] == NULL) chdir("..");
chdir(to);
continue;
}
// Creamos el proceso
pid = fork();
if (pid < 0) {
printf("Error al crear los procesos \n");
exit(1);
} else if (pid == 0) {
// Ejecutamos los comandos, a no ser que sea erroneo
if (execvp(*argv, argv) < 0) {
printf("%s: no se encontró la orden \n", argv[0]);
exit(1);
}
}else {
waitpid(pid,&status,0);
}
}
return 0;
}
void parseo(char *line, char **argv){
while (*line != '%pre%') {
while (*line == ' ' || *line == '\t' || *line == '\n')
*line++ = '%pre%';
*argv++ = line;
while (*line != '%pre%' && *line != ' ' && *line != '\t' && *line != '\n')
line++;
}
*argv = '%pre%';
}
char* normalizar(char *str){
unsigned char *p = (unsigned char *)str;
while (*p) {
*p = tolower((unsigned char)*p);
p++;
}
return str;
}
'; // lo marcamos como final de sentencia
// Si no se escribe nada, se espera
if (strlen(cad) == 0) continue;
// Parseamos lo introducido en el shell
parseo(cad, argv);
// Normalizamos los comandos
normalizar((char*)argv[0]);
// Exit para salir del shell
if (!strcmp(argv[0], "exit")) exit(0);
// Implementación del comando CD
if (!strcmp(argv[0], "cd")){
to = argv[1];
// Retorno al directorio anterior
if(argv[1] == NULL) chdir("..");
chdir(to);
continue;
}
// Creamos el proceso
pid = fork();
if (pid < 0) {
printf("Error al crear los procesos \n");
exit(1);
} else if (pid == 0) {
// Ejecutamos los comandos, a no ser que sea erroneo
if (execvp(*argv, argv) < 0) {
printf("%s: no se encontró la orden \n", argv[0]);
exit(1);
}
}else {
waitpid(pid,&status,0);
}
}
return 0;
}
void parseo(char *line, char **argv){
while (*line != '%pre%') {
while (*line == ' ' || *line == '\t' || *line == '\n')
*line++ = '%pre%';
*argv++ = line;
while (*line != '%pre%' && *line != ' ' && *line != '\t' && *line != '\n')
line++;
}
*argv = '%pre%';
}
char* normalizar(char *str){
unsigned char *p = (unsigned char *)str;
while (*p) {
*p = tolower((unsigned char)*p);
p++;
}
return str;
}