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