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 5*004388ebScasper * Common Development and Distribution License (the "License"). 6*004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*004388ebScasper * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdlib.h> 297c478bd9Sstevel@tonic-gate #include <stdio.h> 30*004388ebScasper #include <stdio_ext.h> 317c478bd9Sstevel@tonic-gate #include <limits.h> 327c478bd9Sstevel@tonic-gate #include <libproc.h> 337c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 407c478bd9Sstevel@tonic-gate #include <zone.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate static char *pname; 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static void 457c478bd9Sstevel@tonic-gate convert_path(const char *path, char *fname, size_t size, 467c478bd9Sstevel@tonic-gate struct ps_prochandle *P) 477c478bd9Sstevel@tonic-gate { 487c478bd9Sstevel@tonic-gate char *p, *s; 497c478bd9Sstevel@tonic-gate ssize_t len; 507c478bd9Sstevel@tonic-gate const psinfo_t *pip = Ppsinfo(P); 517c478bd9Sstevel@tonic-gate int got_uts = 0; 527c478bd9Sstevel@tonic-gate struct utsname uts; 537c478bd9Sstevel@tonic-gate char exec[PATH_MAX]; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate fname[size - 1] = '\0'; 567c478bd9Sstevel@tonic-gate size--; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate while ((p = strchr(path, '%')) != NULL && size != 0) { 597c478bd9Sstevel@tonic-gate len = MIN(size, p - path); 607c478bd9Sstevel@tonic-gate bcopy(path, fname, len); 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate fname += len; 637c478bd9Sstevel@tonic-gate if ((size -= len) == 0) 647c478bd9Sstevel@tonic-gate break; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate p++; 677c478bd9Sstevel@tonic-gate switch (*p) { 687c478bd9Sstevel@tonic-gate case 'p': 697c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%d", (int)pip->pr_pid); 707c478bd9Sstevel@tonic-gate break; 717c478bd9Sstevel@tonic-gate case 'u': 727c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%d", (int)pip->pr_uid); 737c478bd9Sstevel@tonic-gate break; 747c478bd9Sstevel@tonic-gate case 'g': 757c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%d", (int)pip->pr_gid); 767c478bd9Sstevel@tonic-gate break; 777c478bd9Sstevel@tonic-gate case 'f': 787c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%s", pip->pr_fname); 797c478bd9Sstevel@tonic-gate break; 807c478bd9Sstevel@tonic-gate case 'd': 817c478bd9Sstevel@tonic-gate len = 0; 827c478bd9Sstevel@tonic-gate if (Pexecname(P, exec, sizeof (exec)) == NULL || 837c478bd9Sstevel@tonic-gate exec[0] != '/' || (s = strrchr(exec, '/')) == NULL) 847c478bd9Sstevel@tonic-gate break; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate *s = '\0'; 877c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%s", &exec[1]); 887c478bd9Sstevel@tonic-gate break; 897c478bd9Sstevel@tonic-gate case 'n': 907c478bd9Sstevel@tonic-gate if (got_uts++ == 0) 917c478bd9Sstevel@tonic-gate (void) uname(&uts); 927c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%s", uts.nodename); 937c478bd9Sstevel@tonic-gate break; 947c478bd9Sstevel@tonic-gate case 'm': 957c478bd9Sstevel@tonic-gate if (got_uts++ == 0) 967c478bd9Sstevel@tonic-gate (void) uname(&uts); 977c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%s", uts.machine); 987c478bd9Sstevel@tonic-gate break; 997c478bd9Sstevel@tonic-gate case 't': 1007c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%ld", (long)time(NULL)); 1017c478bd9Sstevel@tonic-gate break; 1027c478bd9Sstevel@tonic-gate case 'z': 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * getzonenamebyid() returns the size including the 1057c478bd9Sstevel@tonic-gate * terminating null byte so we need to adjust len. 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate if ((len = getzonenamebyid(pip->pr_zoneid, fname, 1087c478bd9Sstevel@tonic-gate size)) < 0) 1097c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%d", 1107c478bd9Sstevel@tonic-gate (int)pip->pr_zoneid); 1117c478bd9Sstevel@tonic-gate else 1127c478bd9Sstevel@tonic-gate len--; 1137c478bd9Sstevel@tonic-gate break; 1147c478bd9Sstevel@tonic-gate case '%': 1157c478bd9Sstevel@tonic-gate *fname = '%'; 1167c478bd9Sstevel@tonic-gate len = 1; 1177c478bd9Sstevel@tonic-gate break; 1187c478bd9Sstevel@tonic-gate default: 1197c478bd9Sstevel@tonic-gate len = snprintf(fname, size, "%%%c", *p); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate if (len >= size) 1237c478bd9Sstevel@tonic-gate return; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate fname += len; 1267c478bd9Sstevel@tonic-gate size -= len; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate path = p + 1; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate (void) strncpy(fname, path, size); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate static void 1357c478bd9Sstevel@tonic-gate gcore(struct ps_prochandle *P, const char *fname, core_content_t content, 1367c478bd9Sstevel@tonic-gate int *errp) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate if (Pgcore(P, fname, content) == 0) { 1397c478bd9Sstevel@tonic-gate (void) printf("%s: %s dumped\n", pname, fname); 1407c478bd9Sstevel@tonic-gate } else { 1417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s dump failed: %s\n", pname, 1427c478bd9Sstevel@tonic-gate fname, strerror(errno)); 1437c478bd9Sstevel@tonic-gate (*errp)++; 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate int 1487c478bd9Sstevel@tonic-gate main(int argc, char **argv) 1497c478bd9Sstevel@tonic-gate { 1507c478bd9Sstevel@tonic-gate struct ps_prochandle *P; 1517c478bd9Sstevel@tonic-gate int gerr; 1527c478bd9Sstevel@tonic-gate char *prefix = NULL; 1537c478bd9Sstevel@tonic-gate int opt; 1547c478bd9Sstevel@tonic-gate int opt_p = 0, opt_g = 0, opt_c = 0; 1557c478bd9Sstevel@tonic-gate int oflags = 0; 1567c478bd9Sstevel@tonic-gate int i; 1577c478bd9Sstevel@tonic-gate char fname[MAXPATHLEN]; 1587c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 1597c478bd9Sstevel@tonic-gate int err = 0; 1607c478bd9Sstevel@tonic-gate core_content_t content = CC_CONTENT_DEFAULT; 1617c478bd9Sstevel@tonic-gate struct rlimit rlim; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate if ((pname = strrchr(argv[0], '/')) == NULL) 1647c478bd9Sstevel@tonic-gate pname = argv[0]; 1657c478bd9Sstevel@tonic-gate else 1667c478bd9Sstevel@tonic-gate argv[0] = ++pname; /* for getopt() */ 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "o:Fgpc:")) != EOF) { 1697c478bd9Sstevel@tonic-gate switch (opt) { 1707c478bd9Sstevel@tonic-gate case 'o': 1717c478bd9Sstevel@tonic-gate prefix = optarg; 1727c478bd9Sstevel@tonic-gate break; 1737c478bd9Sstevel@tonic-gate case 'c': 1747c478bd9Sstevel@tonic-gate if (proc_str2content(optarg, &content) != 0) { 1757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: invalid " 1767c478bd9Sstevel@tonic-gate "content string '%s'\n", pname, optarg); 1777c478bd9Sstevel@tonic-gate goto usage; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate opt_c = 1; 1807c478bd9Sstevel@tonic-gate break; 1817c478bd9Sstevel@tonic-gate case 'F': 1827c478bd9Sstevel@tonic-gate oflags |= PGRAB_FORCE; 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate case 'p': 1857c478bd9Sstevel@tonic-gate opt_p = 1; 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate case 'g': 1887c478bd9Sstevel@tonic-gate opt_g = 1; 1897c478bd9Sstevel@tonic-gate break; 1907c478bd9Sstevel@tonic-gate default: 1917c478bd9Sstevel@tonic-gate goto usage; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate if ((opt_p | opt_g) == 0) { 1967c478bd9Sstevel@tonic-gate if (prefix == NULL) 1977c478bd9Sstevel@tonic-gate prefix = "core"; 1987c478bd9Sstevel@tonic-gate } else { 1997c478bd9Sstevel@tonic-gate int options; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate if ((options = core_get_options()) == -1) { 2027c478bd9Sstevel@tonic-gate perror("core_get_options()"); 2037c478bd9Sstevel@tonic-gate return (1); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (opt_p && !(options & CC_PROCESS_PATH)) { 2077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: per-process core dumps " 2087c478bd9Sstevel@tonic-gate "are disabled (ignoring -p)\n", pname); 2097c478bd9Sstevel@tonic-gate opt_p = 0; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate if (opt_g && !(options & CC_GLOBAL_PATH)) { 2137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: global core dumps " 2147c478bd9Sstevel@tonic-gate "are disabled (ignoring -g)\n", pname); 2157c478bd9Sstevel@tonic-gate opt_g = 0; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if ((opt_p | opt_g) == 0 && prefix == NULL) 2197c478bd9Sstevel@tonic-gate return (1); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate argc -= optind; 2237c478bd9Sstevel@tonic-gate argv += optind; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (argc == 0) 2267c478bd9Sstevel@tonic-gate goto usage; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * Make sure we'll have enough file descriptors to handle a target 2307c478bd9Sstevel@tonic-gate * that has many many mappings. 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { 2337c478bd9Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 2347c478bd9Sstevel@tonic-gate (void) setrlimit(RLIMIT_NOFILE, &rlim); 235*004388ebScasper (void) enable_extended_FILE_stdio(-1, -1); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 2397c478bd9Sstevel@tonic-gate P = proc_arg_grab(argv[i], PR_ARG_PIDS, oflags, &gerr); 2407c478bd9Sstevel@tonic-gate if (P == NULL) { 2417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: cannot grab %s: %s\n", 2427c478bd9Sstevel@tonic-gate pname, argv[i], Pgrab_error(gerr)); 2437c478bd9Sstevel@tonic-gate err++; 2447c478bd9Sstevel@tonic-gate continue; 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate if (prefix != NULL) { 2487c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s.%%p", prefix); 2497c478bd9Sstevel@tonic-gate convert_path(path, fname, sizeof (fname), P); 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate gcore(P, fname, content, &err); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate if (opt_p) { 2557c478bd9Sstevel@tonic-gate pid_t pid = Pstatus(P)->pr_pid; 2567c478bd9Sstevel@tonic-gate (void) core_get_process_path(path, sizeof (path), pid); 2577c478bd9Sstevel@tonic-gate convert_path(path, fname, sizeof (fname), P); 2587c478bd9Sstevel@tonic-gate if (!opt_c) 2597c478bd9Sstevel@tonic-gate (void) core_get_process_content(&content, pid); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate gcore(P, fname, content, &err); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (opt_g) { 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * Global core files are always just readable and 2677c478bd9Sstevel@tonic-gate * writable by their owner so we temporarily change 2687c478bd9Sstevel@tonic-gate * the umask. 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate mode_t oldmode = umask(S_IXUSR | S_IRWXG | S_IRWXO); 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate (void) core_get_global_path(path, sizeof (path)); 2737c478bd9Sstevel@tonic-gate convert_path(path, fname, sizeof (fname), P); 2747c478bd9Sstevel@tonic-gate if (!opt_c) 2757c478bd9Sstevel@tonic-gate (void) core_get_global_content(&content); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate gcore(P, fname, content, &err); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate (void) umask(oldmode); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate Prelease(P, 0); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate return (err != 0); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate usage: 2887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "usage: %s " 2897c478bd9Sstevel@tonic-gate "[ -pgF ] [ -o filename ] [ -c content ] pid ...\n", pname); 2907c478bd9Sstevel@tonic-gate return (2); 2917c478bd9Sstevel@tonic-gate } 292