xref: /csrg-svn/usr.bin/write/write.c (revision 26069)
122608Sserge #ifndef	lint
2*26069Skarels static char *sccsid = "@(#)write.c	4.12 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];
2726068Skarels 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;
4726068Skarels 	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");
60*26069Skarels 		if (histtya == 0)
61*26069Skarels 			exit(10);
621169Sbill 		goto cont;
631169Sbill 	}
641169Sbill 	mytty = ttyname(2);
651169Sbill 	if (mytty == NULL) {
6622608Sserge 		fprintf(stderr, "write: Can't find your tty\n");
671169Sbill 		exit(1);
681169Sbill 	}
696202Sroot 	if (stat(mytty, &stbuf) < 0) {
7022608Sserge 		perror("write: Can't stat your tty");
716202Sroot 		exit(1);
721881Serics 	}
7326068Skarels 	if ((stbuf.st_mode&02) == 0) {
7422608Sserge 		fprintf(stderr,
7522608Sserge 			"write: You have write permission turned off\n");
7626068Skarels 		if (!suser)
7726068Skarels 			exit(1);
781881Serics 	}
791169Sbill 	mytty = rindex(mytty, '/') + 1;
801169Sbill 	if (histtya) {
811169Sbill 		strcpy(histty, "/dev/");
821169Sbill 		strcat(histty, histtya);
831169Sbill 	}
841169Sbill 	while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) {
851799Seric 		if (ubuf.ut_name[0] == '\0')
861799Seric 			continue;
871169Sbill 		if (strcmp(ubuf.ut_line, mytty)==0) {
886202Sroot 			for (i=0; i<NMAX; i++) {
891169Sbill 				c1 = ubuf.ut_name[i];
906202Sroot 				if (c1 == ' ')
911169Sbill 					c1 = 0;
921169Sbill 				me[i] = c1;
936202Sroot 				if (c1 == 0)
941169Sbill 					break;
951169Sbill 			}
961169Sbill 		}
9722608Sserge 		if (him[0] == '-' && him[1] == 0)
9822608Sserge 			goto nomat;
996202Sroot 		for (i=0; i<NMAX; i++) {
1001169Sbill 			c1 = him[i];
1011169Sbill 			c2 = ubuf.ut_name[i];
1026202Sroot 			if (c1 == 0)
1036202Sroot 				if (c2 == 0 || c2 == ' ')
1041169Sbill 					break;
1056202Sroot 			if (c1 != c2)
1061169Sbill 				goto nomat;
1071169Sbill 		}
10826068Skarels 		if (histtya && strncmp(histtya, ubuf.ut_line,
10926068Skarels 		    sizeof(ubuf.ut_line)))
11026068Skarels 			continue;
1111169Sbill 		logcnt++;
11226068Skarels 		if (histty[0]==0 || nomesg && histtya == 0) {
11326068Skarels 			strcpy(ttybuf, "/dev/");
11426068Skarels 			strcat(ttybuf, ubuf.ut_line);
11526068Skarels 			if (histty[0]==0)
11626068Skarels 				strcpy(histty, ttybuf);
11726068Skarels 			if (access(ttybuf, 0) < 0 || stat(ttybuf, &stbuf) < 0 ||
11826068Skarels 			    (stbuf.st_mode&02) == 0)
11926068Skarels 				nomesg++;
12026068Skarels 			else {
12126068Skarels 				strcpy(histty, ttybuf);
12226068Skarels 				nomesg = 0;
12326068Skarels 			}
1241169Sbill 		}
1251169Sbill 	nomat:
1261169Sbill 		;
1271169Sbill 	}
128*26069Skarels 	fclose(uf);
12926068Skarels 	if (logcnt==0) {
130*26069Skarels 		fprintf(stderr, "write: %s not logged in%s\n", him,
131*26069Skarels 			histtya ? " on that tty" : "");
1321169Sbill 		exit(1);
1331169Sbill 	}
1341169Sbill 	if (histtya==0 && logcnt > 1) {
13522608Sserge 		fprintf(stderr,
13622608Sserge 		"write: %s logged in more than once ... writing to %s\n",
13722608Sserge 			him, histty+5);
1381169Sbill 	}
139*26069Skarels cont:
1401169Sbill 	if (access(histty, 0) < 0) {
14122608Sserge 		fprintf(stderr, "write: No such tty\n");
1421169Sbill 		exit(1);
1431169Sbill 	}
1441169Sbill 	signal(SIGALRM, timout);
1451169Sbill 	alarm(5);
14626068Skarels 	if ((tf = fopen(histty, "w")) == NULL) {
14726068Skarels 		fprintf(stderr, "write: Permission denied\n");
14826068Skarels 		exit(1);
14926068Skarels 	}
1501169Sbill 	alarm(0);
1511169Sbill 	sigs(eof);
1526202Sroot 	{ char hostname[32];
1536202Sroot 	  gethostname(hostname, sizeof (hostname));
15422608Sserge 	  fprintf(tf,
15522608Sserge 	      "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007",
15622608Sserge 	      me, hostname, mytty, localclock->tm_hour, localclock->tm_min);
15722608Sserge 	fflush(tf);
1586202Sroot 	}
1596202Sroot 	for (;;) {
16022608Sserge 		char buf[BUFSIZ];
16122608Sserge 		register char *bp;
16222608Sserge 		i = read(0, buf, sizeof buf);
1636202Sroot 		if (i <= 0)
1641169Sbill 			eof();
1656202Sroot 		if (buf[0] == '!') {
1661169Sbill 			buf[i] = 0;
1671169Sbill 			ex(buf);
1681169Sbill 			continue;
1691169Sbill 		}
17022608Sserge 		for (bp = buf; --i >= 0; bp++) {
17122608Sserge 			if (*bp == '\n')
17222608Sserge 				putc('\r', tf);
17322608Sserge 
17422608Sserge 			if (!isascii(*bp)) {
17522608Sserge 				putc('M', tf);
17622608Sserge 				putc('-', tf);
17722608Sserge 				*bp = toascii(*bp);
17822608Sserge 			}
17922608Sserge 
18022608Sserge 			if (isprint(*bp) ||
18122608Sserge 			    *bp == ' ' || *bp == '\t' || *bp == '\n') {
18222608Sserge 				putc(*bp, tf);
18322608Sserge 			} else {
18422608Sserge 				putc('^', tf);
18522608Sserge 				putc(*bp ^ 0100, tf);
18622608Sserge 			}
18722608Sserge 
18822608Sserge 			if (*bp == '\n')
18922608Sserge 				fflush(tf);
19022608Sserge 
19122608Sserge 			if (ferror(tf) || feof(tf)) {
19222608Sserge 				printf("\n\007Write failed (%s logged out?)\n",
19322608Sserge 					him);
19422608Sserge 				exit(1);
19522608Sserge 			}
1967401Skre 		}
1971169Sbill 	}
1981169Sbill }
1991169Sbill 
2001169Sbill timout()
2011169Sbill {
2021169Sbill 
20322608Sserge 	fprintf(stderr, "write: Timeout opening their tty\n");
2041169Sbill 	exit(1);
2051169Sbill }
2061169Sbill 
2071169Sbill eof()
2081169Sbill {
2091169Sbill 
2101169Sbill 	fprintf(tf, "EOF\r\n");
2111169Sbill 	exit(0);
2121169Sbill }
2131169Sbill 
2141169Sbill ex(bp)
2156202Sroot 	char *bp;
2161169Sbill {
2171169Sbill 	register i;
2181169Sbill 
2191169Sbill 	sigs(SIG_IGN);
2201169Sbill 	i = fork();
2216202Sroot 	if (i < 0) {
2221169Sbill 		printf("Try again\n");
2231169Sbill 		goto out;
2241169Sbill 	}
2256202Sroot 	if (i == 0) {
2261169Sbill 		sigs((int (*)())0);
2276202Sroot 		execl(getenv("SHELL") ?
2286202Sroot 		    getenv("SHELL") : "/bin/sh", "sh", "-c", bp+1, 0);
2291169Sbill 		exit(0);
2301169Sbill 	}
2316202Sroot 	while (wait((int *)NULL) != i)
2321169Sbill 		;
2331169Sbill 	printf("!\n");
2341169Sbill out:
2351169Sbill 	sigs(eof);
2361169Sbill }
2371169Sbill 
2381169Sbill sigs(sig)
2396202Sroot 	int (*sig)();
2401169Sbill {
2411169Sbill 	register i;
2421169Sbill 
2436202Sroot 	for (i=0; signum[i]; i++)
2446202Sroot 		signal(signum[i], sig);
2451169Sbill }
246