linux下简易实现write命令及相应权限位设置

/*
    write用于登录到一台主机上两个用户直接进行通信
    mesg  y/n 用于设置是否接收write的消息
    格式:write username terminal-line
    例如:write 123 tty1    
                write 123 /dev/tty1  此时制定用户与终端进行通信
                write 123 此时程序访问utmp文件,获得获取登录的用户名为123的终端,若终端为多个,则向访问到的最后一个终端发信
    输入EOF字符,终止进程
    
*/
#include <stdio.h>
#include <string.h>
#include <utmp.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#define NUMNAME 30     // 存放终端名的长度
#define NUMMES 50         //接受消息缓冲区的长度
int main(int argc, char* argv[])
{
    char name[NUMNAME]= "";                 //存放用户名
    char writeto[NUMNAME] = "/dev/";     //存放终端名
    struct utmp buf;
    int fd;
    int num, num_utmp, ch;
    char mes[NUMMES];
    num = 0;
    if (argc == 1) {
        fprintf(stderr, "usage: write user [tty]");
        exit(1);
    }
    strcpy(name, argv[1]);
    if (argc == 3) {
    //兼容/dev/tty1 和tty1两种参数模式,做兼容处理
        if (!strncmp(argv[2], writeto, 5))
            strcat(writeto, &argv[2][5]);
        else
            strcat(writeto, argv[2]);
        num++;
    }
    else {
    //遍历utmp文件,获得此时登录机器的用户及终端
        if ((fd = open("/var/run/utmp", O_RDONLY)) == -1) {
            perror("open error");
            exit(1);
        }
        num_utmp = sizeof(struct utmp);
        while (read(fd, &buf, num_utmp) == num_utmp) {
            if (!strcmp (buf.ut_user, name)&&strcmp(buf.ut_line, ":0")) {
                if (num > 0) 
                    writeto[5] = '\0';
                strcat(writeto, buf.ut_line);
                num++;
            }
        }
        close(fd);
    }
    //最后writeto参数均为/dev/tty 种形式
    if (num == 0){
        fprintf(stderr, "no destination:%s\n", name);
        exit(0);
    }
    if (num >1) 
        fprintf(stdout, "more then 1 tty, chose: %s\n", writeto);
        
    if ((fd = open(writeto, O_WRONLY)) == -1) {
        perror("open error");
        exit(1);
    }
    /*
        为相应接受到EOF字符,终止进程,采用getc函数,按字节接收字符,通过write函数,按行写入到目的终端
        若接收'\n' 或EOF,则write一次。EOF同时终止程序
        */
    while (1) {
        for (num =0;num < NUMMES ;num++) {
            ch=getc(stdin);
            mes[num] = ch;
            if (ch == '\n' || ch == EOF)
                break;
        }
        if (ch == EOF) {
            if (num != 0)
                mes[num++] = '\n';
            mes[num] = 'E';
            mes[++num] = 'O';
            mes[++num] = 'F';
            mes[++num] = '\0';
        }
        if (write(fd, mes, num+1) != (num+1)) {
            perror("write error");
            exit(1);
        }
        if (ch == EOF)
            break;
    }    
}

执行文件需要设置权限位,才能和系统提供的write命令,运行结果完全一致。否则,在是否有写权限的问题上存在偏差。

依次执行命令:chown root write 用户ID设置为root

                       chgrp tty write     组ID设置为tty

                       chmod g+s write 组权限设置set-group-ID位


总结:

1、设置权限位,否则程序运行起来与系统wirte命令结果有较大出入。

chmod g+s write 组权限设置set-group-ID位,非常重要

2、字符串如果越界会出现非常奇怪的错误,且很难察觉,所以字符一定预留足够的长度。此处浪费大量时间。


你可能感兴趣的:(linux下简易实现write命令及相应权限位设置)