栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用C在Linux Shell中实现输入/输出重定向

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用C在Linux Shell中实现输入/输出重定向

我添加了一个单独的参数传递来捕获和记住I / O重定向,并将其从传递给子级的arg列表中删除。

这是更正后的代码[请原谅免费的样式清理]:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <signal.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/types.h>#include <sys/wait.h>char *prompt = "% ";intmain(){    int pid;    //int child_pid;    char line[81];    char *token;    char *separator = " tn";    char **args;    char **args2;    char *cp;    char *ifile;    char *ofile;    int i;    int j;    int err;    //int check;    //char history[90];    //typedef void (*sighandler_t) (int);    args = malloc(80 * sizeof(char *));    args2 = malloc(80 * sizeof(char *));    //signal(SIGINT, SIG_IGN);    while (1) {        fprintf(stderr, "%s", prompt);        fflush(stderr);        if (fgets(line, 80, stdin) == NULL) break;        // split up the line        i = 0;        while (1) { token = strtok((i == 0) ? line : NULL, separator); if (token == NULL)     break; args[i++] = token;           }        args[i] = NULL;        if (i == 0) continue;        // assume no redirections        ofile = NULL;        ifile = NULL;        // split off the redirections        j = 0;        i = 0;        err = 0;        while (1) { cp = args[i++]; if (cp == NULL)     break; switch (*cp) { case '<':     if (cp[1] == 0)         cp = args[i++];     else         ++cp;     ifile = cp;     if (cp == NULL)         err = 1;     else         if (cp[0] == 0)  err = 1;     break; case '>':     if (cp[1] == 0)         cp = args[i++];     else         ++cp;     ofile = cp;     if (cp == NULL)         err = 1;     else         if (cp[0] == 0)  err = 1;     break; default:     args2[j++] = cp;     break; }        }        args2[j] = NULL;        // we got something like "cat <"        if (err) continue;        // no child arguments        if (j == 0) continue;        switch (pid = fork()) {        case 0: // open stdin if (ifile != NULL) {     int fd = open(ifile, O_RDONLY);     if (dup2(fd, STDIN_FILENO) == -1) {         fprintf(stderr, "dup2 failed");     }     close(fd); } // trying to get this to work // NOTE: now it works :-) // open stdout if (ofile != NULL) {     // args[1] = NULL;     int fd2;     //printf("PLEASE WORK");     if ((fd2 = open(ofile, O_WRonLY | O_CREAT, 0644)) < 0) {         perror("couldn't open output file.");         exit(0);     }     // args+=2;     printf("okay");     dup2(fd2, STDOUT_FILENO);     close(fd2); } execvp(args2[0], args2);         signal(SIGINT, SIG_DFL); fprintf(stderr, "ERROR %s no such programn", line); exit(1); break;        case -1:  fprintf(stderr, "ERROR can't create child process!n"); break;        default: //printf("am I here"); wait(NULL); //waitpid(pid, 0, 0);        }    }    exit(0);}

更新:

如果您还在身边,您认为可以帮助我创建管道吗?

当然。太大,无法在此处发布。请参阅:http://pastebin.com/Ny1w6pUh


哇,您创建了所有3300条线吗?

是。

xstr
从我的另一个SO答案中借用了[错误修正和增强]。它
dlk
是新的,但是我做很多,所以很容易。其中大多数是新代码。

但是…它由我之前做过的片段/概念组成:tgb,FWD,BTV,sysmagic。请注意,所有struct成员

structfoo
都以
foo_
[standard for me] 为前缀。
DLHDEF
DLKDEF
在需要时使用[模拟]继承/范本的巨集“
trickery” 。

许多函数var都重用我的样式:

idx
对于索引var
[我从不使用
i/j
,而是
xidx/yidx
],
cp
对于char指针,
cnt
用于计数,
len
对于字节长度,等等。因此,我不必“思考”一些小东西[策略]并且可以专注于策略。

以上

idx
等。等
对我来说是一种“签名风格”。它不一定比其他人更好(或更糟)。这是因为当链接器/加载器只能处理8个字符符号时,我开始使用C,因此简洁是关键。但是,我习惯于使用较短的名称。考虑哪个更清楚/更好:

for (fooidx = 0;  fooidx <= 10;  ++fooidx)

要么:

for (indexForFooArray = 0;  indexForFooArray <= 10;  ++indexForFooArray)

我用的是

do { ... } while (0)
避免
if/else
梯子一个 不少
。这称为“一次通过”循环。这被认为是“有争议的”,但是以我的经验,它可以使代码更整洁。就个人而言,我从来没有发现[更多标准]使用的
do/while
,不能做更容易/有一个更好的环
while
for
环-因人而异。实际上,许多语言甚至根本没有
do/while

另外,我使用小写字母,除非它始终是大写的

#define
[或
enum
]。也就是说,我使用“蛇皮套”(例如
fooidx
),而 不是
“驼峰皮套”(例如
indexForFooArray
)。

.proto
包含函数原型的文件是自动生成的。这可以节省 大量 时间。 旁注: 确保外部链接中至少有v2,因为Makefile中存在错误。A
make clean
会删除
.proto
。v2不会那样做

这些年来,我发展了自己的风格。原来,Linux内核样式是“从我的借来的”。实际上不是:-)我的是第一位的。但是…他们同时提出了与我的匹配度为99%的内容:

/usr/src/kernels/whatever_version/documentation/CodingStyle

与给定样式(自己的样式)的一致性是关键。对于给定的函数,您不必担心要为变量命名,要使用的缩进或空白行。

这有助于读者/新开发者。他们可以阅读一些功能,查看演奏中的风格,然后由于所有功能具有相似的风格而运行得更快。

所有这些使您可以“更快”,并且在第一次尝试时仍可以获得高质量的代码。我也 很有 经验。

另外,我的代码注释集中在“意图”上。就是说,您希望代码按照实际情况执行什么操作。他们应该回答“什么/为什么”,而代码则是“如何”。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/409032.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号