1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
24 /*	  All Rights Reserved  	*/
25 
26 /*
27  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI" 	/* SVr4.0 1.4	*/
32 /*LINTLIBRARY*/
33 
34 #include "c_synonyms.h"
35 #include "libmail.h"
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <utmpx.h>
40 #include <syslog.h>
41 #if !defined(__cplusplus) && !defined(c_plusplus)
42 typedef void (*SIG_PF) (int);
43 #endif
44 #include <unistd.h>
45 #include <signal.h>
46 
47 static SIG_PF catcher(void);
48 
49 static SIG_PF catcher(void)
50 {
51 	/* do nothing, but allow the write() to break */
52 	return (0);
53 }
54 
55 void
56 notify(char *user, char *msg, int check_mesg_y, char *etcdir)
57 {
58 	/* search the utmp file for this user */
59 	SIG_PF old;
60 	unsigned int oldalarm;
61 	struct utmpx utmpx, *putmpx = &utmpx;
62 
63 	setutxent();
64 
65 	/* grab the tty name */
66 	while ((putmpx = getutxent()) != NULL) {
67 		if (strncmp(user, utmpx.ut_name,
68 		    sizeof (utmpx.ut_name)) == 0) {
69 			char tty[sizeof (utmpx.ut_line)+1];
70 			char dev[MAXFILENAME];
71 			FILE *port;
72 			size_t i;
73 			int fd;
74 
75 			for (i = 0; i < sizeof (utmpx.ut_line); i++)
76 				tty[i] = utmpx.ut_line[i];
77 			tty[i] = '\0';
78 
79 			/* stick /dev/ in front */
80 			(void) sprintf(dev, "%s/dev/%s", etcdir, tty);
81 
82 			/* break out if write() to the tty hangs */
83 			old = (SIG_PF)signal(SIGALRM, (SIG_PF)catcher);
84 			oldalarm = alarm(300);
85 
86 			/* check if device is really a tty */
87 			if ((fd = open(dev, O_WRONLY|O_NOCTTY)) == -1) {
88 				(void) fprintf(stderr,
89 				    "Cannot open %s.\n", dev);
90 				continue;
91 			} else {
92 				if (!isatty(fd)) {
93 					(void) fprintf(stderr, "%s in utmpx is "
94 					    "not a tty\n", tty);
95 					openlog("mail", 0, LOG_AUTH);
96 					syslog(LOG_CRIT, "%s in utmp is "
97 					    "not a tty\n", tty);
98 					closelog();
99 					(void) close(fd);
100 					continue;
101 				}
102 			}
103 			(void) close(fd);
104 
105 			/* write to the tty */
106 			port = fopen(dev, "w");
107 			if (port != 0) {
108 				(void) fprintf(port, "\r\n%s\r\n", msg);
109 				(void) fclose(port);
110 			}
111 
112 			/* clean up our alarm */
113 			(void) alarm(0);
114 			(void) signal(SIGALRM, old);
115 			(void) alarm(oldalarm);
116 		}
117 	}
118 	endutxent();
119 }
120