运行效果截图:
错误提示:
/* 编译命令:gcc w2.c -o w2
* 使用方法:w2 用户名
* 权限设置:假设编译后得到可执行文件write1,为了使得任意用户均可使用write1,先设置权限
chmod 4755 write1
再将write1拷贝到/bin下
如果u02登录不止一次,则会向所有u02登录的终端发信息
如果u02没有登录,提示错误
不会给root登陆的桌面发信息
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <utmp.h>
#define max_user 10 //最大用户
//声明查找终端函数
void get_tty(char *logname,char tty_for_user[max_user][max_user]);
int main( int ac, char *av[] )
{
int fd[max_user];
char buf[BUFSIZ];
char tty_for_user[max_user][max_user];
//如果使用 char *tty_for_user[max_user];则要修改相应的代码,不然运行时可能出现段错误.(原因就是二维数组与指针数组直接分配空间的差异)....
int i=0;
if ( ac != 2 ){ //判断是否输入用户名
fprintf(stderr,"Message: Please write the logname\n");
exit(1);
}
if(strncmp(av[1],"root",4)==0)//禁止向root发送消息
{
fprintf(stderr,"ERROR: DON'T WRITE TO ROOT\n");
exit(1);
}
get_tty(av[1],tty_for_user);//根据用户名查找终端名
if(tty_for_user[0]==NULL ||strlen(tty_for_user[0])==0 )//
{
printf("Message: The user %s no login \n ",av[1]);
return 0;
}
i=0;
while(i<max_user)
{
if(strlen(tty_for_user[i])==0 )break;
sprintf(buf, "/dev/%s", tty_for_user[i]);
fd[i] = open( buf, O_WRONLY );/*打开设备并且获取相应终端名*/
if ( fd[i] == -1 )
{
perror(buf); //如果有错就显示错误
exit(1);
}
i++;
}
while( fgets(buf, BUFSIZ, stdin) != NULL ) //循环获取用户输入的信息。
{ i=0;
while(i<max_user)
{
if(strlen(tty_for_user[i])==0)break;
//将消息写到相应用户终端屏幕,并判断是否有错误
if ( write(fd[i], buf, strlen(buf)) == -1 )
break;
i++;
}
}
i=0;
while(i<max_user)
{
if(strlen(tty_for_user[i])==0)break;
close( fd[i]);//关闭
}
return 1;
}
/* 使用类似who命令根据用户名查找终端名 */
void get_tty(char *logname,char tty_for_user[max_user][max_user] )
{
static struct utmp utrec;
int utfd;
int i=0;
int namelen = sizeof( utrec.ut_name );
//打开utmp登陆日志
if ( (utfd = open( UTMP_FILE, O_RDONLY )) == -1 )
{
printf ("Message:No user login \n"); return;
}
//获取用户名对应的终端名
while( read( utfd, &utrec, sizeof(utrec)) == sizeof(utrec) )
{
if ( strncmp(logname, utrec.ut_name, namelen ) == 0 )
{
strcpy(tty_for_user[i++],utrec.ut_line);
}
if (i==utfd)break;
}
close(utfd);//关闭
}
运行效果截图:
错误提示: