如何将命令嵌入内置的bash中? [英] How to embed a command into bash which act as built-in?

查看:85
本文介绍了如何将命令嵌入内置的bash中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用C编程语言创建了一个命令行实用程序.现在,我想将该命令嵌入到bash中.它应该充当bash内置命令"cd".我该怎么办??

I have created a command line utility using C programming language. Now I want to embed that command into bash. It should act as bash built-in command 'cd'. How can I do that??

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

In the bash source I saw there is a directory called builtins. I looked that directory and found there is *.def files and there is a file called cd.def.

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

I think this is the definition of bash built-in cd. Now my question is how to create my own definition???

推荐答案

如果您希望将二进制文件内置在bash中

If you wish to make your binary a built-in in bash

方法1:bash功能

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

You can emulate the behavior by creating a bash function in, say ~/.bashrc, file:

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

export -f mycommand

并使用 mycommand ,就像您使用 cd 一样.

and the use mycommand just like you use cd.

请参阅此 [tldp文章] 这与实际的内置软件有所不同.

Do have a look at this [ tldp article ] on how this differ from an actual built-in.

方法2:使用启用

我想我会通过创建一个新的内置函数来查找阶乘来证明这一点.以下是我编写的代码:

I thought I would demonstrate this by creating a new builtin for finding factorial. Below is the code I've written :

/* 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/

Copy the shared object factorial.so to to a local lib location say /usr/local/lib/mylib/

通过在〜/.bashrc中添加以下内容来启用(持久)新的内置文件(如果希望其他用户使用新的内置文件,则可以添加/etc/bash.bashrc)

Enable(persistent) the new builtin by adding the below in ~/.bashrc (or /etc/bash.bashrc if you wish the new builtin to be used by other users)

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

瞧!您已经准备好在新的Shell会话中使用新的内置函数.

And voila! you have the new builtin ready for use in a new shell session.

$ 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提醒这一点)

(thanks @chepner for reminding this)

方法3:重新编译bash

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

Just recompile bash(the dirty way!) with added functionality - [ source code here ].

参考:

  1. enable 联机帮助页 [此处] .
  2. WORD_LIST:始终为内置函数提供指向WORD_LIST类型的列表的指针.如果内置函数实际上没有任何选项,则必须先调用no_options(list)并检查其返回值,然后再进行进一步处理.如果返回值不为零,则您的函数应立即返回值EX_USAGE.检查 [此] .
  3. >
  4. 您需要安装 bash-builtins 库(我在Ubuntu 12.04上,实际的软件包名称可能因发行版而异)才能编译新的内置文件.
  5. 检查 builtin_usage 的使用方式 [定义] .
  6. 要使用enable命令,您的系统应支持动态加载.
  7. enable 中,内置名称(此处为factorial60)应与结构中给出的名称(注意 factorial60_struct )匹配,而 _struct 应会被附加到结构中的内置名称中.
  1. enable manpage [ here ].
  2. WORD_LIST : Built-in functions are always given a pointer to a list of type WORD_LIST. If the built-in doesn't actually take any options, you must call no_options(list) and check its return value before any further processing. If the return value is non-zero, your function should immediately return with the value EX_USAGE. Check [ this ].
  3. You need to install bash-builtins library (I'm on Ubuntu 12.04,The actual package name may differ by distro) to compile new builtins.
  4. Check how builtin_usage is [ defined ].
  5. To use the enable command, your system should support dynamic loading.
  6. In enable the name of the builtin (here factorial60) should match the name given in the structure (notice factorial60_struct) and _struct should be appended to the builtin name in the structure.

这篇关于如何将命令嵌入内置的bash中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆