1174915Srwatson/*- 2174915Srwatson * Copyright (c) 2007 Robert N. M. Watson 3174915Srwatson * All rights reserved. 4174915Srwatson * 5174915Srwatson * Redistribution and use in source and binary forms, with or without 6174915Srwatson * modification, are permitted provided that the following conditions 7174915Srwatson * are met: 8174915Srwatson * 1. Redistributions of source code must retain the above copyright 9174915Srwatson * notice, this list of conditions and the following disclaimer. 10174915Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11174915Srwatson * notice, this list of conditions and the following disclaimer in the 12174915Srwatson * documentation and/or other materials provided with the distribution. 13174915Srwatson * 14174915Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15174915Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16174915Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17174915Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18174915Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19174915Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20174915Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21174915Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22174915Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23174915Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24174915Srwatson * SUCH DAMAGE. 25174915Srwatson */ 26174915Srwatson 27174915Srwatson#include <sys/cdefs.h> 28174915Srwatson__FBSDID("$FreeBSD$"); 29174915Srwatson 30174915Srwatson#include <sys/types.h> 31174915Srwatson#include <sys/sysctl.h> 32174915Srwatson 33174915Srwatson#include <err.h> 34174915Srwatson#include <errno.h> 35174915Srwatson#include <stdio.h> 36174915Srwatson#include <stdlib.h> 37174915Srwatson#include <string.h> 38174915Srwatson#include <sysexits.h> 39174915Srwatson 40174915Srwatson#include "ddb.h" 41174915Srwatson 42174915Srwatson/* 43174915Srwatson * These commands manage DDB(4) scripts from user space. For better or worse, 44174915Srwatson * the setting and unsetting of scripts is only poorly represented using 45174915Srwatson * sysctl(8), and this interface provides a more user-friendly way to 46174915Srwatson * accomplish this management, wrapped around lower-level sysctls. For 47174915Srwatson * completeness, listing of scripts is also included. 48174915Srwatson */ 49174915Srwatson 50174915Srwatson#define SYSCTL_SCRIPT "debug.ddb.scripting.script" 51174915Srwatson#define SYSCTL_SCRIPTS "debug.ddb.scripting.scripts" 52174915Srwatson#define SYSCTL_UNSCRIPT "debug.ddb.scripting.unscript" 53174915Srwatson 54174915Srwatson/* 55174915Srwatson * Print all scripts (scriptname==NULL) or a specific script. 56174915Srwatson */ 57174915Srwatsonstatic void 58174915Srwatsonddb_list_scripts(const char *scriptname) 59174915Srwatson{ 60174915Srwatson char *buffer, *line, *nextline; 61174915Srwatson char *line_script, *line_scriptname; 62174915Srwatson size_t buflen, len; 63174915Srwatson int ret; 64174915Srwatson 65174915Srwatsonrepeat: 66174915Srwatson if (sysctlbyname(SYSCTL_SCRIPTS, NULL, &buflen, NULL, 0) < 0) 67174915Srwatson err(EX_OSERR, "sysctl: %s", SYSCTL_SCRIPTS); 68174915Srwatson if (buflen == 0) 69174915Srwatson return; 70174915Srwatson buffer = malloc(buflen); 71174915Srwatson if (buffer == NULL) 72174915Srwatson err(EX_OSERR, "malloc"); 73174915Srwatson bzero(buffer, buflen); 74174915Srwatson len = buflen; 75174915Srwatson ret = sysctlbyname(SYSCTL_SCRIPTS, buffer, &len, NULL, 0); 76174915Srwatson if (ret < 0 && errno != ENOMEM) 77174915Srwatson err(EX_OSERR, "sysctl: %s", SYSCTL_SCRIPTS); 78174915Srwatson if (ret < 0) { 79174915Srwatson free(buffer); 80174915Srwatson goto repeat; 81174915Srwatson } 82174915Srwatson 83174915Srwatson /* 84174915Srwatson * We nul'd the buffer before calling sysctl(), so at worst empty. 85174915Srwatson * 86174915Srwatson * If a specific script hasn't been requested, print it all. 87174915Srwatson */ 88174915Srwatson if (scriptname == NULL) { 89174915Srwatson printf("%s", buffer); 90174915Srwatson free(buffer); 91174915Srwatson return; 92174915Srwatson } 93174915Srwatson 94174915Srwatson /* 95174915Srwatson * If a specific script has been requested, we have to parse the 96174915Srwatson * string to find it. 97174915Srwatson */ 98174915Srwatson nextline = buffer; 99174915Srwatson while ((line = strsep(&nextline, "\n")) != NULL) { 100174915Srwatson line_script = line; 101174915Srwatson line_scriptname = strsep(&line_script, "="); 102174915Srwatson if (line_script == NULL) 103174915Srwatson continue; 104174915Srwatson if (strcmp(scriptname, line_scriptname) != 0) 105174915Srwatson continue; 106174915Srwatson printf("%s\n", line_script); 107174915Srwatson break; 108174915Srwatson } 109174915Srwatson if (line == NULL) { 110174915Srwatson errno = ENOENT; 111174915Srwatson err(EX_DATAERR, "%s", scriptname); 112174915Srwatson } 113174915Srwatson free(buffer); 114174915Srwatson} 115174915Srwatson 116174915Srwatson/* 117174915Srwatson * "ddb script" can be used to either print or set a script. 118174915Srwatson */ 119174915Srwatsonvoid 120174915Srwatsonddb_script(int argc, char *argv[]) 121174915Srwatson{ 122174915Srwatson 123174915Srwatson if (argc != 2) 124174915Srwatson usage(); 125174915Srwatson argv++; 126174915Srwatson argc--; 127174915Srwatson if (strchr(argv[0], '=') != 0) { 128174915Srwatson if (sysctlbyname(SYSCTL_SCRIPT, NULL, NULL, argv[0], 129174915Srwatson strlen(argv[0]) + 1) < 0) 130174915Srwatson err(EX_OSERR, "sysctl: %s", SYSCTL_SCRIPTS); 131174915Srwatson } else 132174915Srwatson ddb_list_scripts(argv[0]); 133174915Srwatson} 134174915Srwatson 135174915Srwatsonvoid 136174915Srwatsonddb_scripts(int argc, char *argv[]) 137174915Srwatson{ 138174915Srwatson 139174915Srwatson if (argc != 1) 140174915Srwatson usage(); 141174915Srwatson ddb_list_scripts(NULL); 142174915Srwatson} 143174915Srwatson 144174915Srwatsonvoid 145174915Srwatsonddb_unscript(int argc, char *argv[]) 146174915Srwatson{ 147174915Srwatson int ret; 148174915Srwatson 149174915Srwatson if (argc != 2) 150174915Srwatson usage(); 151174915Srwatson argv++; 152174915Srwatson argc--; 153174915Srwatson ret = sysctlbyname(SYSCTL_UNSCRIPT, NULL, NULL, argv[0], 154174915Srwatson strlen(argv[0]) + 1); 155174915Srwatson if (ret < 0 && errno == EINVAL) { 156174915Srwatson errno = ENOENT; 157174915Srwatson err(EX_DATAERR, "sysctl: %s", argv[0]); 158174915Srwatson } else if (ret < 0) 159174915Srwatson err(EX_OSERR, "sysctl: %s", SYSCTL_UNSCRIPT); 160174915Srwatson} 161