如何将命令嵌入到作为内置的 bash 中?

Ris*_*nol 5 c bash

我使用 C 编程语言创建了一个命令行实用程序。现在我想将该命令嵌入到 bash 中。它应该作为 bash 内置命令 'cd'。我怎样才能做到这一点??

在 bash 源代码中,我看到有一个名为builtins. 我查看了那个目录,发现有*.def文件,有一个名为cd.def.

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

sjs*_*sam 3

如果你想让你的二进制文件成为 bash 的内置文件

方法一:bash函数

您可以通过在文件中创建 bash 函数来模拟该行为~/.bashrc

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

export -f mycommand
Run Code Online (Sandbox Code Playgroud)

和使用mycommand就像你使用一样cd

请查看这篇[tldp 文章],了解这与实际内置有何不同。

方法2:使用enable

我想我可以通过创建一个新的内置函数来查找阶乘来演示这一点。下面是我写的代码:

/* 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*
};
Run Code Online (Sandbox Code Playgroud)

编译如下代码:

gcc -shared -fpic -o factorial.so factorial.c
Run Code Online (Sandbox Code Playgroud)

将共享对象 Factorial.so 复制到本地库位置(例如)/usr/local/lib/mylib/

通过在 ~/.bashrc 中添加以下内容来启用(持久)新的内置函数(如果您希望其他用户使用新的内置函数,则添加到 /etc/bash.bashrc 中)

enable -f /usr/local/lib/mylib/factorial.so factorial60  # You need to give the full path
Run Code Online (Sandbox Code Playgroud)

瞧!您已准备好在新的 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'
Run Code Online (Sandbox Code Playgroud)

(感谢@chepner提醒这一点)

方法3:重新编译bash

只需重新编译 bash(肮脏的方式!)并添加功能 - [源代码在这里]


参考:

  1. enable联机帮助页[此处]
  2. WORD_LIST :内置函数始终给出一个指向 WORD_LIST 类型列表的指针。如果内置函数实际上不接受任何选项,则必须调用 no_options(list) 并在进一步处理之前检查其返回值。如果返回值非零,您的函数应立即返回值 EX_USAGE。检查[这个]
  3. 你需要安装bash-builtins库(我使用的是 Ubuntu 12.04,实际的包名称可能因发行版而异)来编译新的内置函数。
  4. 检查[定义]builtin_usage如何。
  5. 要使用enable命令,您的系统应该支持动态加载。
  6. 内置函数的名称enable(此处为 Factorial60)应与结构中给出的名称匹配(注意factorial60_struct),并且_struct应附加到结构中的内置名称。