xref: /csrg-svn/usr.bin/write/write.c (revision 22608)
1*22608Sserge #ifndef	lint
2*22608Sserge static char *sccsid = "@(#)write.c	4.9 06/07/85";
3*22608Sserge #endif
41169Sbill /*
51169Sbill  * write to another user
61169Sbill  */
71169Sbill 
81169Sbill #include <stdio.h>
9*22608Sserge #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};
23*22608Sserge 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);
451169Sbill 	struct tm *localtime();
461169Sbill 	struct tm *localclock = localtime( &clock );
471169Sbill 
486202Sroot 	if (argc < 2) {
49*22608Sserge 		fprintf(stderr, "Usage: write user [ttyname]\n");
501169Sbill 		exit(1);
511169Sbill 	}
521169Sbill 	him = argv[1];
536202Sroot 	if (argc > 2)
541169Sbill 		histtya = argv[2];
551169Sbill 	if ((uf = fopen("/etc/utmp", "r")) == NULL) {
56*22608Sserge 		perror("write: Can't open /etc/utmp");
571169Sbill 		goto cont;
581169Sbill 	}
591169Sbill 	mytty = ttyname(2);
601169Sbill 	if (mytty == NULL) {
61*22608Sserge 		fprintf(stderr, "write: Can't find your tty\n");
621169Sbill 		exit(1);
631169Sbill 	}
646202Sroot 	if (stat(mytty, &stbuf) < 0) {
65*22608Sserge 		perror("write: Can't stat your tty");
666202Sroot 		exit(1);
671881Serics 	}
681881Serics 	if ((stbuf.st_mode&02) == 0) {
69*22608Sserge 		fprintf(stderr,
70*22608Sserge 			"write: You have write permission turned off\n");
716202Sroot 		exit(1);
721881Serics 	}
731169Sbill 	mytty = rindex(mytty, '/') + 1;
741169Sbill 	if (histtya) {
751169Sbill 		strcpy(histty, "/dev/");
761169Sbill 		strcat(histty, histtya);
771169Sbill 	}
781169Sbill 	while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) {
791799Seric 		if (ubuf.ut_name[0] == '\0')
801799Seric 			continue;
811169Sbill 		if (strcmp(ubuf.ut_line, mytty)==0) {
826202Sroot 			for (i=0; i<NMAX; i++) {
831169Sbill 				c1 = ubuf.ut_name[i];
846202Sroot 				if (c1 == ' ')
851169Sbill 					c1 = 0;
861169Sbill 				me[i] = c1;
876202Sroot 				if (c1 == 0)
881169Sbill 					break;
891169Sbill 			}
901169Sbill 		}
91*22608Sserge 		if (him[0] == '-' && him[1] == 0)
92*22608Sserge 			goto nomat;
936202Sroot 		for (i=0; i<NMAX; i++) {
941169Sbill 			c1 = him[i];
951169Sbill 			c2 = ubuf.ut_name[i];
966202Sroot 			if (c1 == 0)
976202Sroot 				if (c2 == 0 || c2 == ' ')
981169Sbill 					break;
996202Sroot 			if (c1 != c2)
1001169Sbill 				goto nomat;
1011169Sbill 		}
1021169Sbill 		logcnt++;
1031169Sbill 		if (histty[0]==0) {
1041169Sbill 			strcpy(histty, "/dev/");
1051169Sbill 			strcat(histty, ubuf.ut_line);
1061169Sbill 		}
1071169Sbill 	nomat:
1081169Sbill 		;
1091169Sbill 	}
1101169Sbill cont:
1111169Sbill 	if (logcnt==0 && histty[0]=='\0') {
112*22608Sserge 		fprintf(stderr, "write: %s not logged in\n", him);
1131169Sbill 		exit(1);
1141169Sbill 	}
115*22608Sserge 	if (uf != NULL)
116*22608Sserge 		fclose(uf);
1171169Sbill 	if (histtya==0 && logcnt > 1) {
118*22608Sserge 		fprintf(stderr,
119*22608Sserge 		"write: %s logged in more than once ... writing to %s\n",
120*22608Sserge 			him, histty+5);
1211169Sbill 	}
1226202Sroot 	if (histty[0] == 0) {
1231169Sbill 		printf(him);
1246202Sroot 		if (logcnt)
1251169Sbill 			printf(" not on that tty\n"); else
1261169Sbill 			printf(" not logged in\n");
1271169Sbill 		exit(1);
1281169Sbill 	}
1291169Sbill 	if (access(histty, 0) < 0) {
130*22608Sserge 		fprintf(stderr, "write: No such tty\n");
1311169Sbill 		exit(1);
1321169Sbill 	}
1331169Sbill 	signal(SIGALRM, timout);
1341169Sbill 	alarm(5);
1351169Sbill 	if ((tf = fopen(histty, "w")) == NULL)
1361169Sbill 		goto perm;
1371169Sbill 	alarm(0);
1381169Sbill 	if (fstat(fileno(tf), &stbuf) < 0)
1391169Sbill 		goto perm;
1401169Sbill 	if ((stbuf.st_mode&02) == 0)
1411169Sbill 		goto perm;
1421169Sbill 	sigs(eof);
1436202Sroot 	{ char hostname[32];
1446202Sroot 	  gethostname(hostname, sizeof (hostname));
145*22608Sserge 	  fprintf(tf,
146*22608Sserge 	      "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007",
147*22608Sserge 	      me, hostname, mytty, localclock->tm_hour, localclock->tm_min);
148*22608Sserge 	fflush(tf);
1496202Sroot 	}
1506202Sroot 	for (;;) {
151*22608Sserge 		char buf[BUFSIZ];
152*22608Sserge 		register char *bp;
153*22608Sserge 		i = read(0, buf, sizeof buf);
1546202Sroot 		if (i <= 0)
1551169Sbill 			eof();
1566202Sroot 		if (buf[0] == '!') {
1571169Sbill 			buf[i] = 0;
1581169Sbill 			ex(buf);
1591169Sbill 			continue;
1601169Sbill 		}
161*22608Sserge 		for (bp = buf; --i >= 0; bp++) {
162*22608Sserge 			if (*bp == '\n')
163*22608Sserge 				putc('\r', tf);
164*22608Sserge 
165*22608Sserge 			if (!isascii(*bp)) {
166*22608Sserge 				putc('M', tf);
167*22608Sserge 				putc('-', tf);
168*22608Sserge 				*bp = toascii(*bp);
169*22608Sserge 			}
170*22608Sserge 
171*22608Sserge 			if (isprint(*bp) ||
172*22608Sserge 			    *bp == ' ' || *bp == '\t' || *bp == '\n') {
173*22608Sserge 				putc(*bp, tf);
174*22608Sserge 			} else {
175*22608Sserge 				putc('^', tf);
176*22608Sserge 				putc(*bp ^ 0100, tf);
177*22608Sserge 			}
178*22608Sserge 
179*22608Sserge 			if (*bp == '\n')
180*22608Sserge 				fflush(tf);
181*22608Sserge 
182*22608Sserge 			if (ferror(tf) || feof(tf)) {
183*22608Sserge 				printf("\n\007Write failed (%s logged out?)\n",
184*22608Sserge 					him);
185*22608Sserge 				exit(1);
186*22608Sserge 			}
1877401Skre 		}
1881169Sbill 	}
1891169Sbill perm:
190*22608Sserge 	fprintf(stderr, "write: Permission denied\n");
1911169Sbill 	exit(1);
1921169Sbill }
1931169Sbill 
1941169Sbill timout()
1951169Sbill {
1961169Sbill 
197*22608Sserge 	fprintf(stderr, "write: Timeout opening their tty\n");
1981169Sbill 	exit(1);
1991169Sbill }
2001169Sbill 
2011169Sbill eof()
2021169Sbill {
2031169Sbill 
2041169Sbill 	fprintf(tf, "EOF\r\n");
2051169Sbill 	exit(0);
2061169Sbill }
2071169Sbill 
2081169Sbill ex(bp)
2096202Sroot 	char *bp;
2101169Sbill {
2111169Sbill 	register i;
2121169Sbill 
2131169Sbill 	sigs(SIG_IGN);
2141169Sbill 	i = fork();
2156202Sroot 	if (i < 0) {
2161169Sbill 		printf("Try again\n");
2171169Sbill 		goto out;
2181169Sbill 	}
2196202Sroot 	if (i == 0) {
2201169Sbill 		sigs((int (*)())0);
2216202Sroot 		execl(getenv("SHELL") ?
2226202Sroot 		    getenv("SHELL") : "/bin/sh", "sh", "-c", bp+1, 0);
2231169Sbill 		exit(0);
2241169Sbill 	}
2256202Sroot 	while (wait((int *)NULL) != i)
2261169Sbill 		;
2271169Sbill 	printf("!\n");
2281169Sbill out:
2291169Sbill 	sigs(eof);
2301169Sbill }
2311169Sbill 
2321169Sbill sigs(sig)
2336202Sroot 	int (*sig)();
2341169Sbill {
2351169Sbill 	register i;
2361169Sbill 
2376202Sroot 	for (i=0; signum[i]; i++)
2386202Sroot 		signal(signum[i], sig);
2391169Sbill }
240