xref: /csrg-svn/usr.bin/write/write.c (revision 22703)
122608Sserge #ifndef	lint
2*22703Slepreau static char *sccsid = "@(#)write.c	4.10 06/07/85";
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];
271169Sbill char	*histtya;
281169Sbill char	*ttyname();
291169Sbill char	*rindex();
301169Sbill int	logcnt;
311169Sbill int	eof();
321169Sbill int	timout();
331169Sbill FILE	*tf;
341169Sbill char	*getenv();
351169Sbill 
361169Sbill main(argc, argv)
376202Sroot 	int argc;
386202Sroot 	char *argv[];
391169Sbill {
401169Sbill 	struct stat stbuf;
411169Sbill 	register i;
421169Sbill 	register FILE *uf;
431169Sbill 	int c1, c2;
446202Sroot 	long clock = time(0);
45*22703Slepreau 	int suser = getuid() == 0;
461169Sbill 	struct tm *localtime();
471169Sbill 	struct tm *localclock = localtime( &clock );
481169Sbill 
496202Sroot 	if (argc < 2) {
5022608Sserge 		fprintf(stderr, "Usage: write user [ttyname]\n");
511169Sbill 		exit(1);
521169Sbill 	}
531169Sbill 	him = argv[1];
546202Sroot 	if (argc > 2)
551169Sbill 		histtya = argv[2];
561169Sbill 	if ((uf = fopen("/etc/utmp", "r")) == NULL) {
5722608Sserge 		perror("write: Can't open /etc/utmp");
581169Sbill 		goto cont;
591169Sbill 	}
601169Sbill 	mytty = ttyname(2);
611169Sbill 	if (mytty == NULL) {
6222608Sserge 		fprintf(stderr, "write: Can't find your tty\n");
631169Sbill 		exit(1);
641169Sbill 	}
656202Sroot 	if (stat(mytty, &stbuf) < 0) {
6622608Sserge 		perror("write: Can't stat your tty");
676202Sroot 		exit(1);
681881Serics 	}
69*22703Slepreau 	if (!suser && (stbuf.st_mode&02) == 0) {
7022608Sserge 		fprintf(stderr,
7122608Sserge 			"write: You have write permission turned off\n");
726202Sroot 		exit(1);
731881Serics 	}
741169Sbill 	mytty = rindex(mytty, '/') + 1;
751169Sbill 	if (histtya) {
761169Sbill 		strcpy(histty, "/dev/");
771169Sbill 		strcat(histty, histtya);
781169Sbill 	}
791169Sbill 	while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) {
801799Seric 		if (ubuf.ut_name[0] == '\0')
811799Seric 			continue;
821169Sbill 		if (strcmp(ubuf.ut_line, mytty)==0) {
836202Sroot 			for (i=0; i<NMAX; i++) {
841169Sbill 				c1 = ubuf.ut_name[i];
856202Sroot 				if (c1 == ' ')
861169Sbill 					c1 = 0;
871169Sbill 				me[i] = c1;
886202Sroot 				if (c1 == 0)
891169Sbill 					break;
901169Sbill 			}
911169Sbill 		}
9222608Sserge 		if (him[0] == '-' && him[1] == 0)
9322608Sserge 			goto nomat;
946202Sroot 		for (i=0; i<NMAX; i++) {
951169Sbill 			c1 = him[i];
961169Sbill 			c2 = ubuf.ut_name[i];
976202Sroot 			if (c1 == 0)
986202Sroot 				if (c2 == 0 || c2 == ' ')
991169Sbill 					break;
1006202Sroot 			if (c1 != c2)
1011169Sbill 				goto nomat;
1021169Sbill 		}
1031169Sbill 		logcnt++;
1041169Sbill 		if (histty[0]==0) {
1051169Sbill 			strcpy(histty, "/dev/");
1061169Sbill 			strcat(histty, ubuf.ut_line);
1071169Sbill 		}
1081169Sbill 	nomat:
1091169Sbill 		;
1101169Sbill 	}
1111169Sbill cont:
1121169Sbill 	if (logcnt==0 && histty[0]=='\0') {
11322608Sserge 		fprintf(stderr, "write: %s not logged in\n", him);
1141169Sbill 		exit(1);
1151169Sbill 	}
11622608Sserge 	if (uf != NULL)
11722608Sserge 		fclose(uf);
1181169Sbill 	if (histtya==0 && logcnt > 1) {
11922608Sserge 		fprintf(stderr,
12022608Sserge 		"write: %s logged in more than once ... writing to %s\n",
12122608Sserge 			him, histty+5);
1221169Sbill 	}
1236202Sroot 	if (histty[0] == 0) {
1241169Sbill 		printf(him);
1256202Sroot 		if (logcnt)
1261169Sbill 			printf(" not on that tty\n"); else
1271169Sbill 			printf(" not logged in\n");
1281169Sbill 		exit(1);
1291169Sbill 	}
1301169Sbill 	if (access(histty, 0) < 0) {
13122608Sserge 		fprintf(stderr, "write: No such tty\n");
1321169Sbill 		exit(1);
1331169Sbill 	}
1341169Sbill 	signal(SIGALRM, timout);
1351169Sbill 	alarm(5);
1361169Sbill 	if ((tf = fopen(histty, "w")) == NULL)
1371169Sbill 		goto perm;
1381169Sbill 	alarm(0);
1391169Sbill 	if (fstat(fileno(tf), &stbuf) < 0)
1401169Sbill 		goto perm;
141*22703Slepreau 	if (!suser && (stbuf.st_mode&02) == 0)
1421169Sbill 		goto perm;
1431169Sbill 	sigs(eof);
1446202Sroot 	{ char hostname[32];
1456202Sroot 	  gethostname(hostname, sizeof (hostname));
14622608Sserge 	  fprintf(tf,
14722608Sserge 	      "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007",
14822608Sserge 	      me, hostname, mytty, localclock->tm_hour, localclock->tm_min);
14922608Sserge 	fflush(tf);
1506202Sroot 	}
1516202Sroot 	for (;;) {
15222608Sserge 		char buf[BUFSIZ];
15322608Sserge 		register char *bp;
15422608Sserge 		i = read(0, buf, sizeof buf);
1556202Sroot 		if (i <= 0)
1561169Sbill 			eof();
1576202Sroot 		if (buf[0] == '!') {
1581169Sbill 			buf[i] = 0;
1591169Sbill 			ex(buf);
1601169Sbill 			continue;
1611169Sbill 		}
16222608Sserge 		for (bp = buf; --i >= 0; bp++) {
16322608Sserge 			if (*bp == '\n')
16422608Sserge 				putc('\r', tf);
16522608Sserge 
16622608Sserge 			if (!isascii(*bp)) {
16722608Sserge 				putc('M', tf);
16822608Sserge 				putc('-', tf);
16922608Sserge 				*bp = toascii(*bp);
17022608Sserge 			}
17122608Sserge 
17222608Sserge 			if (isprint(*bp) ||
17322608Sserge 			    *bp == ' ' || *bp == '\t' || *bp == '\n') {
17422608Sserge 				putc(*bp, tf);
17522608Sserge 			} else {
17622608Sserge 				putc('^', tf);
17722608Sserge 				putc(*bp ^ 0100, tf);
17822608Sserge 			}
17922608Sserge 
18022608Sserge 			if (*bp == '\n')
18122608Sserge 				fflush(tf);
18222608Sserge 
18322608Sserge 			if (ferror(tf) || feof(tf)) {
18422608Sserge 				printf("\n\007Write failed (%s logged out?)\n",
18522608Sserge 					him);
18622608Sserge 				exit(1);
18722608Sserge 			}
1887401Skre 		}
1891169Sbill 	}
1901169Sbill perm:
19122608Sserge 	fprintf(stderr, "write: Permission denied\n");
1921169Sbill 	exit(1);
1931169Sbill }
1941169Sbill 
1951169Sbill timout()
1961169Sbill {
1971169Sbill 
19822608Sserge 	fprintf(stderr, "write: Timeout opening their tty\n");
1991169Sbill 	exit(1);
2001169Sbill }
2011169Sbill 
2021169Sbill eof()
2031169Sbill {
2041169Sbill 
2051169Sbill 	fprintf(tf, "EOF\r\n");
2061169Sbill 	exit(0);
2071169Sbill }
2081169Sbill 
2091169Sbill ex(bp)
2106202Sroot 	char *bp;
2111169Sbill {
2121169Sbill 	register i;
2131169Sbill 
2141169Sbill 	sigs(SIG_IGN);
2151169Sbill 	i = fork();
2166202Sroot 	if (i < 0) {
2171169Sbill 		printf("Try again\n");
2181169Sbill 		goto out;
2191169Sbill 	}
2206202Sroot 	if (i == 0) {
2211169Sbill 		sigs((int (*)())0);
2226202Sroot 		execl(getenv("SHELL") ?
2236202Sroot 		    getenv("SHELL") : "/bin/sh", "sh", "-c", bp+1, 0);
2241169Sbill 		exit(0);
2251169Sbill 	}
2266202Sroot 	while (wait((int *)NULL) != i)
2271169Sbill 		;
2281169Sbill 	printf("!\n");
2291169Sbill out:
2301169Sbill 	sigs(eof);
2311169Sbill }
2321169Sbill 
2331169Sbill sigs(sig)
2346202Sroot 	int (*sig)();
2351169Sbill {
2361169Sbill 	register i;
2371169Sbill 
2386202Sroot 	for (i=0; signum[i]; i++)
2396202Sroot 		signal(signum[i], sig);
2401169Sbill }
241