Use a função execlp em C

Jinku Hu 12 outubro 2023
Use a função execlp em C

Este artigo irá demonstrar vários métodos sobre como usar a função execlp em C.

Use execlp para executar um novo programa usando o nome de arquivo em C

A família de funções exec é fornecida como uma API alternativa para a chamada de sistema execve de nível inferior para gerenciar o carregamento de um novo programa na memória do processo. Existem 6 funções separadas nesta família e elas diferem principalmente em seus parâmetros ao invés de resultados. A função execlp é aquela que dá ao usuário a opção de especificar o nome do arquivo e o programa é pesquisado nos diretórios que estão listados na variável de ambiente PATH atual.

Se o nome do arquivo ainda contiver a barra, será tratado o nome do caminho relativo ou absoluto. No exemplo a seguir, implementamos um programa que se comporta de maneira semelhante a um shell. Ou seja, ele pega o nome do programa do usuário e o executa como um processo filho. O pai espera e, quando o filho retorna, o controle vai para a próxima iteração da entrada do usuário. O programa deve ser encerrado pelo usuário com Ctrl+D como o pressionamento de tecla (depende do sistema operacional). Observe que alguns comandos do shell não podem ser executados e, o mais importante, os argumentos da linha de comando não são passados, mas o programa imprime couldn't execute em seu lugar.

#include <sys/wait.h>

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"

enum { MAXLINE = 256, MAXARGS = 48 };

int main(int argc, char *argv[]) {
  char buf[MAXLINE];
  pid_t pid;
  int status;

  char *str1, *token;

  printf("%% ");
  while (fgets(buf, MAXLINE, stdin) != NULL) {
    if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0;

    if ((pid = fork()) < 0) {
      perror("fork");
    } else if (pid == 0) {
      execlp(buf, buf, (char *)NULL);
      printf("couldn't execute: %s", buf);
      exit(127);
    }

    if (waitpid(pid, &status, 0) < 0) perror("waitpid");
    printf("%% ");
  }

  exit(EXIT_SUCCESS);
}

execlp é uma função variável; portanto, pode receber um número variável de argumentos. O primeiro e o último argumentos são fixos, porém, representando o ponteiro para o nome do arquivo e NULL convertido para o char* correspondentemente. Observe que lançar um ponteiro nulo é obrigatório para que a função funcione e também denota o final do número variável de argumentos. Resumindo, os argumentos da segunda posição devem especificar os argumentos da linha de comando para o programa, e o primeiro deles deve ser o próprio nome do arquivo.

Como alternativa, podemos implementar o exemplo anterior para poder executar comandos com argumentos. Nesse caso, utilizamos a função execvp que recebe a lista de argumentos como um array. Além disso, analisamos a entrada do usuário usando strtok para pegar cada string separada por espaço e passá-los como argumentos. Como resultado, obtemos uma emulação mais próxima de um programa shell.

#include <sys/wait.h>

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"

enum { MAXLINE = 256, MAXARGS = 48 };

int main(int argc, char *argv[]) {
  char buf[MAXLINE];
  char *args[MAXARGS];
  pid_t pid;
  int status, args_num = 0;

  char *str1, *token;

  printf("%% ");
  while (fgets(buf, MAXLINE, stdin) != NULL) {
    if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0;

    str1 = strdup(buf);
    for (int j = 0;; j++, str1 = NULL) {
      token = strtok(str1, " ");
      if (token == NULL) break;
      args[j] = token;
      args_num += 1;
      printf("%d: %s\n", j + 1, args[j]);
    }
    free(str1);
    args[args_num] = (char *)NULL;

    if ((pid = fork()) < 0) {
      perror("fork");
    } else if (pid == 0) {
      execvp(args[0], &args[0]);
      printf("couldn't execute: %s", buf);
      exit(127);
    }

    if (waitpid(pid, &status, 0) < 0) perror("waitpid");
    printf("%% ");
  }

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artigo relacionado - C Process