xref: /csrg-svn/usr.bin/write/write.c (revision 26068)
122608Sserge #ifndef	lint
2*26068Skarels static char *sccsid = "@(#)write.c	4.11 02/04/86";
322608Sserge #endif
41169Sbill /*
51169Sbill  * write to another user
61169Sbill  */
71169Sbill 
81169Sbill #include <stdio.h>
922608Sserge #include <ctype.h>
101169Sbill #include <sys/types.h>
111169Sbill #include <sys/stat.h>
121169Sbill #include <signal.h>
131169Sbill #include <utmp.h>
1413599Swnj #include <sys/time.h>
151169Sbill 
166202Sroot #define	NMAX	sizeof(ubuf.ut_name)
176202Sroot #define	LMAX	sizeof(ubuf.ut_line)
181169Sbill 
191169Sbill char	*strcat();
201169Sbill char	*strcpy();
211169Sbill struct	utmp ubuf;
221169Sbill int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
2322608Sserge char	me[NMAX + 1]	= "???";
241169Sbill char	*him;
251169Sbill char	*mytty;
261169Sbill char	histty[32];
27*26068Skarels char	ttybuf[32];
281169Sbill char	*histtya;
291169Sbill char	*ttyname();
301169Sbill char	*rindex();
311169Sbill int	logcnt;
321169Sbill int	eof();
331169Sbill int	timout();
341169Sbill FILE	*tf;
351169Sbill char	*getenv();
361169Sbill 
371169Sbill main(argc, argv)
386202Sroot 	int argc;
396202Sroot 	char *argv[];
401169Sbill {
411169Sbill 	struct stat stbuf;
421169Sbill 	register i;
431169Sbill 	register FILE *uf;
441169Sbill 	int c1, c2;
456202Sroot 	long clock = time(0);
4622703Slepreau 	int suser = getuid() == 0;
47*26068Skarels 	int nomesg = 0;
481169Sbill 	struct tm *localtime();
491169Sbill 	struct tm *localclock = localtime( &clock );
501169Sbill 
516202Sroot 	if (argc < 2) {
5222608Sserge 		fprintf(stderr, "Usage: write user [ttyname]\n");
531169Sbill 		exit(1);
541169Sbill 	}
551169Sbill 	him = argv[1];
566202Sroot 	if (argc > 2)
571169Sbill 		histtya = argv[2];
581169Sbill 	if ((uf = fopen("/etc/utmp", "r")) == NULL) {
5922608Sserge 		perror("write: Can't open /etc/utmp");
601169Sbill 		goto cont;
611169Sbill 	}
621169Sbill 	mytty = ttyname(2);
631169Sbill 	if (mytty == NULL) {
6422608Sserge 		fprintf(stderr, "write: Can't find your tty\n");
651169Sbill 		exit(1);
661169Sbill 	}
676202Sroot 	if (stat(mytty, &stbuf) < 0) {
6822608Sserge 		perror("write: Can't stat your tty");
696202Sroot 		exit(1);
701881Serics 	}
71*26068Skarels 	if ((stbuf.st_mode&02) == 0) {
7222608Sserge 		fprintf(stderr,
7322608Sserge 			"write: You have write permission turned off\n");
74*26068Skarels 		if (!suser)
75*26068Skarels 			exit(1);
761881Serics 	}
771169Sbill 	mytty = rindex(mytty, '/') + 1;
781169Sbill 	if (histtya) {
791169Sbill 		strcpy(histty, "/dev/");
801169Sbill 		strcat(histty, histtya);
811169Sbill 	}
821169Sbill 	while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) {
831799Seric 		if (ubuf.ut_name[0] == '\0')
841799Seric 			continue;
851169Sbill 		if (strcmp(ubuf.ut_line, mytty)==0) {
866202Sroot 			for (i=0; i<NMAX; i++) {
871169Sbill 				c1 = ubuf.ut_name[i];
886202Sroot 				if (c1 == ' ')
891169Sbill 					c1 = 0;
901169Sbill 				me[i] = c1;
916202Sroot 				if (c1 == 0)
921169Sbill 					break;
931169Sbill 			}
941169Sbill 		}
9522608Sserge 		if (him[0] == '-' && him[1] == 0)
9622608Sserge 			goto nomat;
976202Sroot 		for (i=0; i<NMAX; i++) {
981169Sbill 			c1 = him[i];
991169Sbill 			c2 = ubuf.ut_name[i];
1006202Sroot 			if (c1 == 0)
1016202Sroot 				if (c2 == 0 || c2 == ' ')
1021169Sbill 					break;
1036202Sroot 			if (c1 != c2)
1041169Sbill 				goto nomat;
1051169Sbill 		}
106*26068Skarels 		if (histtya && strncmp(histtya, ubuf.ut_line,
107*26068Skarels 		    sizeof(ubuf.ut_line)))
108*26068Skarels 			continue;
1091169Sbill 		logcnt++;
110*26068Skarels 		if (histty[0]==0 || nomesg && histtya == 0) {
111*26068Skarels 			strcpy(ttybuf, "/dev/");
112*26068Skarels 			strcat(ttybuf, ubuf.ut_line);
113*26068Skarels 			if (histty[0]==0)
114*26068Skarels 				strcpy(histty, ttybuf);
115*26068Skarels 			if (access(ttybuf, 0) < 0 || stat(ttybuf, &stbuf) < 0 ||
116*26068Skarels 			    (stbuf.st_mode&02) == 0)
117*26068Skarels 				nomesg++;
118*26068Skarels 			else {
119*26068Skarels 				strcpy(histty, ttybuf);
120*26068Skarels 				nomesg = 0;
121*26068Skarels 			}
1221169Sbill 		}
1231169Sbill 	nomat:
1241169Sbill 		;
1251169Sbill 	}
1261169Sbill cont:
127*26068Skarels 	if (logcnt==0) {
12822608Sserge 		fprintf(stderr, "write: %s not logged in\n", him);
1291169Sbill 		exit(1);
1301169Sbill 	}
13122608Sserge 	if (uf != NULL)
13222608Sserge 		fclose(uf);
1331169Sbill 	if (histtya==0 && logcnt > 1) {
13422608Sserge 		fprintf(stderr,
13522608Sserge 		"write: %s logged in more than once ... writing to %s\n",
13622608Sserge 			him, histty+5);
1371169Sbill 	}
138*26068Skarels 	if (logcnt == 0) {
1391169Sbill 		printf(him);
140*26068Skarels 		if (histtya)
141*26068Skarels 			printf(" not on that tty\n");
142*26068Skarels 		else
1431169Sbill 			printf(" not logged in\n");
1441169Sbill 		exit(1);
1451169Sbill 	}
1461169Sbill 	if (access(histty, 0) < 0) {
14722608Sserge 		fprintf(stderr, "write: No such tty\n");
1481169Sbill 		exit(1);
1491169Sbill 	}
1501169Sbill 	signal(SIGALRM, timout);
1511169Sbill 	alarm(5);
152*26068Skarels 	if ((tf = fopen(histty, "w")) == NULL) {
153*26068Skarels 		fprintf(stderr, "write: Permission denied\n");
154*26068Skarels 		exit(1);
155*26068Skarels 	}
1561169Sbill 	alarm(0);
1571169Sbill 	sigs(eof);
1586202Sroot 	{ char hostname[32];
1596202Sroot 	  gethostname(hostname, sizeof (hostname));
16022608Sserge 	  fprintf(tf,
16122608Sserge 	      "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007",
16222608Sserge 	      me, hostname, mytty, localclock->tm_hour, localclock->tm_min);
16322608Sserge 	fflush(tf);
1646202Sroot 	}
1656202Sroot 	for (;;) {
16622608Sserge 		char buf[BUFSIZ];
16722608Sserge 		register char *bp;
16822608Sserge 		i = read(0, buf, sizeof buf);
1696202Sroot 		if (i <= 0)
1701169Sbill 			eof();
1716202Sroot 		if (buf[0] == '!') {
1721169Sbill 			buf[i] = 0;
1731169Sbill 			ex(buf);
1741169Sbill 			continue;
1751169Sbill 		}
17622608Sserge 		for (bp = buf; --i >= 0; bp++) {
17722608Sserge 			if (*bp == '\n')
17822608Sserge 				putc('\r', tf);
17922608Sserge 
18022608Sserge 			if (!isascii(*bp)) {
18122608Sserge 				putc('M', tf);
18222608Sserge 				putc('-', tf);
18322608Sserge 				*bp = toascii(*bp);
18422608Sserge 			}
18522608Sserge 
18622608Sserge 			if (isprint(*bp) ||
18722608Sserge 			    *bp == ' ' || *bp == '\t' || *bp == '\n') {
18822608Sserge 				putc(*bp, tf);
18922608Sserge 			} else {
19022608Sserge 				putc('^', tf);
19122608Sserge 				putc(*bp ^ 0100, tf);
19222608Sserge 			}
19322608Sserge 
19422608Sserge 			if (*bp == '\n')
19522608Sserge 				fflush(tf);
19622608Sserge 
19722608Sserge 			if (ferror(tf) || feof(tf)) {
19822608Sserge 				printf("\n\007Write failed (%s logged out?)\n",
19922608Sserge 					him);
20022608Sserge 				exit(1);
20122608Sserge 			}
2027401Skre 		}
2031169Sbill 	}
2041169Sbill }
2051169Sbill 
2061169Sbill timout()
2071169Sbill {
2081169Sbill 
20922608Sserge 	fprintf(stderr, "write: Timeout opening their tty\n");
2101169Sbill 	exit(1);
2111169Sbill }
2121169Sbill 
2131169Sbill eof()
2141169Sbill {
2151169Sbill 
2161169Sbill 	fprintf(tf, "EOF\r\n");
2171169Sbill 	exit(0);
2181169Sbill }
2191169Sbill 
2201169Sbill ex(bp)
2216202Sroot 	char *bp;
2221169Sbill {
2231169Sbill 	register i;
2241169Sbill 
2251169Sbill 	sigs(SIG_IGN);
2261169Sbill 	i = fork();
2276202Sroot 	if (i < 0) {
2281169Sbill 		printf("Try again\n");
2291169Sbill 		goto out;
2301169Sbill 	}
2316202Sroot 	if (i == 0) {
2321169Sbill 		sigs((int (*)())0);
2336202Sroot 		execl(getenv("SHELL") ?
2346202Sroot 		    getenv("SHELL") : "/bin/sh", "sh", "-c", bp+1, 0);
2351169Sbill 		exit(0);
2361169Sbill 	}
2376202Sroot 	while (wait((int *)NULL) != i)
2381169Sbill 		;
2391169Sbill 	printf("!\n");
2401169Sbill out:
2411169Sbill 	sigs(eof);
2421169Sbill }
2431169Sbill 
2441169Sbill sigs(sig)
2456202Sroot 	int (*sig)();
2461169Sbill {
2471169Sbill 	register i;
2481169Sbill 
2496202Sroot 	for (i=0; signum[i]; i++)
2506202Sroot 		signal(signum[i], sig);
2511169Sbill }
252