2016-05-21 25 views
4

我已经使用C编程语言创建了一个命令行实用程序。现在我想将该命令嵌入到bash中。它应该作为bash内置命令'cd'。 我该怎么做?如何将命令嵌入到作为内置的bash中?

在bash源文件中,我看到有一个目录builtins。我看了那个目录,发现有*.def文件,还有一个文件叫cd.def

我认为这是bash内置的定义cd。现在我的问题是如何创建我自己的定义?

+5

您不能将其嵌入到bash中,但可以将其复制到路径中的某个位置,如/ usr/bin或/ usr/local/bin。然后运行它,你需要做的就是输入它的名字。 – par

+5

您必须构建一个定制版本的bash –

+4

您可以通过'enable'命令加载新的内置函数。这可能会涉及修改实用程序,以便它以正确的形式加载。源代码分发提供了许多[示例](http://git.savannah.gnu.org/cgit/bash.git/tree/examples/loadables?id=bash-4.3)。 – chepner

回答

2

如果你想使你的二进制内置在bash

方法1:bash函数

您可以通过创建一个bash函数模仿行为,说~/.bashrc,文件:

function mycommand 
{ 
/path/to/your/binary #plus arguments if any 
} 

export -f mycommand 

和使用mycommand就像你使用cd

看看这[ tldp article ]如何这不同于实际的内置。

方法2:使用使

我想我会通过创建寻找阶乘一个新的内置证明这一点。下面是我写的代码:

/* Programme to compute the factorial of numbers up to 60 */ 

#include <bash/config.h> 

#if defined(HAVE_UNISTD_H) 
    #include <unistd.h> 
#endif 

#include <bash/shell.h> // for shell internals 
#include <bash/builtins.h> // for struct builtin 

#include <stdio.h> 
#include <stdlib.h> // for atoi 

/* For unsigned long long numbers, my system could handle numbers 
* upto 65 when it comes to factorial, but I'm restricting the value 
* to 60 for the sake of the example so naming my builtin 'factorial60' 
* the wrapper is factorial_wrapper and the actual task of computing the 
* factorial is done by the function 'factorial'which resides inside the 
* wrapper. 
*/ 

unsigned long long factorial(unsigned long long x, unsigned long long amt) 
{ 
    if (x == 0) 
    return amt; 
    else 
    amt*=x; 
    return factorial(x-1, amt); 
} 

int factorial_wrapper(WORD_LIST* list) //Wrapper function 
{ 
    char* ptr=NULL; 
    int num; 
    if (list == 0) { 
    builtin_usage(); 
    fflush(stdout); 
    return (EX_USAGE); 
    } 
    else{ 
    ptr=list->word->word; 

    /* We're expecting one & only one argument here. 
    * I haven't checked for multiple arguments for the sake of brevity 
    */ 
    num=atoi(ptr); 

    /* atoi is not the best here because it returns zero for invalid conversions 
    * I used it just for the sake of this example. 
    */ 

    if (num>60){ 
    builtin_usage(); 
    fflush(stdout); 
    return (EX_USAGE); 
    } 

    printf("%llu\n",factorial(num,1)); 
    fflush(stdout); 
    } 
    return (EXECUTION_SUCCESS);  // returning 0 
} 


char *factorial60_doc[] = { 
    "factorial60", 
    "Usage : factorial60 number", 
    "Description :", 
    "Gives the factorial of numbers upto 60", 
    (char *)NULL 
}; 
// Make sure the above documentation is sensible 
// You need to supply factorial60_doc to the structure below. 


struct builtin factorial60_struct = { 
    "factorial60", // builtin name 
    factorial_wrapper, // wrapper function for implementing the builtin 
    BUILTIN_ENABLED, // initial flags for builtin - See Reference 1 
    factorial60_doc, // array of long documentation strings. 
    "Usage : factorial60 'number_upto_60'", // usage synopsis; becomes short_doc 
    NULL // reserved for internal use, this a char* 
}; 

编译像下面的代码:

gcc -shared -fpic -o factorial.so factorial.c 

复制共享对象factorial.so对本地的lib位置说/usr/local/lib/mylib/

启用(通过在〜/ .bashrc中添加下面的内容(或者/etc/bash.bashrc,如果您希望其他用户使用新的内置函数),新的内置函数将被添加到内存中:

enable -f /usr/local/lib/mylib/factorial.so factorial60 # You need to give the full path 

瞧!你已经准备好在新的shell会话中使用新内置。

$ factorial60 24 
10611558092380307456 
$ factorial60 
factorial60: usage: Usage : factorial60 'number_upto_60' 
$ type -a factorial60 
factorial60 is a shell builtin 
$ factorial60 61 
factorial60: usage: Usage : factorial60 'number_upto_60' 

(提醒此感谢@chepner)

方法3:重新编译的bash

只需重新编译与附加功能的bash(肮脏的方式!) - [ source code here ]


参考文献:

  1. enable手册页[ here ]
  2. WORD_LIST:内置函数总是给出一个指向WORD_LIST类型列表的指针。如果内置实际上没有选择任何选项,则必须在进一步处理之前调用no_options(list)并检查其返回值。如果返回值不为零,则函数应立即返回值EX_USAGE。检查[ this ]
  3. 您需要安装bash-builtins库(我在Ubuntu 12.04上,实际的软件包名称可能因发行版而异)来编译新的内置函数。
  4. 检查如何builtin_usage[ defined ]
  5. 要使用enable命令,您的系统应支持动态加载。
  6. enable内建(这里factorial60)应与在结构给出的名称的名称(注意factorial60_struct)和_struct应该附加到该结构中的内置名称

+0

'cd'不是一个二进制文件。如果是这样,它不会改变其子进程的工作目录 –

+0

您可以使用bash功能 –

+0

@EdHeal:更新:-) – sjsam

-1

您还可以使用alias,只需添加以下行~/.bashrc将做的工作。

alias commandname='/path/to/your/binary' 
-2

您可以将其安装到您的用户路径的直接部分。通常以下选项之一:

"/bin" or "/usr/bin" - 您需要在机器上进行root访问才能执行此操作。

"~/bin" - 如果它只是为你的用户,你没有root权限。