c语言字符串拼接——snprintf
获取可执行文件绝对路径的时候遇到了一个问题,比如给了可执行文件的名字 “ls”,要求在/bin和/usr/bin里面找存在的可执行的名叫ls的可执行文件,返回绝对路径比如/bin/ls,如果高效拼接“/bin”、“/”、“ls”。

借鉴上面的回答,得到代码:
char *pathSet[] = {"/bin", "/usr/bin", NULL};#define BUFF_SIZE 256int searchPath(char *execute, char *path) {for (int i = 0; pathSet[i] != NULL; i++) {snprintf(path, BUFF_SIZE, "%s/%s", pathSet[i], execute);if (access(path, X_OK) == 0) return 0;}return -1;}
答案(未实现并行指令)
#include <ctype.h> // isspace#include <regex.h> // regcomp, regexec, regfree#include <stdio.h> // fopen, fclose, fileno, getline, feof#include <stdlib.h> // exit#include <sys/types.h>#include <sys/wait.h> // waitpid#include <string.h> // strlen, strsep, strcat, strdup, strcmp#include <unistd.h> // STDERR_FILENO, fork, exec, access, exit, chdir#define INTERACTIVE_MODE 1#define BATCH_MODE 2#define BUFF_SIZE 256char *pathSet[BUFF_SIZE] = {"/bin", "/usr/bin", NULL};char *line = NULL;FILE *in;void printError() {char error_message[30] = "An error has occurred\n";write(STDERR_FILENO, error_message, strlen(error_message));}void parseInputAndExecute(char *arg);void executeCommands(char *args[], int argsNum, FILE *out);int searchPath(char *execute, char *path);void redirect(FILE *out);char *trim(char *s);int main(int argc, char *argv[]) {size_t len = 0;ssize_t readlen = 0;char *command = NULL;//int commandsNum = 0;if (argc == 1) {while (1) {printf("wish> ");if ((readlen = getline(&line, &len, stdin)) != -1) {if (line[readlen - 1] == '\n') line[readlen - 1] = '\0';while ((command = strsep(&line, "&")) != NULL) {//printf("cmd:%s--line:%s--|", command, line);if (command[0] == '\0') continue;parseInputAndExecute(command);}} else {free(line);printError();exit(1);}}} else if (argc == 2){in = fopen(argv[1], "r");if (in == NULL) {free(line);printError();exit(1);}while ((readlen = getline(&line, &len, in)) != -1) {if (line[readlen - 1] == '\n') line[readlen - 1] = '\0';while ((command = strsep(&line, "&")) != NULL) {//printf("cmd:%s--line:%s--|", command, line);if (command[0] == '\0') continue;parseInputAndExecute(command);}}fclose(in);free(line);exit(0);} else {printError();exit(1);}return 0;}void parseInputAndExecute(char *arg) {FILE *out = stdout;int argsNum = 0;char *args[BUFF_SIZE];char *token;char *command = strsep(&arg, ">");if (command == NULL || *command == '\0') {printError();return;}if (arg != NULL) {// contain white space in the middle or ">"char *file = trim(arg);token = strsep(&file, " \t");//printf("file:%s---token:%s", file, token);if (file != NULL) {printError();return;}if ((out = fopen(token, "w")) == NULL) {printError();return;}}//printf("command:%s--arg:%s\n", line, arg);char *const delim = " \t";command = trim(command);while (command && *command != '\0') {token = strsep(&command, delim);if (token != NULL && *token != '\0') args[argsNum++] = token;if (argsNum >= BUFF_SIZE) break;}// for (int i = 0; i < argsNum; i++) {// printf("token:%s--argsNum:%d\n", args[i], argsNum);// }if (argsNum < BUFF_SIZE) args[argsNum] = NULL;else args[BUFF_SIZE - 1] = NULL;if (argsNum > 0) {executeCommands(args, argsNum, out);}}void executeCommands(char *args[], int argsNum, FILE *out) {// check built-in command: exit, cd, pathif (strcmp(args[0], "exit") == 0) {if (argsNum > 1) printError();else {free(line);exit(EXIT_SUCCESS); //exit(0);}} else if (strcmp(args[0], "cd") == 0) {if (argsNum != 2) printError();else {if (chdir(args[1]) == -1) {printError();}}} else if (strcmp(args[0], "path") == 0) {int i = 0;// while (args[i]) {// printf("args:%s\n", args[i]);// i++;// }// i = 0;while (pathSet[i] != NULL) i++;int j = 0;while (j < argsNum - 1) {pathSet[i] = strdup(args[j + 1]);i++;j++;}pathSet[i] = NULL;if (argsNum == 1) pathSet[0] = NULL;// i = 0;// while (pathSet[i]) {// printf("pathset:%s\n", pathSet[i]);// i++;// }} else {// not built-in commandchar path[BUFF_SIZE];int rc = searchPath(args[0], path);if (rc == -1) {printError(); // not fond in pathreturn;}//printf("path: %s,args: %s", path, args[0]);pid_t pid = fork();if (pid < 0) {printError();exit(1);} else if (pid == 0) {redirect(out);execv(path, args);printError();} else {waitpid(pid, NULL, 0); // parent process waits child}}}int searchPath(char *execute, char *path) {for (int i = 0; pathSet[i] != NULL; i++) {snprintf(path, BUFF_SIZE, "%s/%s", pathSet[i], execute);int rc = access(path, X_OK);//printf("path:%s---rc:%d\n", path, rc);if (rc == 0) {return 0;}}return -1;}void redirect(FILE *out) {int outFileno = fileno(out);if (outFileno == -1) {printError();exit(1);}if (outFileno != STDOUT_FILENO) {// redirect outputif (dup2(outFileno, STDOUT_FILENO) == -1) {printError();return;}if (dup2(outFileno, STDERR_FILENO) == -1) {printError();return;}fclose(out);}}char *trim(char *s) {// trim leading spaceswhile (isspace(*s)) s++;if (*s == '\0') return s; //empty string// trim trailing spaceschar *end = s + strlen(s) - 1;while (end > s && isspace(*end)) end--;*(end + 1) = '\0';return s;}
