这个命令行程序的功能是解决在Linux下编写C代码的时候,快速创建.h和.c文件的模板,为了来规范代码。实现这个程序的主要目的是我想熟悉一下命令行程序的编写以及如何自定义自己写的命令的man手册.
这个自定义的命令为create,下面为实现过程:
//create.c
/********************************************************** FileName : create.c FileFunc : Linux下实现.c和.h文件模板 Version : V0.1 Author : Sunrier Date : 2012-06-28 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,"用法:create 选项... 文件... \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如遇到问题,请向 <[email protected]> 报告错误。\n"); } else if( 0==memcmp(argv[1],"--version",strlen(argv[1])) ) { fprintf(stderr,"create (free code) 1.01\n"); fprintf(stderr,"这是自由软件,相互交流学习可以加入QQ群:80060765 \n"); fprintf(stderr,"\n"); fprintf(stderr,"由 Sunrier 编写\n"); } else { fprintf(stderr,"%s:无效选项\"%s\" \n",argv[0],argv[1]); fprintf(stderr,"请尝试执行 \"create --help\" 来获取更多的信息. \n"); } exit (1); } if( 3!=argc ) { fprintf(stderr,"%s:无效选项 \n",argv[0]); fprintf(stderr,"请尝试执行 \"create --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,"请尝试执行 \"create --help\" 来获取更多的信息. \n"); exit(1); } } else { fprintf(stderr,"%s:无效选项\"%s\" \"%s\" \n",argv[0],argv[1],argv[2]); fprintf(stderr,"请尝试执行 \"create --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"); }
//makefile
#makefile OBJS = create all:$(OBJS) CFLAGS = -O -w -ansi #CFLAGS = -O -Wall -ansi CC = gcc $(CFLAGS) create:create.c @$(CC) -o $@ $? @gzip -c create.1 > create.1.gz @mv create.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
下面为实现自定义的create命令的man手册:
//create.1
.\"表示:行首注释 而\":表示在行中的注释 .\":create命令程序手册页的实例 .TH CREATE 1 "2012-06-28" "create 1.01" "User Commands" .\"CREATE:表示标题 .\"1:表示此命令出现在手册页的第几部分,范围为1-8的数字,和定义这个文件名小数点后的数字一致 .\""2012-06-28":表示"2012-06-28"显示在整个页的下中 .\""create 1.01":表示"create 1.01"显示在整个页的左下 .\""User Commands":表示"User Commands"显示在整个页的上中 .\".TH在文件的开始,主要说明标题 .SH NAME .\"说明名称 .\".SH从行首开始,靠左边,宽体 \fBcreate\fR \- A simple demonstration application creates a file that head file or c file . .\"-:表示为\- .SH SYNOPSIS .\"说明语法格式 .B create .\".B:表示宽体,如果本行没有文字,则.B标签的下一行为宽体 \-OPTION... FILE... .SH DESCRIPTION .\"说明本命令或程序等的相关描述 This manual page document is from Sunrier . \fBcreate\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 .\":版权声明 \fBcreate\fR is Copyright Sunrier .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 <[email protected]> .这一句缩进0个字符,这句即为了实现换行的作用 There probably are some,but I don't know that what they are yet. Report bugs to <[email protected]> . .SH AUTHOR .\":文档编写作者 Written by Sunrier . .\"看显示创建man手册命令的结果groff -Tascii -man create.1(注:此时不会创建任务文件,只是看下显示效果) .\"gzip create.1 把create.1压缩成.gz 文件,会创建一个create.1.gz的文件,而create.1文件会在gzip执行完后删除 .\"如果想保留原文件可以这样用:gzip -c create.1 > create.1.gz .\"把文件create.1.gz放到/usr/share/man/man1下就可以完成create命令的man手册了 .\"当执行man create后还会在在/var/cache/man/cat1/create.1.bz2创建一个create.1.bz2压缩文件
[root@localhost Sunrier]# ls
create.1 create.c makefile
[root@localhost Sunrier]# make
[root@localhost Sunrier]#ls
create create.1 create.c makefile
[root@localhost Sunrier]# ./create -h test
[root@localhost Sunrier]# ls
create create.1 create.c makefile test.h
[root@localhost Sunrier]#./create -c test
[root@localhost Sunrier]# ls
create create.1 create.c makefile test.c test.h
[root@localhost Sunrier]# man create
[root@localhost Sunrier]#
注:为了像常用的命令一样使用,可以把create放到可执行bin路径下如/usr/bin,可以用echo $PATH看下当前的系统默认执行路径有哪些!