[BACK]Return to mksubr CVS log [TXT][DIR] Up to [local] / src / usr.bin / kdump

File: [local] / src / usr.bin / kdump / mksubr (download)

Revision 1.28, Sun May 17 01:22:01 2015 UTC (9 years ago) by deraadt
Branch: MAIN
CVS Tags: OPENBSD_5_8_BASE, OPENBSD_5_8
Changes since 1.27: +2 -2 lines

isatty() is used by stdio to determine the buffering mode.  Add a F_ISATTY
option to fcntl(), so that isatty() can use this rather than than the bloated
ioctl() interface.  Reducing uses of ioctl() by libc makes it easier to
constrain programs with various kinds of systrace sandboxes.
ok guenther, previously discussed as a concept with nicm

#!/bin/sh
# $OpenBSD: mksubr,v 1.28 2015/05/17 01:22:01 deraadt Exp $
#
# Copyright (c) 2006 David Kirchner <dpk@dpk.net>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# $FreeBSD: src/usr.bin/kdump/mksubr,v 1.17 2011/06/06 19:00:38 dchagin Exp $
#
# Generates kdump_subr.c
# mkioctls is a special-purpose script, and works fine as it is
# now, so it remains independent. The idea behind how it generates
# its list was heavily borrowed here.
#
# Some functions here are automatically generated. This can mean
# the user will see unusual kdump output or errors while building
# if the underlying .h files are changed significantly.
#
# Key:
# AUTO: Completely auto-generated with either the "or" or the "switch"
# method.
# AUTO - Special: Generated automatically, but with some extra commands
# that the auto_*_type() functions are inappropriate for.
# MANUAL: Manually entered and must therefore be manually updated.

set -e

LC_ALL=C; export LC_ALL

if [ -z "$1" ]
then
	echo "usage: sh $0 include-dir"
	exit 1
fi
include_dir=$1

#
# Automatically generates a C function that will print out the
# numeric input as a pipe-delimited string of the appropriate
# #define keys. ex:
# 0x1a4<S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH>
# The XOR is necessary to prevent including the "0"-value in every
# line.
#
auto_or_type () {
	local name grep file
	name=$1
	grep=$2
	file=$3
	format=${4-%#x}

	cat <<_EOF_
/* AUTO */
void
$name (int arg)
{
	int	or = 0;
	printf("$format<", arg);
_EOF_
	egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \
		$include_dir/$file | \
	awk '{ for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		printf "\tif(!((arg>0)^((%s)>0)))\n\t\tif_print_or(arg, %s, or);\n", $i, $i }'
cat <<_EOF_
	printf(">");
	if (or == 0)
		(void)printf("<invalid>%d", arg);
}

_EOF_
}

#
# Like auto_or_type(), but a zero value is valid and prints as "0<>"
#
auto_orz_type () {
	local name grep file
	name=$1
	grep=$2
	file=$3
	format=${4-%#x}

	cat <<_EOF_
/* AUTO */
void
$name (int arg)
{
	int	or = 0;
	if (arg == 0) {
		printf("0<>");
		return;
	}
	printf("$format<", arg);
_EOF_
	egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \
		$include_dir/$file | \
	awk '{ for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		printf "\tif(!((arg>0)^((%s)>0)))\n\t\tif_print_or(arg, %s, or);\n", $i, $i }'
cat <<_EOF_
	printf(">");
	if (or == 0)
		(void)printf("<invalid>%d", arg);
}

_EOF_
}

#
# Automatically generates a C function that will print out a
# file flags input as a pipe-delimited string of the appropriate
# #define keys. ex:
# 0x30000<O_RDONLY|O_CLOEXEC|O_DIRECTORY>
# This is different than the others to handle O_RDONLY correctly when
# other flags are present and to diagnose an invalid O_ACCMODE value
#
auto_fflags_type () {
	local name grep file
	name=$1
	grep=$2
	file=$3

	cat <<_EOF_
/* AUTO */
void
$name (int arg, int show_accmode)
{
	int	or = 0;

	printf("%#x<", arg);
	if (show_accmode || (arg & O_ACCMODE)) {
		or = 1;
		switch (arg & O_ACCMODE) {
		case O_RDONLY:
			printf("O_RDONLY");
			break;
		case O_WRONLY:
			printf("O_WRONLY");
			break;
		case O_RDWR:
			printf("O_RDWR");
			break;
		default:
			printf("<invalid>O_ACCMODE");
			break;
		}
	}
_EOF_
	egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \
		$include_dir/$file | \
	egrep -v 'O_(RD(ONLY|WR)|WRONLY|ACCMODE)' | \
	awk '{ for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		printf "\tif_print_or(arg, %s, or);\n", $i }'
cat <<_EOF_
	printf(">");
}

/*
 * Wrappers of the above to use with pn()
 */
void
flagsname(int flags)
{
	doflagsname(flags, 0);
}

void
openflagsname(int flags)
{
	doflagsname(flags, 1);
}


_EOF_
}


#
# Automatically generates a C function used when the argument
# maps to a single, specific #definition
#
auto_switch_type () {
	local name grep file
	name=$1
	grep=$2
	file=$3

	cat <<_EOF_
/* AUTO */
void
$name (int arg)
{
	switch (arg) {
_EOF_
	egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \
		$include_dir/$file | \
	awk '{ for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		printf "\tcase %s:\n\t\t(void)printf(\"%s\");\n\t\tbreak;\n", $i, $i }'
cat <<_EOF_
	default: /* Should not reach */
		(void)printf("<invalid=%d>", arg);
	}
}

_EOF_
}

#
# Automatically generates a C function used when the argument
# maps to a #definition
#
auto_if_type () {
	local name grep file
	name=$1
	grep=$2
	file=$3

	cat <<_EOF_
/* AUTO */
void
$name (int arg)
{
_EOF_
	egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \
		$include_dir/$file | \
	awk '{ printf "\t"; \
		if (NR > 1) \
			printf "else " ; \
		printf "if (arg == %s) \n\t\tprintf(\"%s\");\n", $2, $2 }'
cat <<_EOF_
	else /* Should not reach */
		(void)printf("<invalid=%d>", arg);
}

_EOF_
}

# C start

cat <<_EOF_
#include <stdio.h>
#include <sys/param.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#define _KERNEL
#include <sys/mman.h>
#undef _KERNEL
#include <sys/wait.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/poll.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
#include <sys/reboot.h>
#include <sys/uio.h>
#include <sys/ktrace.h>
#include <sched.h>
#if 0
#include <sys/linker.h>
#define _KERNEL
#include <sys/thr.h>
#undef _KERNEL
#include <sys/extattr.h>
#include <sys/acl.h>
#include <aio.h>
#endif
#include <sys/sem.h>
#include <sys/ipc.h>
#if 0
#include <sys/rtprio.h>
#endif
#include <sys/shm.h>
#if 0
#include <nfsserver/nfs.h>
#endif
#include <ufs/ufs/quota.h>

#include "kdump_subr.h"

_EOF_

auto_orz_type "modename" "S_[A-Z]+[[:space:]]+[0-6]{7}" "sys/stat.h" "%#o"
auto_fflags_type "doflagsname" "O_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/fcntl.h"
auto_orz_type "atflagsname" "AT_[A-Z_]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/fcntl.h"
auto_or_type "accessmodename" "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+" "sys/unistd.h"
auto_or_type "mmapprotname" "PROT_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/mman.h"
auto_or_type "mmapflagsname" "(__)?MAP_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/mman.h"
auto_orz_type "wait4optname" "W[A-Z]+[[:space:]]+[0-9]+" "sys/wait.h"
#auto_or_type "timerflagsname" "TIMER_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/time.h"
#auto_or_type "getfsstatflagsname" "MNT_[A-Z]+[[:space:]]+[1-9][0-9]*" "sys/mount.h"
auto_or_type "mountflagsname" "MNT_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mount.h"
auto_or_type "rebootoptname" "RB_[A-Z]+[[:space:]]+0x[0-9]+" "sys/reboot.h"
auto_or_type "flockname" "LOCK_[A-Z]+[[:space:]]+0x[0-9]+" "sys/fcntl.h"
#auto_or_type "thrcreateflagsname" "THR_[A-Z]+[[:space:]]+0x[0-9]+" "sys/thr.h"
auto_or_type "mlockallname" "MCL_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h"
auto_orz_type "shmatname" "SHM_[A-Z]+[[:space:]]+[0-9]{6}" "sys/shm.h"
#auto_or_type "nfssvcname" "NFSSVC_[A-Z]+[[:space:]]+0x[0-9]+" "nfsserver/nfs.h"
#
auto_switch_type "whencename" "SEEK_[A-Z]+[[:space:]]+[0-9]+" "sys/unistd.h"
auto_switch_type "pathconfname" "_PC_[_A-Z]+[[:space:]]+[0-9]+" "sys/unistd.h"
auto_switch_type "rlimitname" "RLIMIT_[A-Z]+[[:space:]]+[0-9]+" "sys/resource.h"
auto_switch_type "shutdownhowname" "SHUT_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h"
auto_switch_type "prioname" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.h"
auto_switch_type "madvisebehavname" "_?MADV_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h"
auto_switch_type "msyncflagsname" "MS_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h"
auto_switch_type "clocktypename" "CLOCK_[_A-Z]+[[:space:]]+[0-9]+" "sys/_time.h"
#auto_switch_type "schedpolicyname" "SCHED_[A-Z]+[[:space:]]+[0-9]+" "sched.h"
#auto_switch_type "kldunloadfflagsname" "LINKER_UNLOAD_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h"
#auto_switch_type "extattrctlname" "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/extattr.h"
#auto_switch_type "kldsymcmdname" "KLDSYM_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h"
#auto_switch_type "sendfileflagsname" "SF_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h"
#auto_switch_type "acltypename" "ACL_TYPE_[A-Z4_]+[[:space:]]+0x[0-9]+" "sys/acl.h"
auto_switch_type "rusagewho" "RUSAGE_[A-Z]+[[:space:]]+[-0-9()]+" "sys/resource.h"
auto_orz_type "sigactionflagname" "SA_[A-Z]+[[:space:]]+0x[0-9]+" "sys/signal.h"
auto_switch_type "sigprocmaskhowname" "SIG_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h"
auto_switch_type "sigill_name" "ILL_[A-Z]+[[:space:]]+[0-9]+" "sys/siginfo.h"
auto_switch_type "sigtrap_name" "TRAP_[A-Z]+[[:space:]]+[0-9]+" "sys/siginfo.h"
auto_switch_type "sigemt_name" "EMT_[A-Z]+[[:space:]]+[0-9]+" "sys/siginfo.h"
auto_switch_type "sigfpe_name" "FPE_[A-Z]+[[:space:]]+[0-9]+" "sys/siginfo.h"
auto_switch_type "sigbus_name" "BUS_[A-Z]+[[:space:]]+[0-9]+" "sys/siginfo.h"
auto_switch_type "sigsegv_name" "SEGV_[A-Z]+[[:space:]]+[0-9]+" "sys/siginfo.h"
auto_switch_type "sigchld_name" "CLD_[A-Z]+[[:space:]]+[0-9]+" "sys/siginfo.h"
#auto_switch_type "lio_listioname" "LIO_(NO)?WAIT[[:space:]]+[0-9]+" "aio.h"
auto_switch_type "minheritname" "MAP_INHERIT_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h"
auto_switch_type "quotactlname" "Q_[A-Z]+[[:space:]]+0x[0-9]+" "ufs/ufs/quota.h"
#auto_if_type "sockdomainname" "PF_[[:alnum:]]+[[:space:]]+" "sys/socket.h"
auto_if_type "sockfamilyname" "AF_[[:alnum:]]+[[:space:]]+" "sys/socket.h"
auto_if_type "sockipprotoname" "IPPROTO_[[:alnum:]]+[[:space:]]+" "netinet/in.h"
auto_switch_type "sockoptname" "SO_[A-Z]+[[:space:]]+0x[0-9]+" "sys/socket.h"
#auto_switch_type "ptraceopname" "PT_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/ptrace.h"
auto_orz_type "ktracefacname" "KTRFAC_[^M][[:alnum:]_]+" "sys/ktrace.h"
auto_switch_type "itimername" "ITIMER_[[:alnum:]_]+" "sys/time.h"

cat <<_EOF_
/*
 * AUTO - Special
 * F_ is used to specify fcntl commands as well as arguments. Both sets are
 * grouped in fcntl.h, and this awk script grabs the first group.
 */
void
fcntlcmdname (int arg)
{
	switch (arg1) {
_EOF_
egrep "^#[[:space:]]*define[[:space:]]+F_[A-Z_]+[[:space:]]+[0-9]+[[:space:]]*" \
	$include_dir/sys/fcntl.h | \
	awk 'BEGIN { o=0 } { for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		if (o <= $(i+1)) \
			printf "\tcase %s:\n\t\t(void)printf(\"%s\");\n\t\tbreak;\n", $i, $i; \
		else \
			exit; \
		o = $(i+1) }'
cat <<_EOF_
	default: /* Should not reach */
		(void)printf("<invalid=%d>", arg1);
	}
	if (arg1 == F_SETFD) {
		(void)putchar(',');
		if (arg == FD_CLOEXEC)
			(void)printf("FD_CLOEXEC");
		else if (arg == 0)
			(void)printf("0");
		else
			(void)printf("<invalid>%#x", arg);

	} else if (arg1 == F_SETFL) {
		(void)putchar(',');
		doflagsname(arg, 0);
	} else if (!fancy || (arg1 != F_GETFD && arg1 != F_GETFL && arg1 != F_ISATTY))
		(void)printf(",%#x", arg);
}

/*
 * AUTO - Special
 *
 * The send and recv functions have a flags argument which can be
 * set to 0. There is no corresponding #define. The auto_ functions
 * detect this as "invalid", which is incorrect here.
 */
void
sendrecvflagsname (int flags)
{
	int	or = 0;

	if (flags == 0) {
		(void)printf("0");
		return;
	}

	printf("%#x<", flags);
_EOF_
egrep "^#[[:space:]]*define[[:space:]]+MSG_[_A-Z]+[[:space:]]+0x[0-9]+[[:space:]]*" $include_dir/sys/socket.h | \
	awk '{ for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		printf "\tif(!((flags>0)^((%s)>0)))\n\t\tif_print_or(flags, %s, or);\n", $i, $i }'
cat <<_EOF_
	printf(">");
}

/*
 * AUTO - Special
 *
 * SOCK_NONBLOCK and SOCK_CLOEXEC are or'ed into the type
 */
static void
dosocktypename (int arg, int show_type)
{
	int	type = arg & 0xff;		/* XXX */
	int	or = 0;
	
	printf("%#x<", arg);
	if (show_type || type) {
		or = 1;
		switch (type) {
_EOF_
	egrep "^#[[:space:]]*define[[:space:]]+SOCK_[A-Z]+[[:space:]]+[1-9]+[0-9]*[[:space:]]*" \
		$include_dir/sys/socket.h | \
	awk '{ for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		printf "\t\tcase %s:\n\t\t\t(void)printf(\"%s\");\n\t\t\tbreak;\n", $i, $i }'
cat <<_EOF_
		default: /* Should not reach */
			(void)printf("<invalid=%d>", arg);
		}
	}

_EOF_
	egrep "^#[[:space:]]*define[[:space:]]+SOCK_[A-Z]+[[:space:]]+0x[0-9]+[[:space:]]*" \
		$include_dir/sys/socket.h | \
	awk '{ for (i = 1; i <= NF; i++) \
		if ($i ~ /define/) \
			break; \
		++i; \
		printf "\tif_print_or(arg, %s, or);\n", $i }'
cat <<_EOF_
	printf(">");
}

void
socktypename (int arg)
{
	dosocktypename(arg, 1);
}

void
sockflagsname (int arg)
{
	dosocktypename(arg, 0);
}

void
quotactlcmdname(int cmd)
{
	printf("%#x<QCMD(", cmd);
	quotactlname(cmd >> SUBCMDSHIFT);
	switch (cmd & SUBCMDMASK) {
	case USRQUOTA:
		printf(",%s)>", "USRQUOTA");
		break;
	case GRPQUOTA:
		printf(",%s)>", "GRPQUOTA");
		break;
	default:
		printf(",<invalid>%#x)>", cmd & SUBCMDMASK);
		break;
	}
}

_EOF_