V10/cmd/write.c
#include <stdio.h>
#include <signal.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utsname.h>
#define MAXPPL 15 /* maximum number of people to whom we can write */
#define TTYSIZ 16 /* path-name size for ttys */
#define UDIRSIZ 8 /* size of fields in utmp */
int num;
int fd[MAXPPL + 1];
char *logname, *mytty, *sysname;
struct utmp ut[MAXPPL + 1];
main(argc, argv)
int argc;
char **argv;
{
int x;
int cleanup();
char inp[BUFSIZ], mesg[BUFSIZ], strm[MAXPPL + 1][TTYSIZ];
char *getlogin(), *ttyname();
struct utsname ourname;
signal(SIGHUP, cleanup);
signal(SIGINT, cleanup);
signal(SIGQUIT, cleanup);
logname = getlogin();
if ((mytty = ttyname(3)) != NULL) {
mytty += 5; /* strip "/dev/" off of tty */
cktty(logname, mytty, 1);
}
uname(&ourname);
sysname = ourname.nodename;
if (argc > MAXPPL + 1 || argc < 2) {
sprintf(mesg, "usage: write person1 [... person%d]\n", MAXPPL);
error(mesg);
}
num = argc - 1;
if ((fd[0] = open("/etc/utmp", 0)) < 0)
error("write: Cannot open /etc/utmp.\n");
while (read(fd[0], &ut[0], sizeof(struct utmp)) == sizeof(struct utmp))
for (x = 1; x <= num; x++)
if (strncmp(ut[0].ut_name, argv[x], UDIRSIZ) == 0 ||
strncmp(ut[0].ut_line, argv[x], UDIRSIZ) == 0)
ut[x] = ut[0];
for (x = 1; x <= num; x++) {
if(ut[x].ut_name[0] == 0){
sprintf(mesg, "write: %s is not on.\n", argv[x]);
error(mesg);
}
if (strcmp(ut[x].ut_line, argv[x]) == 0)
strcpy(ut[x].ut_name, ut[x].ut_line);
cktty(ut[x].ut_name, ut[x].ut_line, 0);
devoftty(strm[x], ut[x].ut_line);
if ((fd[x] = open(strm[x], 1)) < 0) {
sprintf(mesg, "write: Cannot open %s's tty.\n", argv[x]);
error(mesg);
}
}
people(mesg);
for (x = 1; x <= num; x++) {
write(fd[x], "\007\007\007write: ", 10);
write(fd[x], sysname, strlen(sysname));
write(fd[x], "!", 1);
write(fd[x], logname, strlen(logname));
if (mytty) {
write(fd[x], " on ", 4);
write(fd[x], mytty, strlen(mytty));
}
write(fd[x], " to ", 4);
write(fd[x], mesg, strlen(mesg));
write(fd[x], ".\n", 2);
}
if (num > 1)
used();
while (fgets(inp, 512, stdin) != NULL)
if (inp[0] == '!')
shell(inp);
else if (inp[0] == ':')
colon(inp);
else
for (x = 1; x <= num; x++) {
if (num != 1) {
write(fd[x], logname, strlen(logname));
write(fd[x], ": ", 2);
}
write(fd[x], inp, strlen(inp));
}
cleanup();
}
cleanup()
{
int x;
for (x = 1; x <= num; x++) {
write(fd[x], "write: ", 7);
write(fd[x], logname, strlen(logname));
write(fd[x], ": EOF\n", 6);
close(fd[x]);
}
close(fd[0]);
exit(0);
}
people(list)
char *list;
{
int x;
strncpy(list, ut[1].ut_name, UDIRSIZ);
list[UDIRSIZ] = '\0';
if (num > 2) {
for (x = 2; x < num; x++) {
strcat(list, ", ");
strncat(list, ut[x].ut_name, UDIRSIZ);
}
strcat(list, ",");
}
if (num > 1) {
strcat(list, " and ");
strncat(list, ut[num].ut_name, UDIRSIZ);
}
}
shell(str)
char *str;
{
int frkd;
int cleanup();
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if ((frkd = fork()) < 0)
printf("write: Cannot fork.\n");
if (frkd == 0) {
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
execl("/bin/sh", "sh", "-c", str + 1, 0);
exit(0);
}
if (frkd > 0)
wait(0);
signal(SIGINT, cleanup);
signal(SIGQUIT, cleanup);
printf("!\n");
}
colon(arg)
char *arg;
{
char arg1[BUFSIZ], arg2[BUFSIZ];
used();
strcpy(arg1, "\0");
strcpy(arg2, "\0");
sscanf(arg, ":%s %s\n", arg1, arg2);
if (strlen(arg1) <= 1) {
if (strcmp(arg2, "\0") == 0 && (strcmp(arg1, "a") == 0 ||
strcmp(arg1, "d") == 0))
printf("write: missing argument to colon escape.\n");
else
switch(arg1[0]) {
case 'a':
add(arg2);
break;
case 'd':
drop(arg2);
break;
case 'l':
plist();
break;
default:
printf("write: unknown colon escape.\n");
}
}
else
printf("write: unknown colon escape.\n");
}
add(name)
char *name;
{
int x;
char dev[TTYSIZ], list[BUFSIZ];
if (num + 1 > MAXPPL) {
printf("write: too many people.\n");
return;
}
lseek(fd[0], 0L, 0);
while (read(fd[0], &ut[0], sizeof(struct utmp)) == sizeof(struct utmp))
if (strcmp(ut[0].ut_name, name) == 0 ||
strcmp(ut[0].ut_line, name) == 0)
ut[num + 1] = ut[0];
if (strcmp(ut[num + 1].ut_name, "\0") == 0) {
printf("write: %s is not on.\n", name);
return;
}
if (strcmp(ut[num + 1].ut_line, name) == 0)
strcpy(ut[num + 1].ut_name, ut[num + 1].ut_line);
if (cktty(name, ut[num + 1].ut_line, 1))
return;
devoftty(dev, ut[num + 1].ut_line);
if ((fd[num + 1] = open(dev, 1)) < 0) {
printf("write: Cannot open %s's tty.\n", name);
return;
}
num++;
people(list);
write(fd[num], "\007\007\007write: ", 10);
write(fd[num], sysname, strlen(sysname));
write(fd[num], "!", 1);
write(fd[num], logname, strlen(logname));
if (mytty) {
write(fd[num], " on ", 4);
write(fd[num], mytty, strlen(mytty));
}
write(fd[num], " to ", 4);
write(fd[num], list, strlen(list));
write(fd[num], ".\n", 2);
for (x = 1; x < num; x++) {
write(fd[x], "\007\007\007write: ", 10);
write(fd[x], logname, strlen(logname));
if (mytty) {
write(fd[x], " on ", 4);
write(fd[x], mytty, strlen(mytty));
}
write(fd[x], " added ", 7);
write(fd[x], name, strlen(name));
write(fd[x], ".\n", 2);
}
}
drop(name)
char *name;
{
int x;
int place = 0;
for (x = 1; x <= num; x++)
if (strcmp(ut[x].ut_name, name) == 0)
place = x;
if (place == 0)
printf("write: %s is not in the conversation.\n", name);
else {
write(fd[place], "\007\007\007write: ", 10);
write(fd[place], logname, strlen(logname));
if (mytty) {
write(fd[place], " on ", 4);
write(fd[place], mytty, strlen(mytty));
}
write(fd[place], " dropped you.\n", 14);
close(fd[place]);
for (x = place; x <= num; x++) {
fd[x] = fd[x + 1];
ut[x] = ut[x + 1];
}
num--;
for (x = 1; x <= num; x++) {
write(fd[x], "\007\007\007write: ", 10);
write(fd[x], logname, strlen(logname));
if (mytty) {
write(fd[x], " on ", 4);
write(fd[x], mytty, strlen(mytty));
}
write(fd[x], " dropped ", 9);
write(fd[x], name, strlen(name));
write(fd[x], ".\n", 2);
}
}
}
plist()
{
char list[BUFSIZ];
people(list);
if (strlen(list) < 1)
printf("write: You're not talking to anyone.\n");
else
printf("write: You're talking to %s.\n", list);
}
cktty(user, tty, flag)
int flag;
char *user, *tty;
{
char bfr[TTYSIZ], msg[BUFSIZ];
struct stat sbuf;
devoftty(bfr, tty);
if (stat(bfr, &sbuf) < 0) {
sprintf(msg, "write: Cannot stat %s (%s's tty).\n", bfr, user);
if (flag) {
fprintf(stderr, msg);
return(1);
}
error(msg);
}
if (!(sbuf.st_mode & 02)) {
sprintf(msg, "write: %s's tty is protected.\n", user);
if (flag) {
fprintf(stderr, msg);
return(1);
}
error(msg);
}
}
devoftty(buf, tty)
char *buf, *tty;
{
sprintf(buf, "/dev/%s", tty);
buf[13] = 0; /* strlen("/dev/")+8 */
}
error(s)
char *s;
{
fprintf(stderr, s);
exit(1);
}
used()
{
int fd;
char buf[20];
if ((fd = open("/tmp/wacct", 2)) < 0)
return;
sprintf(buf, "%s\n", logname);
lseek(fd, 0L, 2);
write(fd, buf, strlen(buf));
close(fd);
}