#
#define  ALARM  14
/*
 * write to another user
 */
struct utmp
{
	char	name[8];
	int	ttyno;
	int	fill[3];
};
struct
{
	char	pad[4];
	int	flag;
};
char	me[10]	"???";
char	tty[]	"/dev/ln\0\0";
char	*him;
int	ttyno;
int	mytty;
int	histty;
int	logcnt;
char	buf[512];
int	tf;
int	eof();
int	timout();
main(argc, argv)
char *argv[];
{
	register i,k;
	register struct utmp *p;
	int c1, c2, uf;
	struct{
		char lobyte;
		char hibyte;
	};
	if(argc < 2) {
		prs(1, "usage: write user [lineno]\n");
		exit(1);
	}
	him = argv[1];
	if(argc > 2){
		ttyno.lobyte = argv[2][0];
		ttyno.hibyte = argv[2][1];
	}
	if((uf=open("/etc/utmp",0)) < 0){
		prs(1, "cannot open /etc/utmp\n");
		exit();
	}
	mytty = lnxx(1);
	if(mytty.lobyte == 'x' && mytty.hibyte == 'x'){
		prs(1,"nonexistent line\n");
		exit();
	}
	while((k=read(uf,buf,512)) > 0){
	for(p=buf;(k =- 16) >= 0;p++){
		if(p->name[0] >= 0)continue;
		p->name[0] =& ~0200;
		if(mytty == p->ttyno)
			for(i=0; i<8; i++) {
				c1 = p->name[i];
				if(c1 == ' ')c1 = 0;
				me[i] = c1;
				if(c1 == 0) break;
			}
		if(him[0] != '-' || him[1] != 0)
			for(i=0; i<8; i++) {
				c1 = him[i];
				c2 = p->name[i];
				if(c1 == 0)
					if(c2 == 0 || c2 == ' ') break;
				if(c1 != c2) goto loop;
			}
		logcnt++;
		c1 = p->ttyno;
		if(ttyno != 0 && ttyno != c1) continue;
		if(histty == 0) histty = c1;
	loop:
		;
	}
	}
	close(uf);
	if(ttyno == 0 && logcnt > 1 && *him != '-') 
		printf("%s multiply logged in\nwriting to ln%-2.2s\n",
			him,&histty);
	if(histty == 0) {
		prs(1, him);
		if(logcnt)
			prs(1, " not on that line\n");
		else
			prs(1, " not logged in\n");
		exit(1);
	}
	tty[7] = histty.lobyte;
	tty[8] = histty.hibyte;
	signal(ALARM, timout);
	alarm(5);
	tf = open(tty, 1);
	alarm(0);
	if((tf<0) || (fstat(tf,buf)<0) || 
	((buf->flag & 2) == 0 && getuid())){
		prs(1,"Permission denied\n");
		exit(1);
	}
	sigs(eof);
	prs(tf, "\nMessage from ");
	prs(tf, me);
	write(tf," (ln",4);
	write(tf,&mytty,2);
	write(tf,")...\n",5);
	for(;;) {
		i = read(0, buf, 512);
		if(i <= 0) eof();
		if(buf[0] == '!') {
			buf[i] = 0;
			ex();
			continue;
		}
		write(tf, buf, i);
	}
}
timout()
{
	prs(1, "Timeout opening his line\n");
	exit(1);
}
eof()
{
	prs(tf, "EOT\n");
	exit(0);
}
prs(f, s)
char *s;
{
	register n;
	for(n=0; s[n]; n++);
	write(f, s, n);
}
ex()
{
	register i;
	sigs(1);
	i = fork();
	if(i < 0) {
		prs(1, "Try again\n");
		sigs(eof);
	}
	if(i == 0) {
		sigs(0);
		execl("/bin/sh", "sh", "-c", buf+1, 0);
		exit(0);
	}
	while(wait(buf) != i);
	prs(1, "!\n");
}
sigs(sig)
{
	register i;
	for(i=1; i<4; i++) signal(i,sig);
}
