xref: /titanic_53/usr/src/cmd/wall/wall.c (revision de6baaf51812fba698b0a3cdfb5c6c0bf3d52960)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
237c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * Copyright 1988-2003 Sun Microsystems, Inc.  All rights reserved.
297c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
32*de6baaf5SJohn Sonnenschein /*
33*de6baaf5SJohn Sonnenschein  * Copyright 2012 Joyent, Inc. All rights reserved.
34*de6baaf5SJohn Sonnenschein  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <signal.h>
377c478bd9Sstevel@tonic-gate #include <stdio.h>
38*de6baaf5SJohn Sonnenschein #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <grp.h>
407c478bd9Sstevel@tonic-gate #include <sys/types.h>
417c478bd9Sstevel@tonic-gate #include <unistd.h>
427c478bd9Sstevel@tonic-gate #include <string.h>
437c478bd9Sstevel@tonic-gate #include <ctype.h>
447c478bd9Sstevel@tonic-gate #include <sys/stat.h>
457c478bd9Sstevel@tonic-gate #include <utmpx.h>
467c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
477c478bd9Sstevel@tonic-gate #include <dirent.h>
487c478bd9Sstevel@tonic-gate #include <pwd.h>
497c478bd9Sstevel@tonic-gate #include <fcntl.h>
507c478bd9Sstevel@tonic-gate #include <time.h>
517c478bd9Sstevel@tonic-gate #include <errno.h>
527c478bd9Sstevel@tonic-gate #include <locale.h>
537c478bd9Sstevel@tonic-gate #include <syslog.h>
547c478bd9Sstevel@tonic-gate #include <sys/wait.h>
557c478bd9Sstevel@tonic-gate #include <limits.h>
56*de6baaf5SJohn Sonnenschein #include <libzonecfg.h>
57*de6baaf5SJohn Sonnenschein #include <zone.h>
58*de6baaf5SJohn Sonnenschein #include <sys/contract/process.h>
59*de6baaf5SJohn Sonnenschein #include <libcontract.h>
60*de6baaf5SJohn Sonnenschein #include <sys/ctfs.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate  * utmpx defines wider fields for user and line.  For compatibility of output,
647c478bd9Sstevel@tonic-gate  * we are limiting these to the old maximums in utmp. Define UTMPX_NAMELEN
657c478bd9Sstevel@tonic-gate  * to use the full lengths.
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate #ifndef UTMPX_NAMELEN
687c478bd9Sstevel@tonic-gate /* XXX - utmp -fix name length */
697c478bd9Sstevel@tonic-gate #define	NMAX	(_POSIX_LOGIN_NAME_MAX - 1)
707c478bd9Sstevel@tonic-gate #define	LMAX	12
717c478bd9Sstevel@tonic-gate #else /* UTMPX_NAMELEN */
727c478bd9Sstevel@tonic-gate #define	NMAX	(sizeof (((struct utmpx *)0)->ut_user)
737c478bd9Sstevel@tonic-gate #define	LMAX	(sizeof (((struct utmpx *)0)->ut_line)
747c478bd9Sstevel@tonic-gate #endif /* UTMPX_NAMELEN */
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static char	mesg[3000];
777c478bd9Sstevel@tonic-gate static char	*infile;
787c478bd9Sstevel@tonic-gate static int	gflag;
797c478bd9Sstevel@tonic-gate static struct	group *pgrp;
807c478bd9Sstevel@tonic-gate static char	*grpname;
817c478bd9Sstevel@tonic-gate static char	line[MAXNAMLEN+1] = "???";
827c478bd9Sstevel@tonic-gate static char	systm[MAXNAMLEN+1];
837c478bd9Sstevel@tonic-gate static time_t	tloc;
847c478bd9Sstevel@tonic-gate static struct	utsname utsn;
857c478bd9Sstevel@tonic-gate static char	who[9]	= "???";
867c478bd9Sstevel@tonic-gate static char	time_buf[50];
877c478bd9Sstevel@tonic-gate #define	DATE_FMT	"%a %b %e %H:%M:%S"
887c478bd9Sstevel@tonic-gate 
89*de6baaf5SJohn Sonnenschein static void sendmes(struct utmpx *, zoneid_t);
90*de6baaf5SJohn Sonnenschein static void sendmes_tozone(zoneid_t, int);
917c478bd9Sstevel@tonic-gate static int chkgrp(char *);
927c478bd9Sstevel@tonic-gate static char *copy_str_till(char *, char *, char, int);
937c478bd9Sstevel@tonic-gate 
94*de6baaf5SJohn Sonnenschein static int init_template(void);
95*de6baaf5SJohn Sonnenschein int contract_abandon_id(ctid_t);
96*de6baaf5SJohn Sonnenschein 
977c478bd9Sstevel@tonic-gate int
987c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	FILE	*f;
1017c478bd9Sstevel@tonic-gate 	char	*ptr, *start;
1027c478bd9Sstevel@tonic-gate 	struct	passwd *pwd;
1037c478bd9Sstevel@tonic-gate 	char	*term_name;
1047c478bd9Sstevel@tonic-gate 	int	c;
1057c478bd9Sstevel@tonic-gate 	int	aflag = 0;
1067c478bd9Sstevel@tonic-gate 	int	errflg = 0;
107*de6baaf5SJohn Sonnenschein 	int zflg = 0;
108*de6baaf5SJohn Sonnenschein 	int Zflg = 0;
109*de6baaf5SJohn Sonnenschein 
110*de6baaf5SJohn Sonnenschein 	char *zonename = NULL;
111*de6baaf5SJohn Sonnenschein 	zoneid_t *zoneidlist = NULL;
112*de6baaf5SJohn Sonnenschein 	uint_t nzids_saved, nzids = 0;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1157c478bd9Sstevel@tonic-gate 
116*de6baaf5SJohn Sonnenschein 	while ((c = getopt(argc, argv, "g:az:Z")) != EOF)
1177c478bd9Sstevel@tonic-gate 		switch (c) {
1187c478bd9Sstevel@tonic-gate 		case 'a':
1197c478bd9Sstevel@tonic-gate 			aflag++;
1207c478bd9Sstevel@tonic-gate 			break;
1217c478bd9Sstevel@tonic-gate 		case 'g':
1227c478bd9Sstevel@tonic-gate 			if (gflag) {
1237c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1247c478bd9Sstevel@tonic-gate 				    "Only one group allowed\n");
125*de6baaf5SJohn Sonnenschein 				return (1);
1267c478bd9Sstevel@tonic-gate 			}
1277c478bd9Sstevel@tonic-gate 			if ((pgrp = getgrnam(grpname = optarg)) == NULL) {
1287c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "Unknown group %s\n",
1297c478bd9Sstevel@tonic-gate 				    grpname);
130*de6baaf5SJohn Sonnenschein 				return (1);
1317c478bd9Sstevel@tonic-gate 			}
1327c478bd9Sstevel@tonic-gate 			gflag++;
1337c478bd9Sstevel@tonic-gate 			break;
134*de6baaf5SJohn Sonnenschein 		case 'z':
135*de6baaf5SJohn Sonnenschein 			zflg++;
136*de6baaf5SJohn Sonnenschein 			zonename = optarg;
137*de6baaf5SJohn Sonnenschein 			if (getzoneidbyname(zonename) == -1) {
138*de6baaf5SJohn Sonnenschein 				(void) fprintf(stderr, "Specified zone %s "
139*de6baaf5SJohn Sonnenschein 				    "is invalid", zonename);
140*de6baaf5SJohn Sonnenschein 				return (1);
141*de6baaf5SJohn Sonnenschein 			}
142*de6baaf5SJohn Sonnenschein 			break;
143*de6baaf5SJohn Sonnenschein 		case 'Z':
144*de6baaf5SJohn Sonnenschein 			Zflg++;
145*de6baaf5SJohn Sonnenschein 			break;
1467c478bd9Sstevel@tonic-gate 		case '?':
1477c478bd9Sstevel@tonic-gate 			errflg++;
1487c478bd9Sstevel@tonic-gate 			break;
1497c478bd9Sstevel@tonic-gate 		}
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	if (errflg) {
1527c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
153*de6baaf5SJohn Sonnenschein 		    "Usage: wall [-a] [-g group] [-z zone] [-Z] [files...]\n");
154*de6baaf5SJohn Sonnenschein 		return (1);
155*de6baaf5SJohn Sonnenschein 	}
156*de6baaf5SJohn Sonnenschein 
157*de6baaf5SJohn Sonnenschein 	if (zflg && Zflg) {
158*de6baaf5SJohn Sonnenschein 		(void) fprintf(stderr, "Cannot use -z with -Z\n");
1597c478bd9Sstevel@tonic-gate 		return (1);
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	if (optind < argc)
1637c478bd9Sstevel@tonic-gate 		infile = argv[optind];
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	if (uname(&utsn) == -1) {
1667c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "wall: uname() failed, %s\n",
1677c478bd9Sstevel@tonic-gate 		    strerror(errno));
168*de6baaf5SJohn Sonnenschein 		return (2);
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 	(void) strcpy(systm, utsn.nodename);
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	/*
1737c478bd9Sstevel@tonic-gate 	 * Get the name of the terminal wall is running from.
1747c478bd9Sstevel@tonic-gate 	 */
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	if ((term_name = ttyname(fileno(stderr))) != NULL) {
1777c478bd9Sstevel@tonic-gate 		/*
1787c478bd9Sstevel@tonic-gate 		 * skip the leading "/dev/" in term_name
1797c478bd9Sstevel@tonic-gate 		 */
1807c478bd9Sstevel@tonic-gate 		(void) strncpy(line, &term_name[5], sizeof (line) - 1);
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	if (who[0] == '?') {
1847c478bd9Sstevel@tonic-gate 		if (pwd = getpwuid(getuid()))
1857c478bd9Sstevel@tonic-gate 			(void) strncpy(&who[0], pwd->pw_name, sizeof (who));
1867c478bd9Sstevel@tonic-gate 	}
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	f = stdin;
1897c478bd9Sstevel@tonic-gate 	if (infile) {
1907c478bd9Sstevel@tonic-gate 		f = fopen(infile, "r");
1917c478bd9Sstevel@tonic-gate 		if (f == NULL) {
1927c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Cannot open %s\n", infile);
193*de6baaf5SJohn Sonnenschein 			return (1);
1947c478bd9Sstevel@tonic-gate 		}
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	start = &mesg[0];
1987c478bd9Sstevel@tonic-gate 	ptr = start;
1997c478bd9Sstevel@tonic-gate 	while ((ptr - start) < 3000) {
2007c478bd9Sstevel@tonic-gate 		size_t n;
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 		if (fgets(ptr, &mesg[sizeof (mesg)] - ptr, f) == NULL)
2037c478bd9Sstevel@tonic-gate 			break;
2047c478bd9Sstevel@tonic-gate 		if ((n = strlen(ptr)) == 0)
2057c478bd9Sstevel@tonic-gate 			break;
2067c478bd9Sstevel@tonic-gate 		ptr += n;
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 	(void) fclose(f);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/*
2117c478bd9Sstevel@tonic-gate 	 * If the request is from the rwall daemon then use the caller's
2127c478bd9Sstevel@tonic-gate 	 * name and host.  We determine this if all of the following is true:
2137c478bd9Sstevel@tonic-gate 	 *	1) First 5 characters are "From "
2147c478bd9Sstevel@tonic-gate 	 *	2) Next non-white characters are of the form "name@host:"
2157c478bd9Sstevel@tonic-gate 	 */
2167c478bd9Sstevel@tonic-gate 	if (strcmp(line, "???") == 0) {
2177c478bd9Sstevel@tonic-gate 		char rwho[MAXNAMLEN+1];
2187c478bd9Sstevel@tonic-gate 		char rsystm[MAXNAMLEN+1];
2197c478bd9Sstevel@tonic-gate 		char *cp;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 		if (strncmp(mesg, "From ", 5) == 0) {
2227c478bd9Sstevel@tonic-gate 			cp = &mesg[5];
2237c478bd9Sstevel@tonic-gate 			cp = copy_str_till(rwho, cp, '@', MAXNAMLEN + 1);
2247c478bd9Sstevel@tonic-gate 			if (rwho[0] != '\0') {
2257c478bd9Sstevel@tonic-gate 				cp = copy_str_till(rsystm, ++cp, ':',
2267c478bd9Sstevel@tonic-gate 				    MAXNAMLEN + 1);
2277c478bd9Sstevel@tonic-gate 				if (rsystm[0] != '\0') {
2287c478bd9Sstevel@tonic-gate 					(void) strcpy(systm, rsystm);
2297c478bd9Sstevel@tonic-gate 					(void) strncpy(rwho, who, 9);
2307c478bd9Sstevel@tonic-gate 					(void) strcpy(line, "rpc.rwalld");
2317c478bd9Sstevel@tonic-gate 				}
2327c478bd9Sstevel@tonic-gate 			}
2337c478bd9Sstevel@tonic-gate 		}
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 	(void) time(&tloc);
2367c478bd9Sstevel@tonic-gate 	(void) strftime(time_buf, sizeof (time_buf),
2377c478bd9Sstevel@tonic-gate 	    DATE_FMT, localtime(&tloc));
2387c478bd9Sstevel@tonic-gate 
239*de6baaf5SJohn Sonnenschein 	if (zflg != 0) {
240*de6baaf5SJohn Sonnenschein 		if ((zoneidlist =
241*de6baaf5SJohn Sonnenschein 		    malloc(sizeof (zoneid_t))) == NULL ||
242*de6baaf5SJohn Sonnenschein 		    (*zoneidlist = getzoneidbyname(zonename)) == -1)
243*de6baaf5SJohn Sonnenschein 			return (errno);
244*de6baaf5SJohn Sonnenschein 		nzids = 1;
245*de6baaf5SJohn Sonnenschein 	} else if (Zflg != 0) {
246*de6baaf5SJohn Sonnenschein 		if (zone_list(NULL, &nzids) != 0)
247*de6baaf5SJohn Sonnenschein 			return (errno);
248*de6baaf5SJohn Sonnenschein again:
249*de6baaf5SJohn Sonnenschein 		nzids *= 2;
250*de6baaf5SJohn Sonnenschein 		if ((zoneidlist = malloc(nzids * sizeof (zoneid_t))) == NULL)
251*de6baaf5SJohn Sonnenschein 			exit(errno);
252*de6baaf5SJohn Sonnenschein 		nzids_saved = nzids;
253*de6baaf5SJohn Sonnenschein 		if (zone_list(zoneidlist, &nzids) != 0) {
254*de6baaf5SJohn Sonnenschein 			(void) free(zoneidlist);
255*de6baaf5SJohn Sonnenschein 			return (errno);
2567c478bd9Sstevel@tonic-gate 		}
257*de6baaf5SJohn Sonnenschein 		if (nzids > nzids_saved) {
258*de6baaf5SJohn Sonnenschein 			free(zoneidlist);
259*de6baaf5SJohn Sonnenschein 			goto again;
260*de6baaf5SJohn Sonnenschein 		}
261*de6baaf5SJohn Sonnenschein 	}
262*de6baaf5SJohn Sonnenschein 	if (zflg || Zflg) {
263*de6baaf5SJohn Sonnenschein 		for (; nzids > 0; --nzids)
264*de6baaf5SJohn Sonnenschein 			sendmes_tozone(zoneidlist[nzids-1], aflag);
265*de6baaf5SJohn Sonnenschein 		free(zoneidlist);
266*de6baaf5SJohn Sonnenschein 	} else
267*de6baaf5SJohn Sonnenschein 		sendmes_tozone(getzoneid(), aflag);
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	return (0);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * Copy src to destination upto but not including the delim.
2747c478bd9Sstevel@tonic-gate  * Leave dst empty if delim not found or whitespace encountered.
2757c478bd9Sstevel@tonic-gate  * Return pointer to next character (delim, whitespace, or '\0')
2767c478bd9Sstevel@tonic-gate  */
2777c478bd9Sstevel@tonic-gate static char *
2787c478bd9Sstevel@tonic-gate copy_str_till(char *dst, char *src, char delim, int len)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate 	int i = 0;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	while (*src != '\0' && i < len) {
2837c478bd9Sstevel@tonic-gate 		if (isspace(*src)) {
2847c478bd9Sstevel@tonic-gate 			dst[0] = '\0';
2857c478bd9Sstevel@tonic-gate 			return (src);
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 		if (*src == delim) {
2887c478bd9Sstevel@tonic-gate 			dst[i] = '\0';
2897c478bd9Sstevel@tonic-gate 			return (src);
2907c478bd9Sstevel@tonic-gate 		}
2917c478bd9Sstevel@tonic-gate 		dst[i++] = *src++;
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 	dst[0] = '\0';
2947c478bd9Sstevel@tonic-gate 	return (src);
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate 
297*de6baaf5SJohn Sonnenschein static void
298*de6baaf5SJohn Sonnenschein sendmes_tozone(zoneid_t zid, int aflag) {
299*de6baaf5SJohn Sonnenschein 	int i = 0;
300*de6baaf5SJohn Sonnenschein 	char zonename[ZONENAME_MAX], root[MAXPATHLEN];
301*de6baaf5SJohn Sonnenschein 	struct utmpx *p;
302*de6baaf5SJohn Sonnenschein 
303*de6baaf5SJohn Sonnenschein 	if (zid != getzoneid()) {
304*de6baaf5SJohn Sonnenschein 		root[0] = '\0';
305*de6baaf5SJohn Sonnenschein 		(void) getzonenamebyid(zid, zonename, ZONENAME_MAX);
306*de6baaf5SJohn Sonnenschein 		(void) zone_get_rootpath(zonename, root, sizeof (root));
307*de6baaf5SJohn Sonnenschein 		(void) strlcat(root, UTMPX_FILE, sizeof (root));
308*de6baaf5SJohn Sonnenschein 		if (!utmpxname(root)) {
309*de6baaf5SJohn Sonnenschein 			(void) fprintf(stderr, "Cannot open %s\n", root);
310*de6baaf5SJohn Sonnenschein 			return;
311*de6baaf5SJohn Sonnenschein 		}
312*de6baaf5SJohn Sonnenschein 	} else {
313*de6baaf5SJohn Sonnenschein 		(void) utmpxname(UTMPX_FILE);
314*de6baaf5SJohn Sonnenschein 	}
315*de6baaf5SJohn Sonnenschein 	setutxent();
316*de6baaf5SJohn Sonnenschein 	while ((p = getutxent()) != NULL) {
317*de6baaf5SJohn Sonnenschein 		if (p->ut_type != USER_PROCESS)
318*de6baaf5SJohn Sonnenschein 			continue;
319*de6baaf5SJohn Sonnenschein 		/*
320*de6baaf5SJohn Sonnenschein 		 * if (-a option OR NOT pty window login), send the message
321*de6baaf5SJohn Sonnenschein 		 */
322*de6baaf5SJohn Sonnenschein 		if (aflag || !nonuser(*p))
323*de6baaf5SJohn Sonnenschein 			sendmes(p, zid);
324*de6baaf5SJohn Sonnenschein 	}
325*de6baaf5SJohn Sonnenschein 	endutxent();
326*de6baaf5SJohn Sonnenschein 
327*de6baaf5SJohn Sonnenschein 	(void) alarm(60);
328*de6baaf5SJohn Sonnenschein 	do {
329*de6baaf5SJohn Sonnenschein 		i = (int)wait((int *)0);
330*de6baaf5SJohn Sonnenschein 	} while (i != -1 || errno != ECHILD);
331*de6baaf5SJohn Sonnenschein 
332*de6baaf5SJohn Sonnenschein }
333*de6baaf5SJohn Sonnenschein 
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate  * Note to future maintainers: with the change of wall to use the
3367c478bd9Sstevel@tonic-gate  * getutxent() API, the forked children (created by this function)
3377c478bd9Sstevel@tonic-gate  * must call _exit as opposed to exit. This is necessary to avoid
3387c478bd9Sstevel@tonic-gate  * unwanted fflushing of getutxent's stdio stream (caused by atexit
3397c478bd9Sstevel@tonic-gate  * processing).
3407c478bd9Sstevel@tonic-gate  */
3417c478bd9Sstevel@tonic-gate static void
342*de6baaf5SJohn Sonnenschein sendmes(struct utmpx *p, zoneid_t zid)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate 	int i;
3457c478bd9Sstevel@tonic-gate 	char *s;
3467c478bd9Sstevel@tonic-gate 	static char device[LMAX + 6];
3477c478bd9Sstevel@tonic-gate 	char *bp;
3487c478bd9Sstevel@tonic-gate 	int ibp;
3497c478bd9Sstevel@tonic-gate 	FILE *f;
350*de6baaf5SJohn Sonnenschein 	int fd, tmpl_fd;
351*de6baaf5SJohn Sonnenschein 	boolean_t zoneenter = B_FALSE;
3527c478bd9Sstevel@tonic-gate 
353*de6baaf5SJohn Sonnenschein 	if (zid != getzoneid()) {
354*de6baaf5SJohn Sonnenschein 		zoneenter = B_TRUE;
355*de6baaf5SJohn Sonnenschein 		tmpl_fd = init_template();
356*de6baaf5SJohn Sonnenschein 		if (tmpl_fd == -1) {
357*de6baaf5SJohn Sonnenschein 			(void) fprintf(stderr, "Could not initialize "
358*de6baaf5SJohn Sonnenschein 			    "process contract");
3597c478bd9Sstevel@tonic-gate 			return;
360*de6baaf5SJohn Sonnenschein 		}
361*de6baaf5SJohn Sonnenschein 	}
362*de6baaf5SJohn Sonnenschein 
3637c478bd9Sstevel@tonic-gate 	while ((i = (int)fork()) == -1) {
3647c478bd9Sstevel@tonic-gate 		(void) alarm(60);
3657c478bd9Sstevel@tonic-gate 		(void) wait((int *)0);
3667c478bd9Sstevel@tonic-gate 		(void) alarm(0);
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	if (i)
3707c478bd9Sstevel@tonic-gate 		return;
3717c478bd9Sstevel@tonic-gate 
372*de6baaf5SJohn Sonnenschein 	if (zoneenter && zone_enter(zid) == -1) {
373*de6baaf5SJohn Sonnenschein 		char zonename[ZONENAME_MAX];
374*de6baaf5SJohn Sonnenschein 		(void) getzonenamebyid(zid, zonename, ZONENAME_MAX);
375*de6baaf5SJohn Sonnenschein 		(void) fprintf(stderr, "Could not enter zone "
376*de6baaf5SJohn Sonnenschein 		    "%s\n", zonename);
377*de6baaf5SJohn Sonnenschein 	}
378*de6baaf5SJohn Sonnenschein 	if (zoneenter)
379*de6baaf5SJohn Sonnenschein 		(void) ct_tmpl_clear(tmpl_fd);
380*de6baaf5SJohn Sonnenschein 
381*de6baaf5SJohn Sonnenschein 	if (gflag)
382*de6baaf5SJohn Sonnenschein 		if (!chkgrp(p->ut_user))
383*de6baaf5SJohn Sonnenschein 			_exit(0);
384*de6baaf5SJohn Sonnenschein 
3857c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, SIG_IGN);
3867c478bd9Sstevel@tonic-gate 	(void) alarm(60);
3877c478bd9Sstevel@tonic-gate 	s = &device[0];
3887c478bd9Sstevel@tonic-gate 	(void) snprintf(s, sizeof (device), "/dev/%.*s", LMAX, p->ut_line);
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	/* check if the device is really a tty */
3917c478bd9Sstevel@tonic-gate 	if ((fd = open(s, O_WRONLY|O_NOCTTY|O_NONBLOCK)) == -1) {
3927c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Cannot send to %.*s on %s\n",
3937c478bd9Sstevel@tonic-gate 		    NMAX, p->ut_user, s);
3947c478bd9Sstevel@tonic-gate 		perror("open");
3957c478bd9Sstevel@tonic-gate 		(void) fflush(stderr);
3967c478bd9Sstevel@tonic-gate 		_exit(1);
3977c478bd9Sstevel@tonic-gate 	} else {
3987c478bd9Sstevel@tonic-gate 		if (!isatty(fd)) {
3997c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
4007c478bd9Sstevel@tonic-gate 			    "Cannot send to device %.*s %s\n",
4017c478bd9Sstevel@tonic-gate 			    LMAX, p->ut_line,
4027c478bd9Sstevel@tonic-gate 			    "because it's not a tty");
4037c478bd9Sstevel@tonic-gate 			openlog("wall", 0, LOG_AUTH);
4047c478bd9Sstevel@tonic-gate 			syslog(LOG_CRIT, "%.*s in utmpx is not a tty\n",
4057c478bd9Sstevel@tonic-gate 			    LMAX, p->ut_line);
4067c478bd9Sstevel@tonic-gate 			closelog();
4077c478bd9Sstevel@tonic-gate 			(void) fflush(stderr);
4087c478bd9Sstevel@tonic-gate 			_exit(1);
4097c478bd9Sstevel@tonic-gate 		}
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate #ifdef DEBUG
4127c478bd9Sstevel@tonic-gate 	(void) close(fd);
4137c478bd9Sstevel@tonic-gate 	f = fopen("wall.debug", "a");
4147c478bd9Sstevel@tonic-gate #else
4157c478bd9Sstevel@tonic-gate 	f = fdopen(fd, "w");
4167c478bd9Sstevel@tonic-gate #endif
4177c478bd9Sstevel@tonic-gate 	if (f == NULL) {
4187c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Cannot send to %-.*s on %s\n",
4197c478bd9Sstevel@tonic-gate 		    NMAX, &p->ut_user[0], s);
4207c478bd9Sstevel@tonic-gate 		perror("open");
4217c478bd9Sstevel@tonic-gate 		(void) fflush(stderr);
4227c478bd9Sstevel@tonic-gate 		_exit(1);
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 	(void) fprintf(f,
4257c478bd9Sstevel@tonic-gate 	    "\07\07\07Broadcast Message from %s (%s) on %s %19.19s",
4267c478bd9Sstevel@tonic-gate 	    who, line, systm, time_buf);
4277c478bd9Sstevel@tonic-gate 	if (gflag)
4287c478bd9Sstevel@tonic-gate 		(void) fprintf(f, " to group %s", grpname);
4297c478bd9Sstevel@tonic-gate 	(void) fprintf(f, "...\n");
4307c478bd9Sstevel@tonic-gate #ifdef DEBUG
4317c478bd9Sstevel@tonic-gate 	(void) fprintf(f, "DEBUG: To %.8s on %s\n", p->ut_user, s);
4327c478bd9Sstevel@tonic-gate #endif
4337c478bd9Sstevel@tonic-gate 	i = strlen(mesg);
4347c478bd9Sstevel@tonic-gate 	for (bp = mesg; --i >= 0; bp++) {
4357c478bd9Sstevel@tonic-gate 		ibp = (unsigned int)((unsigned char) *bp);
4367c478bd9Sstevel@tonic-gate 		if (*bp == '\n')
4377c478bd9Sstevel@tonic-gate 			(void) putc('\r', f);
4387c478bd9Sstevel@tonic-gate 		if (isprint(ibp) || *bp == '\r' || *bp == '\013' ||
4397c478bd9Sstevel@tonic-gate 		    *bp == ' ' || *bp == '\t' || *bp == '\n' || *bp == '\007') {
4407c478bd9Sstevel@tonic-gate 			(void) putc(*bp, f);
4417c478bd9Sstevel@tonic-gate 		} else {
4427c478bd9Sstevel@tonic-gate 			if (!isascii(*bp)) {
4437c478bd9Sstevel@tonic-gate 				(void) fputs("M-", f);
4447c478bd9Sstevel@tonic-gate 				*bp = toascii(*bp);
4457c478bd9Sstevel@tonic-gate 			}
4467c478bd9Sstevel@tonic-gate 			if (iscntrl(*bp)) {
4477c478bd9Sstevel@tonic-gate 				(void) putc('^', f);
4487c478bd9Sstevel@tonic-gate 				(void) putc(*bp + 0100, f);
4497c478bd9Sstevel@tonic-gate 			}
4507c478bd9Sstevel@tonic-gate 			else
4517c478bd9Sstevel@tonic-gate 				(void) putc(*bp, f);
4527c478bd9Sstevel@tonic-gate 		}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 		if (*bp == '\n')
4557c478bd9Sstevel@tonic-gate 			(void) fflush(f);
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		if (ferror(f) || feof(f)) {
4587c478bd9Sstevel@tonic-gate 			(void) printf("\n\007Write failed\n");
4597c478bd9Sstevel@tonic-gate 			(void) fflush(stdout);
4607c478bd9Sstevel@tonic-gate 			_exit(1);
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 	}
4637c478bd9Sstevel@tonic-gate 	(void) fclose(f);
4647c478bd9Sstevel@tonic-gate 	(void) close(fd);
4657c478bd9Sstevel@tonic-gate 	_exit(0);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate static int
4707c478bd9Sstevel@tonic-gate chkgrp(char *name)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	int i;
4737c478bd9Sstevel@tonic-gate 	char *p;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	for (i = 0; pgrp->gr_mem[i] && pgrp->gr_mem[i][0]; i++) {
476*de6baaf5SJohn Sonnenschein 		for (p = name; *p && *p != ' '; p++)
477*de6baaf5SJohn Sonnenschein 		;
4787c478bd9Sstevel@tonic-gate 		*p = 0;
4797c478bd9Sstevel@tonic-gate 		if (strncmp(name, pgrp->gr_mem[i], 8) == 0)
4807c478bd9Sstevel@tonic-gate 			return (1);
4817c478bd9Sstevel@tonic-gate 	}
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	return (0);
4847c478bd9Sstevel@tonic-gate }
485*de6baaf5SJohn Sonnenschein 
486*de6baaf5SJohn Sonnenschein static int
487*de6baaf5SJohn Sonnenschein init_template(void) {
488*de6baaf5SJohn Sonnenschein 	int fd = 0;
489*de6baaf5SJohn Sonnenschein 	int err = 0;
490*de6baaf5SJohn Sonnenschein 
491*de6baaf5SJohn Sonnenschein 	fd = open64(CTFS_ROOT "/process/template", O_RDWR);
492*de6baaf5SJohn Sonnenschein 	if (fd == -1)
493*de6baaf5SJohn Sonnenschein 		return (-1);
494*de6baaf5SJohn Sonnenschein 
495*de6baaf5SJohn Sonnenschein 	err |= ct_tmpl_set_critical(fd, 0);
496*de6baaf5SJohn Sonnenschein 	err |= ct_tmpl_set_informative(fd, 0);
497*de6baaf5SJohn Sonnenschein 	err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
498*de6baaf5SJohn Sonnenschein 	err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT);
499*de6baaf5SJohn Sonnenschein 	if (err || ct_tmpl_activate(fd)) {
500*de6baaf5SJohn Sonnenschein 		(void) close(fd);
501*de6baaf5SJohn Sonnenschein 		return (-1);
502*de6baaf5SJohn Sonnenschein 	}
503*de6baaf5SJohn Sonnenschein 
504*de6baaf5SJohn Sonnenschein 	return (fd);
505*de6baaf5SJohn Sonnenschein }
506