现在的位置: 首页 > 综合 > 正文

Linux下建立自定义命令的过程

2018年04月11日 ⁄ 综合 ⁄ 共 7383字 ⁄ 字号 评论关闭

本文通过实现一个“创建C语言头文件和源文件模板”的dn命令作为例子演示linux中实现带参数的命令过程。

第一步:实现命令源代码:

/**********************************************************    
FileName : dn.c 
FileFunc : Linux下实现.c和.h文件模板    
Version  : V0.1     
Author   : qiuyigui     
Date     : 2013-03-30
Descp    : Linux下实现命令行实用程序   
*************************************************************/ 
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <time.h>  

void GetLocalTime( char *pOutTime ); 
unsigned char createfile( unsigned char ucFileFlag,char *pFilename ); 
void StrToUpper( char *pcStr ); 
void write_h( FILE *fp ,char *pFileName,char *pAliasName); 
void write_c( FILE *fp,char *pFileName ); 

void GetLocalTime( char *pOutTime )   
{   
time_t t;   
struct tm tm1;   
t = time(NULL);   
memcpy(&tm1,localtime(&t),sizeof(struct tm));   
sprintf(pOutTime,"%04d-%02d-%02d %02d:%02d:%02d",tm1.tm_year+1900,tm1.tm_mon+1,tm1.tm_mday,tm1.tm_hour,tm1.tm_min,tm1.tm_sec);   
/*YYYYMMDDHHMMSS(年月日时分秒)   */ 
}   

void StrToUpper( char *pcStr ) 

while( '\0'!=*pcStr ) 

    if( islower(*pcStr) ) 
    *pcStr -= 32;  
    ++pcStr; 

     

int main( int argc,char *argv[] )   

unsigned char ucRetCode = 1; 
 
if( 2==argc )   
{   
    if( 0==memcmp(argv[1],"--help",strlen(argv[1])) ) 
    { 
        fprintf(stderr,"用法:dn 选项... 文件... \n"); 
        fprintf(stderr,"根据<选项>参数的设置来选择创建指定的<文件>是.h文件还是.c文件。\n"); 
        fprintf(stderr,"\n<选项>    <文件> 参数的设置\n"); 
        fprintf(stderr,"-h  filename        创建名为filename.h文件\n"); 
        fprintf(stderr,"-c  filename        创建名为filename.c文件\n"); 
        fprintf(stderr,"--help              显示此帮助信息并退出\n"); 
        fprintf(stderr,"--version           输出版本信息并退出\n"); 
        fprintf(stderr,"\n如遇到问题,请向 <qiuyigui@126.com> 报告错误。\n"); 
    } 
    else if( 0==memcmp(argv[1],"--version",strlen(argv[1])) ) 
    { 
        fprintf(stderr,"create (free code) 1.01\n"); 
        fprintf(stderr,"这是自由软件,相互交流学习可以加入QQ:58114361\n"); 
        fprintf(stderr,"\n"); 
        fprintf(stderr,"由qiuyigui编写\n"); 
    } 
    else 
    { 
        fprintf(stderr,"%s:无效选项\"%s\"   \n",argv[0],argv[1]); 
        fprintf(stderr,"请尝试执行 \"dn --help\" 来获取更多的信息. \n"); 
    }              
     
    exit (1);   
}   

if( 3!=argc ) 

    fprintf(stderr,"%s:无效选项  \n",argv[0]); 
    fprintf(stderr,"请尝试执行 \"dn --help\" 来获取更多的信息. \n"); 
    exit (1); 

 
if( '-'==*argv[1]) 
{    
    if( 0==memcmp(argv[1],"-h",strlen(argv[1])) ) 
    {    
        ucRetCode = createfile(0,argv[2]); 
    }    
    else if( 0==memcmp(argv[1],"-c",strlen(argv[1])) ) 
    {    
        ucRetCode = createfile(1,argv[2]);                   
    }    
    else 
    { 
        fprintf(stderr,"%s:无效选项\"%s\"  \"%s\" \n",argv[0],argv[1],argv[2]); 
        fprintf(stderr,"请尝试执行 \"dn --help\" 来获取更多的信息. \n");  
        exit(1); 
    }    
     

else 

    fprintf(stderr,"%s:无效选项\"%s\"  \"%s\" \n",argv[0],argv[1],argv[2]); 
    fprintf(stderr,"请尝试执行 \"dn --help\" 来获取更多的信息. \n");  
    exit(1); 
}    
 
return ucRetCode; 

unsigned char createfile(unsigned char ucFileFlag,char *pFilename) 

unsigned char ucRetCode = 1; 
char szFileName[30]; 
char szAliasName[30]; 
 
FILE *fp = NULL; 
unsigned int uiI; 
 
if( strlen(pFilename)>27 ) 

    fprintf(stderr,"%s:创建文件失败,文件名长度太长!\n",pFilename); 
    return 1; 
}     
 
memset(szFileName,0,sizeof(szFileName)); 
 
if( !ucFileFlag ) 
{    
    sprintf(szFileName,"%s.h",pFilename); 

else 

    sprintf(szFileName,"%s.c",pFilename); 
}    
 
memset(szAliasName,0,sizeof(szAliasName)); 
sprintf(szAliasName,"%s",pFilename); 
StrToUpper(szAliasName); 
fp = fopen(szFileName,"r"); 
if( NULL!=fp ) 

    fclose(fp); 
    fprintf(stderr,"%s:创建文件失败,你指定的文件名当前目录下已经存在!\n",pFilename); 
    return 1; 
}    
 
fp = NULL; 
fp = fopen(szFileName,"a"); 
if( NULL==fp ) 

    fprintf(stderr,"%s:创建文件失败!\n",pFilename); 
    return 1; 

if( !ucFileFlag ) 

    write_h(fp,szFileName,szAliasName); 

else 

    write_c(fp,szFileName); 
}    
fclose(fp); 
 
return 0; 

 

void write_h( FILE *fp ,char *pFileName,char *pAliasName ) 

char szTime[30]; 
 
memset(szTime,0,sizeof(szTime)); 
GetLocalTime(szTime); 
fprintf(fp,"/*************************************************************\n"); 
fprintf(fp,"    FileName : %s \n",pFileName); 
fprintf(fp,"    FileFunc : 定义头文件  \n"); 
fprintf(fp,"    Version  : V0.1  \n"); 
fprintf(fp,"    Author   : Sunrier  \n"); 
fprintf(fp,"    Date     : %s \n",szTime); 
fprintf(fp,"    Descp    : Linux下头文件 \n"); 
fprintf(fp,"*************************************************************/\n"); 
fprintf(fp,"#ifndef   __%s_H__\n",pAliasName); 
fprintf(fp,"#define   __%s_H__\n",pAliasName); 
fprintf(fp,"\n"); 
fprintf(fp,"#ifdef __cplusplus\n"); 
fprintf(fp,"extern \"C\" {\n"); 
fprintf(fp,"#endif\n"); 
fprintf(fp,"\n\n\n\n"); 
fprintf(fp,"#ifdef __cplusplus\n"); 
fprintf(fp,"}\n"); 
fprintf(fp,"#endif\n"); 
fprintf(fp,"\n"); 
fprintf(fp,"#endif\n");          
 

void write_c( FILE *fp,char *pFileName ) 

char szTime[30]; 
 
memset(szTime,0,sizeof(szTime)); 
GetLocalTime(szTime); 
fprintf(fp,"/*************************************************************\n"); 
fprintf(fp,"    FileName : %s \n",pFileName); 
fprintf(fp,"    FileFunc : 定义实现文件  \n"); 
fprintf(fp,"    Version  : V0.1  \n"); 
fprintf(fp,"    Author   : Sunrier  \n"); 
fprintf(fp,"    Date     : %s \n",szTime); 
fprintf(fp,"    Descp    : Linux下实现文件 \n"); 
fprintf(fp,"*************************************************************/\n"); 
fprintf(fp,"#include <stdio.h>\n"); 
fprintf(fp,"\n"); 
fprintf(fp,"int main(int argc,char *argv[])\n"); 
fprintf(fp,"{\n"); 
fprintf(fp,"\n\n"); 
fprintf(fp,"    return 0;\n"); 
fprintf(fp,"}\n"); 
fprintf(fp,"\n"); 
}

第二步:创建man手册文档:

.\"表示:行首注释  而\":表示在行中的注释
.\":dn命令程序手册页的实例
.TH DN 1 "2013-03-30" "dn 1.01" "User Commands"
.\"DN:表示标题
.\"1:表示此命令出现在手册页的第几部分,范围为1-8的数字,和定义这个文件名小数点后的数字一致
.\""2013-03-30":表示"2013-03-30"显示在整个页的下中
.\""dn 1.01":表示"dn 1.01"显示在整个页的左下
.\""User Commands":表示"User Commands"显示在整个页的上中
.\".TH在文件的开始,主要说明标题
.SH NAME
.\"说明名称
.\".SH从行首开始,靠左边,宽体
\fBdn\fR \- A simple demonstration application creates a file that head file or c file .
.\"-:表示为\-
.SH SYNOPSIS
.\"说明语法格式
.B dn
.\".B:表示宽体,如果本行没有文字,则.B标签的下一行为宽体
\-OPTION... FILE...
.SH DESCRIPTION
.\"说明本命令或程序等的相关描述
This manual page document is from qiuyigui . \fBdn\fR is a common application for create a new file that .c or .h file .
.\"\fB文字\fR:表示将该文字设置成宽体
.\"\fI文字\fR:表示将文字加下划线
.\".:表示为\&.
.SH OPTIONS
.\"说明参数选项设置
It will decide to create a .h file or .c file
.sp
.\".sp:表示空行
.B \-h
It will create a new head file
.sp
.B \-c
It will create a new c file
.sp
.B \-\-help
display this help and exit
.sp
.B \-\-version
output version information and exit
.SH COPYRIGHT
.\":版权声明
\fBdn\fR is Copyright qiuyigui .This program is free  software ,you can redistribute it or modify it under the GNU General Public License as published by the free software foundation .
.SH SEE ALSO
.\":其他参考
This program is a template of c and h files to quickly create .
.SH REPORTING BUGS
.\":漏洞说明
.TP 0
.\".TP n:表示TP标签下的第2行开始缩进n个字符(在第1行超过n字符的前提下) n默认值为7
.\".TP 0:表示Report bugs to <
qiuyigui@126.com> .这一句缩进0个字符,这句即为了实现换行的作用
There probably are some,but I don't know that what they are yet.
Report bugs to <qiuyigui
@gmail.com> .
.SH AUTHOR
.\":文档编写作者
Written by qiuyigui .

.\"看显示创建man手册命令的结果groff -Tascii -man dn.1(注:此时不会创建任务文件,只是看下显示效果)
.\"gzip dn.1 把dn.1压缩成.gz 文件,会创建一个dn.1.gz的文件,而dn.1文件会在gzip执行完后删除
.\"如果想保留原文件可以这样用:gzip -c dn.1 > dn.1.gz
.\"把文件dn.1.gz放到/usr/share/man/man1下就可以完成dn命令的man手册了
.\"当执行man dn后还会在在/var/cache/man/cat1/dn.1.bz2创建一个dn.1.bz2压缩文件

第三步:创建Makefile,内容如下:

#makefile  
OBJS = dn 
all:$(OBJS)   
CFLAGS = -O -w -ansi      
#CFLAGS = -O -Wall -ansi      
CC = gcc $(CFLAGS) 
 
dn:dn.c   
 @$(CC) -o $@ $?  
 @gzip -c dn.1 > dn.1.gz  
 @mv dn.1.gz /usr/share/man/man1 
#gzip压缩成.gz 文件  
#gzip不加参数时,默认压缩文件时,不保存原来的文件;  
#如gzip create.1 结果只有压缩文件create.1.gz,原文件create.1没有了.  
clean: 
 @ls | grep -v ^makefile$$ | grep -v [.]c$$ | grep -v [.]h$$ | grep -v [.]1$$ | grep -v [.]txt$$ | xargs rm -rf 
#makefile

第四步:Make生成dn二进制执行文件

第五步:实例:

root@ubuntu:/opt/work/dn# ./dn --version
create (free code) 1.01
这是自由软件,相互交流学习可以加入QQ:58114361

由qiuyigui编写

把dn文件放入/usr/bin下可以省去前面的"./"

抱歉!评论已关闭.