es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo ejecutar múltiples comandos desde argv con un delimitador específico.

Recientemente tuve una tarea en la que tenía que crear un programa que tomara desde la línea de comandos dos comandos diferentes, separados con un signo ‘+’ , por ejemplo:

ps -lu miNombreDeUsuario + ls -la

El objetivo del programa era ejecutar dos órdenes simultáneamente, con cualquier número de parámetros por orden, utilizando fork() y exec(). Esta fue mi solución al problema:

#include <sys types.h="">
#include <unistd.h>
#include <stdio.h>
#include <strings.h>

int main (int argc, char* argv[]) {
    char delimiter = '+';
    char* auxp;
    int i = 1;
    int position;

    while(i < argc){
        if (strcmp("+", argv[i]) == 0) {
            argv[i] = NULL;
            position = i;
        }
        i++;
    }

    if (fork() == 0) {
        execvp(argv[1], &argv[1]);
        exit(1);
    }
    if (fork() == 0) {
        execvp(argv[position+1], &argv[position+1]);
        exit(1);
    }

    wait(NULL);
    wait(NULL);
    exit(0);
}

Esto fue suficiente para la tarea, pero quería que funcionara con N argumentos en lugar de solo 2. No puedo encontrar una manera sistemática de encontrar todas las direcciones necesarias. Cualquier ayuda es apreciada, gracias de antemano.</strings.h></stdio.h></unistd.h>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para hacer que el programa funcione con cualquier número de argumentos, se puede recorrer el arreglo argv y encontrar todas las ocurrencias del carácter delimitador. Luego se puede crear un proceso hijo para cada conjunto de argumentos entre los caracteres delimitadores y ejecutar el comando usando execvp(). Aquí hay una versión actualizada del programa que permite cualquier número de argumentos:

    #include <sys types.h="">
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char *argv[]) {
        char delimiter = '+';
        int num_commands = 0;
        int *positions = malloc((argc - 1) * sizeof(int)); // asignar suficiente espacio para todas las posiciones del delimitador
    
        // encontrar todas las posiciones del delimitador en argv
        for (int i = 1; i < argc; i++) {
            if (argv[i][0] == delimiter) {
                positions[num_commands++] = i;
            }
        }
    
        if (num_commands == 0) { // si no se encuentran delimitadores, imprimir error y salir
            fprintf(stderr, "Error: Se esperaba al menos un carácter delimitador '%c' en los argumentos de la línea de comandos\n", delimiter);
            exit(1);
        }
    
        int start = 1;
        for (int i = 0; i <= num_commands; i++) {
            int end = (i == num_commands) ? argc : positions[i];
            int num_args = end - start;
    
            if (num_args == 0) { // si no se encuentran argumentos entre delimitadores, ignorar
                start = positions[i] + 1;
                continue;
            }
    
            if (fork() == 0) {
                char **args = &argv[start];
                args[num_args] = NULL; // establecer el último argumento en NULL para execvp
    
                execvp(args[0], args);
                perror(args[0]); // si falla execvp, imprimir mensaje de error
                exit(1);
            }
    
            start = positions[i] + 1;
        }
    
        // esperar a que todos los procesos hijos terminen
        for (int i = 0; i < num_commands; i++) {
            wait(NULL);
        }
    
        free(positions);
        return 0;
    }
    

    Este programa utiliza una matriz asignada dinámicamente llamada positions para almacenar todas las posiciones del carácter delimitador. Luego recorre positions y crea un proceso hijo para cada comando entre los delimitadores usando fork(). Para cada proceso hijo, pasa el conjunto correcto de argumentos a execvp() y espera a que termine usando wait(). El programa también maneja casos en los que no se dan argumentos entre los delimitadores o si no hay delimitadores en absoluto, imprimiendo un mensaje de error y saliendo.</string.h></stdlib.h></stdio.h></unistd.h>

Comments are closed.