Print this page
2989 Eliminate use of LOGNAME_MAX in ON
1166 useradd have warning with name more 8 chars
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/wall/wall.c
+++ new/usr/src/cmd/wall/wall.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 23 /* All Rights Reserved */
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
24 24
25 25
26 26
27 27 /*
28 28 * Copyright 1988-2003 Sun Microsystems, Inc. All rights reserved.
29 29 * Use is subject to license terms.
30 30 */
31 31
32 32 /*
33 33 * Copyright 2012 Joyent, Inc. All rights reserved.
34 + *
35 + * Copyright (c) 2013 Gary Mills
34 36 */
35 37
36 38 #include <signal.h>
37 39 #include <stdio.h>
38 40 #include <stdlib.h>
39 41 #include <grp.h>
40 42 #include <sys/types.h>
41 43 #include <unistd.h>
42 44 #include <string.h>
43 45 #include <ctype.h>
44 46 #include <sys/stat.h>
45 47 #include <utmpx.h>
46 48 #include <sys/utsname.h>
47 49 #include <dirent.h>
48 50 #include <pwd.h>
49 51 #include <fcntl.h>
50 52 #include <time.h>
51 53 #include <errno.h>
52 54 #include <locale.h>
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
53 55 #include <syslog.h>
54 56 #include <sys/wait.h>
55 57 #include <limits.h>
56 58 #include <libzonecfg.h>
57 59 #include <zone.h>
58 60 #include <sys/contract/process.h>
59 61 #include <libcontract.h>
60 62 #include <sys/ctfs.h>
61 63
62 64 /*
63 - * utmpx defines wider fields for user and line. For compatibility of output,
64 - * we are limiting these to the old maximums in utmp. Define UTMPX_NAMELEN
65 - * to use the full lengths.
65 + * Use the full lengths from utmpx for user and line.
66 66 */
67 -#ifndef UTMPX_NAMELEN
68 -/* XXX - utmp -fix name length */
69 -#define NMAX (_POSIX_LOGIN_NAME_MAX - 1)
70 -#define LMAX 12
71 -#else /* UTMPX_NAMELEN */
72 -#define NMAX (sizeof (((struct utmpx *)0)->ut_user)
73 -#define LMAX (sizeof (((struct utmpx *)0)->ut_line)
74 -#endif /* UTMPX_NAMELEN */
67 +#define NMAX (sizeof (((struct utmpx *)0)->ut_user))
68 +#define LMAX (sizeof (((struct utmpx *)0)->ut_line))
75 69
76 70 static char mesg[3000];
77 71 static char *infile;
78 72 static int gflag;
79 73 static struct group *pgrp;
80 74 static char *grpname;
81 75 static char line[MAXNAMLEN+1] = "???";
82 76 static char systm[MAXNAMLEN+1];
83 77 static time_t tloc;
84 78 static struct utsname utsn;
85 -static char who[9] = "???";
79 +static char who[NMAX+1] = "???";
86 80 static char time_buf[50];
87 81 #define DATE_FMT "%a %b %e %H:%M:%S"
88 82
89 83 static void sendmes(struct utmpx *, zoneid_t);
90 84 static void sendmes_tozone(zoneid_t, int);
91 85 static int chkgrp(char *);
92 86 static char *copy_str_till(char *, char *, char, int);
93 87
94 88 static int init_template(void);
95 89 int contract_abandon_id(ctid_t);
96 90
97 91 int
98 92 main(int argc, char *argv[])
99 93 {
100 94 FILE *f;
101 95 char *ptr, *start;
102 96 struct passwd *pwd;
103 97 char *term_name;
104 98 int c;
105 99 int aflag = 0;
106 100 int errflg = 0;
107 101 int zflg = 0;
108 102 int Zflg = 0;
109 103
110 104 char *zonename = NULL;
111 105 zoneid_t *zoneidlist = NULL;
112 106 uint_t nzids_saved, nzids = 0;
113 107
114 108 (void) setlocale(LC_ALL, "");
115 109
116 110 while ((c = getopt(argc, argv, "g:az:Z")) != EOF)
117 111 switch (c) {
118 112 case 'a':
119 113 aflag++;
120 114 break;
121 115 case 'g':
122 116 if (gflag) {
123 117 (void) fprintf(stderr,
124 118 "Only one group allowed\n");
125 119 return (1);
126 120 }
127 121 if ((pgrp = getgrnam(grpname = optarg)) == NULL) {
128 122 (void) fprintf(stderr, "Unknown group %s\n",
129 123 grpname);
130 124 return (1);
131 125 }
132 126 gflag++;
133 127 break;
134 128 case 'z':
135 129 zflg++;
136 130 zonename = optarg;
137 131 if (getzoneidbyname(zonename) == -1) {
138 132 (void) fprintf(stderr, "Specified zone %s "
139 133 "is invalid", zonename);
140 134 return (1);
141 135 }
142 136 break;
143 137 case 'Z':
144 138 Zflg++;
145 139 break;
146 140 case '?':
147 141 errflg++;
148 142 break;
149 143 }
150 144
151 145 if (errflg) {
152 146 (void) fprintf(stderr,
153 147 "Usage: wall [-a] [-g group] [-z zone] [-Z] [files...]\n");
154 148 return (1);
155 149 }
156 150
157 151 if (zflg && Zflg) {
158 152 (void) fprintf(stderr, "Cannot use -z with -Z\n");
159 153 return (1);
160 154 }
161 155
162 156 if (optind < argc)
163 157 infile = argv[optind];
164 158
165 159 if (uname(&utsn) == -1) {
166 160 (void) fprintf(stderr, "wall: uname() failed, %s\n",
167 161 strerror(errno));
168 162 return (2);
169 163 }
170 164 (void) strcpy(systm, utsn.nodename);
171 165
172 166 /*
173 167 * Get the name of the terminal wall is running from.
174 168 */
175 169
176 170 if ((term_name = ttyname(fileno(stderr))) != NULL) {
177 171 /*
178 172 * skip the leading "/dev/" in term_name
179 173 */
180 174 (void) strncpy(line, &term_name[5], sizeof (line) - 1);
181 175 }
182 176
183 177 if (who[0] == '?') {
184 178 if (pwd = getpwuid(getuid()))
185 179 (void) strncpy(&who[0], pwd->pw_name, sizeof (who));
186 180 }
187 181
188 182 f = stdin;
189 183 if (infile) {
190 184 f = fopen(infile, "r");
191 185 if (f == NULL) {
192 186 (void) fprintf(stderr, "Cannot open %s\n", infile);
193 187 return (1);
194 188 }
195 189 }
196 190
197 191 start = &mesg[0];
198 192 ptr = start;
199 193 while ((ptr - start) < 3000) {
200 194 size_t n;
201 195
202 196 if (fgets(ptr, &mesg[sizeof (mesg)] - ptr, f) == NULL)
203 197 break;
204 198 if ((n = strlen(ptr)) == 0)
205 199 break;
206 200 ptr += n;
207 201 }
208 202 (void) fclose(f);
209 203
210 204 /*
211 205 * If the request is from the rwall daemon then use the caller's
212 206 * name and host. We determine this if all of the following is true:
213 207 * 1) First 5 characters are "From "
214 208 * 2) Next non-white characters are of the form "name@host:"
215 209 */
216 210 if (strcmp(line, "???") == 0) {
217 211 char rwho[MAXNAMLEN+1];
218 212 char rsystm[MAXNAMLEN+1];
↓ open down ↓ |
123 lines elided |
↑ open up ↑ |
219 213 char *cp;
220 214
221 215 if (strncmp(mesg, "From ", 5) == 0) {
222 216 cp = &mesg[5];
223 217 cp = copy_str_till(rwho, cp, '@', MAXNAMLEN + 1);
224 218 if (rwho[0] != '\0') {
225 219 cp = copy_str_till(rsystm, ++cp, ':',
226 220 MAXNAMLEN + 1);
227 221 if (rsystm[0] != '\0') {
228 222 (void) strcpy(systm, rsystm);
229 - (void) strncpy(rwho, who, 9);
223 + (void) strncpy(rwho, who,
224 + sizeof (who));
230 225 (void) strcpy(line, "rpc.rwalld");
231 226 }
232 227 }
233 228 }
234 229 }
235 230 (void) time(&tloc);
236 231 (void) strftime(time_buf, sizeof (time_buf),
237 232 DATE_FMT, localtime(&tloc));
238 233
239 234 if (zflg != 0) {
240 235 if ((zoneidlist =
241 236 malloc(sizeof (zoneid_t))) == NULL ||
242 237 (*zoneidlist = getzoneidbyname(zonename)) == -1)
243 238 return (errno);
244 239 nzids = 1;
245 240 } else if (Zflg != 0) {
246 241 if (zone_list(NULL, &nzids) != 0)
247 242 return (errno);
248 243 again:
249 244 nzids *= 2;
250 245 if ((zoneidlist = malloc(nzids * sizeof (zoneid_t))) == NULL)
251 246 exit(errno);
252 247 nzids_saved = nzids;
253 248 if (zone_list(zoneidlist, &nzids) != 0) {
254 249 (void) free(zoneidlist);
255 250 return (errno);
256 251 }
257 252 if (nzids > nzids_saved) {
258 253 free(zoneidlist);
259 254 goto again;
260 255 }
261 256 }
262 257 if (zflg || Zflg) {
263 258 for (; nzids > 0; --nzids)
264 259 sendmes_tozone(zoneidlist[nzids-1], aflag);
265 260 free(zoneidlist);
266 261 } else
267 262 sendmes_tozone(getzoneid(), aflag);
268 263
269 264 return (0);
270 265 }
271 266
272 267 /*
273 268 * Copy src to destination upto but not including the delim.
274 269 * Leave dst empty if delim not found or whitespace encountered.
275 270 * Return pointer to next character (delim, whitespace, or '\0')
276 271 */
277 272 static char *
278 273 copy_str_till(char *dst, char *src, char delim, int len)
279 274 {
280 275 int i = 0;
281 276
282 277 while (*src != '\0' && i < len) {
283 278 if (isspace(*src)) {
284 279 dst[0] = '\0';
285 280 return (src);
286 281 }
287 282 if (*src == delim) {
288 283 dst[i] = '\0';
289 284 return (src);
290 285 }
291 286 dst[i++] = *src++;
292 287 }
293 288 dst[0] = '\0';
294 289 return (src);
295 290 }
296 291
297 292 static void
298 293 sendmes_tozone(zoneid_t zid, int aflag) {
299 294 int i = 0;
300 295 char zonename[ZONENAME_MAX], root[MAXPATHLEN];
301 296 struct utmpx *p;
302 297
303 298 if (zid != getzoneid()) {
304 299 root[0] = '\0';
305 300 (void) getzonenamebyid(zid, zonename, ZONENAME_MAX);
306 301 (void) zone_get_rootpath(zonename, root, sizeof (root));
307 302 (void) strlcat(root, UTMPX_FILE, sizeof (root));
308 303 if (!utmpxname(root)) {
309 304 (void) fprintf(stderr, "Cannot open %s\n", root);
310 305 return;
311 306 }
312 307 } else {
313 308 (void) utmpxname(UTMPX_FILE);
314 309 }
315 310 setutxent();
316 311 while ((p = getutxent()) != NULL) {
317 312 if (p->ut_type != USER_PROCESS)
318 313 continue;
319 314 /*
320 315 * if (-a option OR NOT pty window login), send the message
321 316 */
322 317 if (aflag || !nonuser(*p))
323 318 sendmes(p, zid);
324 319 }
325 320 endutxent();
326 321
327 322 (void) alarm(60);
328 323 do {
329 324 i = (int)wait((int *)0);
330 325 } while (i != -1 || errno != ECHILD);
331 326
332 327 }
333 328
334 329 /*
335 330 * Note to future maintainers: with the change of wall to use the
336 331 * getutxent() API, the forked children (created by this function)
337 332 * must call _exit as opposed to exit. This is necessary to avoid
338 333 * unwanted fflushing of getutxent's stdio stream (caused by atexit
339 334 * processing).
340 335 */
341 336 static void
342 337 sendmes(struct utmpx *p, zoneid_t zid)
343 338 {
344 339 int i;
345 340 char *s;
346 341 static char device[LMAX + 6];
347 342 char *bp;
348 343 int ibp;
349 344 FILE *f;
350 345 int fd, tmpl_fd;
351 346 boolean_t zoneenter = B_FALSE;
352 347
353 348 if (zid != getzoneid()) {
354 349 zoneenter = B_TRUE;
355 350 tmpl_fd = init_template();
356 351 if (tmpl_fd == -1) {
357 352 (void) fprintf(stderr, "Could not initialize "
358 353 "process contract");
359 354 return;
360 355 }
361 356 }
362 357
363 358 while ((i = (int)fork()) == -1) {
364 359 (void) alarm(60);
365 360 (void) wait((int *)0);
366 361 (void) alarm(0);
367 362 }
368 363
369 364 if (i)
370 365 return;
371 366
372 367 if (zoneenter && zone_enter(zid) == -1) {
373 368 char zonename[ZONENAME_MAX];
374 369 (void) getzonenamebyid(zid, zonename, ZONENAME_MAX);
375 370 (void) fprintf(stderr, "Could not enter zone "
376 371 "%s\n", zonename);
377 372 }
378 373 if (zoneenter)
379 374 (void) ct_tmpl_clear(tmpl_fd);
380 375
381 376 if (gflag)
382 377 if (!chkgrp(p->ut_user))
383 378 _exit(0);
384 379
385 380 (void) signal(SIGHUP, SIG_IGN);
386 381 (void) alarm(60);
387 382 s = &device[0];
388 383 (void) snprintf(s, sizeof (device), "/dev/%.*s", LMAX, p->ut_line);
389 384
390 385 /* check if the device is really a tty */
391 386 if ((fd = open(s, O_WRONLY|O_NOCTTY|O_NONBLOCK)) == -1) {
392 387 (void) fprintf(stderr, "Cannot send to %.*s on %s\n",
393 388 NMAX, p->ut_user, s);
394 389 perror("open");
395 390 (void) fflush(stderr);
396 391 _exit(1);
397 392 } else {
398 393 if (!isatty(fd)) {
399 394 (void) fprintf(stderr,
400 395 "Cannot send to device %.*s %s\n",
401 396 LMAX, p->ut_line,
402 397 "because it's not a tty");
403 398 openlog("wall", 0, LOG_AUTH);
404 399 syslog(LOG_CRIT, "%.*s in utmpx is not a tty\n",
405 400 LMAX, p->ut_line);
406 401 closelog();
407 402 (void) fflush(stderr);
408 403 _exit(1);
409 404 }
410 405 }
411 406 #ifdef DEBUG
412 407 (void) close(fd);
413 408 f = fopen("wall.debug", "a");
414 409 #else
415 410 f = fdopen(fd, "w");
416 411 #endif
417 412 if (f == NULL) {
418 413 (void) fprintf(stderr, "Cannot send to %-.*s on %s\n",
419 414 NMAX, &p->ut_user[0], s);
420 415 perror("open");
↓ open down ↓ |
181 lines elided |
↑ open up ↑ |
421 416 (void) fflush(stderr);
422 417 _exit(1);
423 418 }
424 419 (void) fprintf(f,
425 420 "\07\07\07Broadcast Message from %s (%s) on %s %19.19s",
426 421 who, line, systm, time_buf);
427 422 if (gflag)
428 423 (void) fprintf(f, " to group %s", grpname);
429 424 (void) fprintf(f, "...\n");
430 425 #ifdef DEBUG
431 - (void) fprintf(f, "DEBUG: To %.8s on %s\n", p->ut_user, s);
426 + (void) fprintf(f, "DEBUG: To %.*s on %s\n", NMAX, p->ut_user, s);
432 427 #endif
433 428 i = strlen(mesg);
434 429 for (bp = mesg; --i >= 0; bp++) {
435 430 ibp = (unsigned int)((unsigned char) *bp);
436 431 if (*bp == '\n')
437 432 (void) putc('\r', f);
438 433 if (isprint(ibp) || *bp == '\r' || *bp == '\013' ||
439 434 *bp == ' ' || *bp == '\t' || *bp == '\n' || *bp == '\007') {
440 435 (void) putc(*bp, f);
441 436 } else {
442 437 if (!isascii(*bp)) {
443 438 (void) fputs("M-", f);
444 439 *bp = toascii(*bp);
445 440 }
446 441 if (iscntrl(*bp)) {
447 442 (void) putc('^', f);
448 443 (void) putc(*bp + 0100, f);
449 444 }
450 445 else
451 446 (void) putc(*bp, f);
452 447 }
453 448
454 449 if (*bp == '\n')
455 450 (void) fflush(f);
456 451
457 452 if (ferror(f) || feof(f)) {
458 453 (void) printf("\n\007Write failed\n");
459 454 (void) fflush(stdout);
460 455 _exit(1);
461 456 }
462 457 }
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
463 458 (void) fclose(f);
464 459 (void) close(fd);
465 460 _exit(0);
466 461 }
467 462
468 463
469 464 static int
470 465 chkgrp(char *name)
471 466 {
472 467 int i;
473 - char *p;
468 + char user[NMAX + 1];
474 469
470 + (void) strncpy(user, name, NMAX);
471 + user[NMAX] = '\0';
475 472 for (i = 0; pgrp->gr_mem[i] && pgrp->gr_mem[i][0]; i++) {
476 - for (p = name; *p && *p != ' '; p++)
477 - ;
478 - *p = 0;
479 - if (strncmp(name, pgrp->gr_mem[i], 8) == 0)
473 + if (strcmp(user, pgrp->gr_mem[i]) == 0)
480 474 return (1);
481 475 }
482 476
483 477 return (0);
484 478 }
485 479
486 480 static int
487 481 init_template(void) {
488 482 int fd = 0;
489 483 int err = 0;
490 484
491 485 fd = open64(CTFS_ROOT "/process/template", O_RDWR);
492 486 if (fd == -1)
493 487 return (-1);
494 488
495 489 err |= ct_tmpl_set_critical(fd, 0);
496 490 err |= ct_tmpl_set_informative(fd, 0);
497 491 err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
498 492 err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT);
499 493 if (err || ct_tmpl_activate(fd)) {
500 494 (void) close(fd);
501 495 return (-1);
502 496 }
503 497
504 498 return (fd);
505 499 }
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX