xref: /csrg-svn/usr.bin/write/write.c (revision 37937)
122608Sserge #ifndef	lint
2*37937Sbostic static char *sccsid = "@(#)write.c	4.15 05/11/89";
322608Sserge #endif
41169Sbill /*
51169Sbill  * write to another user
61169Sbill  */
71169Sbill 
81169Sbill #include <sys/types.h>
91169Sbill #include <sys/stat.h>
10*37937Sbostic #include <sys/signal.h>
11*37937Sbostic #include <sys/time.h>
121169Sbill #include <utmp.h>
13*37937Sbostic #include <stdio.h>
14*37937Sbostic #include <ctype.h>
15*37937Sbostic #include <paths.h>
161169Sbill 
176202Sroot #define	NMAX	sizeof(ubuf.ut_name)
186202Sroot #define	LMAX	sizeof(ubuf.ut_line)
191169Sbill 
201169Sbill char	*strcat();
211169Sbill char	*strcpy();
221169Sbill struct	utmp ubuf;
231169Sbill int	signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
2422608Sserge char	me[NMAX + 1]	= "???";
251169Sbill char	*him;
261169Sbill char	*mytty;
271169Sbill char	histty[32];
2826068Skarels char	ttybuf[32];
291169Sbill char	*histtya;
301169Sbill char	*ttyname();
311169Sbill char	*rindex();
321169Sbill int	logcnt;
331169Sbill int	eof();
341169Sbill int	timout();
351169Sbill FILE	*tf;
361169Sbill char	*getenv();
371169Sbill 
381169Sbill main(argc, argv)
396202Sroot 	int argc;
406202Sroot 	char *argv[];
411169Sbill {
421169Sbill 	struct stat stbuf;
431169Sbill 	register i;
441169Sbill 	register FILE *uf;
451169Sbill 	int c1, c2;
466202Sroot 	long clock = time(0);
4722703Slepreau 	int suser = getuid() == 0;
4826068Skarels 	int nomesg = 0;
491169Sbill 	struct tm *localtime();
501169Sbill 	struct tm *localclock = localtime( &clock );
511169Sbill 
526202Sroot 	if (argc < 2) {
5322608Sserge 		fprintf(stderr, "Usage: write user [ttyname]\n");
541169Sbill 		exit(1);
551169Sbill 	}
561169Sbill 	him = argv[1];
576202Sroot 	if (argc > 2)
581169Sbill 		histtya = argv[2];
5937042Sbostic 	if ((uf = fopen(_PATH_UTMP, "r")) == NULL) {
6037042Sbostic 		fprintf(stderr, "write: can't read %s\n", _PATH_UTMP);
6126069Skarels 		if (histtya == 0)
6226069Skarels 			exit(10);
631169Sbill 		goto cont;
641169Sbill 	}
651169Sbill 	mytty = ttyname(2);
661169Sbill 	if (mytty == NULL) {
6722608Sserge 		fprintf(stderr, "write: Can't find your tty\n");
681169Sbill 		exit(1);
691169Sbill 	}
706202Sroot 	if (stat(mytty, &stbuf) < 0) {
7122608Sserge 		perror("write: Can't stat your tty");
726202Sroot 		exit(1);
731881Serics 	}
7426857Smckusick 	if ((stbuf.st_mode&020) == 0) {
7522608Sserge 		fprintf(stderr,
7622608Sserge 			"write: You have write permission turned off\n");
7726068Skarels 		if (!suser)
7826068Skarels 			exit(1);
791881Serics 	}
801169Sbill 	mytty = rindex(mytty, '/') + 1;
811169Sbill 	if (histtya) {
8237042Sbostic 		strcpy(histty, _PATH_DEV);
831169Sbill 		strcat(histty, histtya);
841169Sbill 	}
851169Sbill 	while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) {
861799Seric 		if (ubuf.ut_name[0] == '\0')
871799Seric 			continue;
881169Sbill 		if (strcmp(ubuf.ut_line, mytty)==0) {
896202Sroot 			for (i=0; i<NMAX; i++) {
901169Sbill 				c1 = ubuf.ut_name[i];
916202Sroot 				if (c1 == ' ')
921169Sbill 					c1 = 0;
931169Sbill 				me[i] = c1;
946202Sroot 				if (c1 == 0)
951169Sbill 					break;
961169Sbill 			}
971169Sbill 		}
9822608Sserge 		if (him[0] == '-' && him[1] == 0)
9922608Sserge 			goto nomat;
1006202Sroot 		for (i=0; i<NMAX; i++) {
1011169Sbill 			c1 = him[i];
1021169Sbill 			c2 = ubuf.ut_name[i];
1036202Sroot 			if (c1 == 0)
1046202Sroot 				if (c2 == 0 || c2 == ' ')
1051169Sbill 					break;
1066202Sroot 			if (c1 != c2)
1071169Sbill 				goto nomat;
1081169Sbill 		}
10926068Skarels 		if (histtya && strncmp(histtya, ubuf.ut_line,
11026068Skarels 		    sizeof(ubuf.ut_line)))
11126068Skarels 			continue;
1121169Sbill 		logcnt++;
11326068Skarels 		if (histty[0]==0 || nomesg && histtya == 0) {
11437042Sbostic 			strcpy(ttybuf, _PATH_DEV);
11526068Skarels 			strcat(ttybuf, ubuf.ut_line);
11626068Skarels 			if (histty[0]==0)
11726068Skarels 				strcpy(histty, ttybuf);
11826068Skarels 			if (access(ttybuf, 0) < 0 || stat(ttybuf, &stbuf) < 0 ||
11926857Smckusick 			    (stbuf.st_mode&020) == 0)
12026068Skarels 				nomesg++;
12126068Skarels 			else {
12226068Skarels 				strcpy(histty, ttybuf);
12326068Skarels 				nomesg = 0;
12426068Skarels 			}
1251169Sbill 		}
1261169Sbill 	nomat:
1271169Sbill 		;
1281169Sbill 	}
12926069Skarels 	fclose(uf);
13026068Skarels 	if (logcnt==0) {
13126069Skarels 		fprintf(stderr, "write: %s not logged in%s\n", him,
13226069Skarels 			histtya ? " on that tty" : "");
1331169Sbill 		exit(1);
1341169Sbill 	}
1351169Sbill 	if (histtya==0 && logcnt > 1) {
13622608Sserge 		fprintf(stderr,
13722608Sserge 		"write: %s logged in more than once ... writing to %s\n",
13822608Sserge 			him, histty+5);
1391169Sbill 	}
14026069Skarels cont:
1411169Sbill 	if (access(histty, 0) < 0) {
14222608Sserge 		fprintf(stderr, "write: No such tty\n");
1431169Sbill 		exit(1);
1441169Sbill 	}
1451169Sbill 	signal(SIGALRM, timout);
1461169Sbill 	alarm(5);
14726068Skarels 	if ((tf = fopen(histty, "w")) == NULL) {
14826068Skarels 		fprintf(stderr, "write: Permission denied\n");
14926068Skarels 		exit(1);
15026068Skarels 	}
1511169Sbill 	alarm(0);
1521169Sbill 	sigs(eof);
1536202Sroot 	{ char hostname[32];
1546202Sroot 	  gethostname(hostname, sizeof (hostname));
15522608Sserge 	  fprintf(tf,
15622608Sserge 	      "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007",
15722608Sserge 	      me, hostname, mytty, localclock->tm_hour, localclock->tm_min);
15822608Sserge 	fflush(tf);
1596202Sroot 	}
1606202Sroot 	for (;;) {
16122608Sserge 		char buf[BUFSIZ];
16222608Sserge 		register char *bp;
16322608Sserge 		i = read(0, buf, sizeof buf);
1646202Sroot 		if (i <= 0)
1651169Sbill 			eof();
1666202Sroot 		if (buf[0] == '!') {
1671169Sbill 			buf[i] = 0;
1681169Sbill 			ex(buf);
1691169Sbill 			continue;
1701169Sbill 		}
17122608Sserge 		for (bp = buf; --i >= 0; bp++) {
17222608Sserge 			if (*bp == '\n')
17322608Sserge 				putc('\r', tf);
17422608Sserge 
17522608Sserge 			if (!isascii(*bp)) {
17622608Sserge 				putc('M', tf);
17722608Sserge 				putc('-', tf);
17822608Sserge 				*bp = toascii(*bp);
17922608Sserge 			}
18022608Sserge 
18122608Sserge 			if (isprint(*bp) ||
18222608Sserge 			    *bp == ' ' || *bp == '\t' || *bp == '\n') {
18322608Sserge 				putc(*bp, tf);
18422608Sserge 			} else {
18522608Sserge 				putc('^', tf);
18622608Sserge 				putc(*bp ^ 0100, tf);
18722608Sserge 			}
18822608Sserge 
18922608Sserge 			if (*bp == '\n')
19022608Sserge 				fflush(tf);
19122608Sserge 
19222608Sserge 			if (ferror(tf) || feof(tf)) {
19322608Sserge 				printf("\n\007Write failed (%s logged out?)\n",
19422608Sserge 					him);
19522608Sserge 				exit(1);
19622608Sserge 			}
1977401Skre 		}
1981169Sbill 	}
1991169Sbill }
2001169Sbill 
2011169Sbill timout()
2021169Sbill {
2031169Sbill 
20422608Sserge 	fprintf(stderr, "write: Timeout opening their tty\n");
2051169Sbill 	exit(1);
2061169Sbill }
2071169Sbill 
2081169Sbill eof()
2091169Sbill {
2101169Sbill 
2111169Sbill 	fprintf(tf, "EOF\r\n");
2121169Sbill 	exit(0);
2131169Sbill }
2141169Sbill 
2151169Sbill ex(bp)
2166202Sroot 	char *bp;
2171169Sbill {
2181169Sbill 	register i;
2191169Sbill 
2201169Sbill 	sigs(SIG_IGN);
2211169Sbill 	i = fork();
2226202Sroot 	if (i < 0) {
2231169Sbill 		printf("Try again\n");
2241169Sbill 		goto out;
2251169Sbill 	}
2266202Sroot 	if (i == 0) {
22726857Smckusick 		fclose(tf);		/* Close his terminal */
22826857Smckusick 		setgid(getgid());	/* Give up effective group privs */
2291169Sbill 		sigs((int (*)())0);
2306202Sroot 		execl(getenv("SHELL") ?
23137042Sbostic 		    getenv("SHELL") : _PATH_BSHELL, "sh", "-c", bp+1, 0);
2321169Sbill 		exit(0);
2331169Sbill 	}
2346202Sroot 	while (wait((int *)NULL) != i)
2351169Sbill 		;
2361169Sbill 	printf("!\n");
2371169Sbill out:
2381169Sbill 	sigs(eof);
2391169Sbill }
2401169Sbill 
2411169Sbill sigs(sig)
2426202Sroot 	int (*sig)();
2431169Sbill {
2441169Sbill 	register i;
2451169Sbill 
2466202Sroot 	for (i=0; signum[i]; i++)
2476202Sroot 		signal(signum[i], sig);
2481169Sbill }
249