/*
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、字符串如果越界会出现非常奇怪的错误,且很难察觉,所以字符一定预留足够的长度。此处浪费大量时间。
原文:http://my.oschina.net/u/2313065/blog/475843