linux whoami cp mv mesg 命令 c语言实现(部分功能)

来源:互联网 发布:淘宝商品标题怎么优化 编辑:程序博客网 时间:2024/05/29 03:17

命令没有实现全部功能,只是初学时为了练习linux中的C语言函数。(有错误请指出,我会及时改正。有不足之处请说明)

whoami实现

#include<stdio.h>#include<pwd.h>#include<sys/types.h>#include<unistd.h>int main(){uid_t id;struct passwd * pa;id=geteuid();pa=getpwuid(id);printf("%d\n",id);printf("%s\n",pa->pw_name);return 0;}
cp实现

/*#define S_ISDIR(x)  (((x)&STAT_MASK)==STAT_DIR_FLAG)STAT_MASK         001000001010STAT_DIR_FLAG   001000000000*/#include<stdio.h>#include<unistd.h> //close#include<fcntl.h> //open#include <sys/stat.h>#include <string.h>#include<utime.h>//use to change time//int utime(const char *filename,struct utimbuf *buf);#define BUFSIZE 4096#define COPYMODE 0644 //文件许可位 permission bit void oops(char * sl,char * s2) {fprintf(stderr,"Error: %s ",sl);perror(s2);  //传来一个文件地址,然后让它判断错误原因。exit(1);}main(int ac,char *av[]){int in_fd,out_fd,n_chars;char buf[BUFSIZE];struct stat st;struct utimbuf  utbuf;if(ac!=3){fprintf(stderr,"usage: %s source destination\n",*av);printf("your parameters are not enough\n");exit(1);}if( (in_fd=open(av[1],O_RDONLY)) == -1 ){oops("Cannot open ",av[1]);}if( (out_fd=creat(av[2],COPYMODE)) == -1 ){//实现了输入目录也可以复制。 但是字符串的截取复杂****************if(stat(av[2],&st)!=-1){if(S_ISDIR(st.st_mode)){char tp[100];int i,j=0;for(i=strlen(av[1])-1;i>=0;i--){if(av[1][i]=='/')break;}for(i++;i<strlen(av[1]);i++){tp[j++]=av[1][i];}tp[j]='\0';//strncpy(av[2]+strlen(av[2]),"/\0",2);//strcpy(av[2]+strlen(av[2]),av[1] );strcpy(av[2]+strlen(av[2]),tp);strncpy(av[2]+strlen(av[2]),"\0",1);if( (out_fd=creat(av[2],COPYMODE)) == -1 ){     oops("Cannot creat ",av[2]);}}}else  oops("Cannot creat ",av[2]);}if(stat(av[1],&st)==-1){oops("Cannot read ",av[1]);}while( (n_chars = read(in_fd,buf,BUFSIZE))>0 ){if( write(out_fd,buf,n_chars)!=n_chars ){oops("write error to",av[2]);}}if( n_chars == -1){oops("Read error from",av[1]);}if((close(out_fd) == -1) | (close(in_fd)== -1)){oops("Error closing files ","");}utbuf.actime=st.st_atime;utbuf.modtime=st.st_mtime;if(-1==utime(av[2],&utbuf)){oops("Error changing time ","");}        printf("Copy has finished,you can use 'ls' to see it\n");}/*st_atime  文件数据的最后存取时间       read            -u st_mtime  文件数据的最后修改时间       write           缺省 st_ctime  文件属性的最后更改时间       chown,chmod     -c*/


mv实现:

#include<stdio.h>#include<unistd.h>#include<sys/stat.h>#include<string.h>#include<stdlib.h>char * getFileName(char * fileName){char tp[100],*nm=(char*)malloc(sizeof(char));int i,j=0;for(i=strlen(fileName)-1;i>=0;i--){if(fileName[i]=='/')break;}for(i++;i<strlen(fileName);i++){tp[j++]=fileName[i];}tp[j]='\0';strcpy(nm,tp);/* strcpy(nm,fileName);strcpy(nm+strlen(nm),tp);strncpy(nm+strlen(nm),"\0",1);*/return nm;}int main(int ac,char * av[]){struct stat st;if(ac!=3){fprintf(stderr,"usage: %s source destination not found\n",*av);}if(stat(av[1],&st)==-1 || S_ISDIR(st.st_mode)){printf("source is not a file");exit(1);}if(stat(av[2],&st)!=-1){//查看是不是目录 if(S_ISDIR(st.st_mode)){strcpy(av[2]+strlen(av[2]),"/");strcpy(av[2]+strlen(av[2]),getFileName(av[1]));strcpy(av[2]+strlen(av[2]),"\0");}else{printf("destination file is already exist\n");//exit(1);  不可以退出,真正的linux也不会出现提示。**********************已改}}/*光下面一个函数就可以实现  复制包含目录的文件,但是如果 第二个参数是目录的话会失败的,所以要处理 .用link如果目标目录文件存在就会失败,不许创建而linux中mv与cp都是可以覆盖目标文件的。*/if(rename(av[1],av[2])==-1){printf("error!\n");}/*if(link(av[1],av[2])!=-1) {unlink(av[1]);}else{printf("link error\n");}*/return 1;}


mesg实现

#include    <unistd.h>#include    <sys/stat.h>#include    <stdio.h>#include    <errno.h>#include    <string.h>#include    <stdlib.h>int main(int argc, char *argv[]){    struct stat    st;    char    *tty;    tty = ttyname(STDERR_FILENO);    if(tty == NULL){        exit(1);    }    if(stat(tty, &st) == -1){        exit(1);    }    if(argc == 1){        if(st.st_mode & S_IWGRP)            printf("is y\n");        else            printf("is n\n");        return 0;    }    switch(argv[1][0]){    case 'y':        if(chmod(tty, st.st_mode | S_IWGRP) == -1)            fprintf(stderr, "cannot set '%s': %s\n",tty, strerror(errno));        break;    case 'n':        if(chmod(tty, st.st_mode & ~S_IWGRP) == -1)            fprintf(stderr, "cannot set '%s': %s\n", tty, strerror(errno));        break;    default: ;    }    return 0;    }    /*主要代码参考网址:http://www.cnblogs.com/mcnns/archive/2012/12/20/2826176.html所用知识简介参考网址:http://baike.baidu.com/view/8031097.htmhttp://baike.baidu.com/link?url=o1UFivoW3f4RUs5LpY8SaWYIBSPGyn_FpKdI3jC5HYzbyLoKGA2DSL0zBuDgMF0Fhttp://blog.csdn.net/novrose/article/details/6947868http://baike.baidu.com/view/568600.htmhttp://baike.baidu.com/view/1229012.htmhttp://linux.chinaunix.net/techdoc/system/2009/07/04/1121929.shtmlchar *strchr(char* _Str,int _Ch)头文件:#include <string.h>功能:查找字符串s中首次出现字符c的位置说明:返回首次出现c的位置的指针,返回的地址是字符串在内存中随机分配的地址再加上你所搜索的字符在字符串位置,如果s中不存在c则返回NULL。//////////////////////stdin, stdout, stderr类型为 FILE* STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO类型为 int 使用stdin的函数主要有:fread、fwrite、fclose等,是文件流方式。属于高级IO,带缓冲的。 使用STDIN_FILENO的函数有:read、write、close等, 属于低级IO,要自己处理缓冲。 通常守护进程在后台运行,所以要将它的标准输入输出重定向到/dev/null。 fd = open("/dev/null", O_RDONLY); if(fd != -1){ dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if(fd > 2){ 就是除了标准输入,输出和错误,其他的都关闭啊close(fd); } }函数名: dup2功能: 复制文件句柄用法: int dup2(int oldhandle,int newhandle);///////////////////////////////头文件#include<unistd.h>2函数原型char * ttyname(int desc);用法举例char * file = “/dev/tty”;fd = open (fiel,O_RDONLY);if(isatty(fd)){printf(“is a tty.\n”);printf(“ttyname = %s \n”,ttyname(fd));}else printf(“ is not a tty\n”);close(fd);////////////////////////////////函数名: stat()功 能: 得到文件的信息,将其保存在buf结构中,buf的地址以参数形式传递给stat。用 法: int _stat(const char *path,struct _stat *buffer)参数:const char *path: 文件名或者目录名struct _stat *buffer:结构体对象地址返回值: 返回-1表示失败。stat 结构定义于:/usr/include/sys/stat.h 文件中struct stat finfo;stat( sFileName, &finfo );int size = finfo. st_size;struct statmode_t st_mode; //文件对应的模式,文件,目录等ino_t st_ino; //i-node节点号dev_t st_dev; //设备号码dev_t st_rdev; //特殊设备号码nlink_t st_nlink; //文件的连接数uid_t st_uid; //文件所有者gid_t st_gid; //文件所有者对应的组off_t st_size; //普通文件,对应的文件字节数time_t st_atime; //文件最后被访问的时间time_t st_mtime; //文件内容最后被修改的时间time_t st_ctime; //文件状态(属性)改变时间blksize_t st_blksize; //文件内容对应的块大小blkcnt_t st_blocks; //文件内容对应的块数量////////////////////////////////函数名称:[1]chmod函数原型:int chmod( const char *filename, int pmode );所属库:stdio.h函数功能:改变文件的读写许可设置,如果改变成功返回0,否则返回-1chmod函数的定义: #include #include int chmod(const char *path, mode_t mode)关于mode_t的定义:#ifndef __mode_t_definedtypedef __mode_t mode_t;# define __mode_t_defined#endif__mode_t的定义:#define __mode_t __MODE_T_TYPE#define __MODE_T_TYPE __U32_TYPE#define __U32_TYPE unsigned int可以看到mode_t的定义实际就是unsigned int形式的。   但是函数chmod(const char *path, mode_t mode)在解释mode_t时是将这里的mode当成8进制的去解释。参数 mode 有下列数种组合S_ISUID 04000 文件的(set user-id on execution)位S_ISGID 02000 文件的(set group-id on execution)位S_ISVTX 01000 文件的sticky位S_IRUSR(S_IREAD) 00400 文件所有者具可读取权限S_IWUSR(S_IWRITE)00200 文件所有者具可写入权限 S_IXUSR(S_IEXEC) 00100 文件所有者具可执行权限S_IRGRP 00040 用户组具可读取权限S_IWGRP 00020 用户组具可写入权限S_IXGRP 00010 用户组具可执行权限S_IROTH 00004 其他用户具可读取权限S_IWOTH 00002 其他用户具可写入权限S_IXOTH 00001 其他用户具可执行权限比如要将文件test的权限修改为644,那么可以采用以下几种方法:chmod("test", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);chmod("test", 0644);chmod("test", 420);   第一种方法是将00400和00200和00040和00004进行或运算,最终得到的结果就是0644(八进制),而八进制的0644就等于十进制的420。所以上面三种方法是等效的。   当我们给chmod函数传递参数时他会将对应的十进制的mode参数转换为相应的八进制进行运算。所以我们要将test文件的权限改为644时传递给函数chmod的参数不能直接是644。而应该是420。这是因为十进制的420就等于八进制的644。   但是我们使用chmod命令时却可以直接输入644。具体的chmod实现时我认为是将644接收后(接收时可能是以字符串形式接收)认为644是八进制的数据,然后将644转换为对应的十进制,然后直接传递给函数chmod(const char *path, mode_t mode)。*/