update/fix manpage support
. add bsd-style MLINKS to minix man set, restoring aliases (e.g. man add64 -> int64) . update daily cron script to run makewhatis and restore makewhatis in man Makefile (makedb), restores functionality of man -k . netbsd imports of man, mdocml, makewhatis, libutil, apropos . update man.conf with manpage locations, restoring man [-s] <section> . throws out some obsolete manpages
This commit is contained in:
parent
8c9e62b299
commit
0c3983b25a
248 changed files with 29174 additions and 13693 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -34,3 +34,4 @@ CVS
|
||||||
minix-port.patch
|
minix-port.patch
|
||||||
*.worldstone.log
|
*.worldstone.log
|
||||||
.worldstone*
|
.worldstone*
|
||||||
|
usr.bin/mdocml/man/*.7
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -61,12 +61,14 @@ commands: includes libraries
|
||||||
$(MAKE) -C commands all
|
$(MAKE) -C commands all
|
||||||
$(MAKE) -C bin all
|
$(MAKE) -C bin all
|
||||||
$(MAKE) -C usr.bin all
|
$(MAKE) -C usr.bin all
|
||||||
|
$(MAKE) -C libexec all
|
||||||
|
|
||||||
dep-all:
|
dep-all:
|
||||||
$(MAKE) CC=cc -C boot dependall
|
$(MAKE) CC=cc -C boot dependall
|
||||||
$(MAKE) -C commands dependall
|
$(MAKE) -C commands dependall
|
||||||
$(MAKE) -C bin dependall
|
$(MAKE) -C bin dependall
|
||||||
$(MAKE) -C usr.bin dependall
|
$(MAKE) -C usr.bin dependall
|
||||||
|
$(MAKE) -C libexec dependall
|
||||||
$(MAKE) -C kernel dependall
|
$(MAKE) -C kernel dependall
|
||||||
$(MAKE) -C servers dependall
|
$(MAKE) -C servers dependall
|
||||||
$(MAKE) -C drivers dependall
|
$(MAKE) -C drivers dependall
|
||||||
|
@ -82,10 +84,12 @@ all:
|
||||||
$(MAKE) -C commands all
|
$(MAKE) -C commands all
|
||||||
$(MAKE) -C bin all
|
$(MAKE) -C bin all
|
||||||
$(MAKE) -C usr.bin all
|
$(MAKE) -C usr.bin all
|
||||||
|
$(MAKE) -C libexec all
|
||||||
$(MAKE) -C tools all
|
$(MAKE) -C tools all
|
||||||
|
|
||||||
install:
|
install:
|
||||||
$(MAKE) CC=cc -C boot install
|
$(MAKE) CC=cc -C boot install
|
||||||
|
$(MAKE) -C libexec install
|
||||||
$(MAKE) -C man install makedb
|
$(MAKE) -C man install makedb
|
||||||
$(MAKE) -C commands install
|
$(MAKE) -C commands install
|
||||||
$(MAKE) -C bin install
|
$(MAKE) -C bin install
|
||||||
|
@ -99,6 +103,7 @@ clean: mkfiles
|
||||||
$(MAKE) -C commands clean
|
$(MAKE) -C commands clean
|
||||||
$(MAKE) -C bin clean
|
$(MAKE) -C bin clean
|
||||||
$(MAKE) -C usr.bin clean
|
$(MAKE) -C usr.bin clean
|
||||||
|
$(MAKE) -C libexec clean
|
||||||
$(MAKE) -C tools clean
|
$(MAKE) -C tools clean
|
||||||
$(MAKE) -C lib clean_all
|
$(MAKE) -C lib clean_all
|
||||||
$(MAKE) -C test clean
|
$(MAKE) -C test clean
|
||||||
|
@ -109,4 +114,5 @@ cleandepend: mkfiles
|
||||||
$(MAKE) -C commands cleandepend
|
$(MAKE) -C commands cleandepend
|
||||||
$(MAKE) -C bin cleandepend
|
$(MAKE) -C bin cleandepend
|
||||||
$(MAKE) -C usr.bin cleandepend
|
$(MAKE) -C usr.bin cleandepend
|
||||||
|
$(MAKE) -C libexec cleandepend
|
||||||
$(MAKE) -C tools cleandepend
|
$(MAKE) -C tools cleandepend
|
||||||
|
|
|
@ -16,8 +16,8 @@ SUBDIR= aal add_route adduser arp ash at autil awk \
|
||||||
hostaddr id ifconfig ifdef install \
|
hostaddr id ifconfig ifdef install \
|
||||||
intr ipcrm ipcs irdpd isoread join kill last leave \
|
intr ipcrm ipcs irdpd isoread join kill last leave \
|
||||||
less lex loadkeys loadramdisk logger login look lp \
|
less lex loadkeys loadramdisk logger login look lp \
|
||||||
lpd ls lspci M mail make MAKEDEV man \
|
lpd ls lspci M mail make MAKEDEV \
|
||||||
mdb mdocml mesg mined ackmkdep mkfifo mkfs.mfs mknod \
|
mdb mesg mined ackmkdep mkfifo mkfs.mfs mknod \
|
||||||
mkproto modem mount mt netconf newroot nice acknm nohup \
|
mkproto modem mount mt netconf newroot nice acknm nohup \
|
||||||
nonamed od passwd paste patch pax \
|
nonamed od passwd paste patch pax \
|
||||||
ping postinstall poweroff pr prep printf printroot \
|
ping postinstall poweroff pr prep printf printroot \
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
# $NetBSD: Makefile,v 1.10 2007/10/05 07:38:52 lukem Exp $
|
|
||||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
|
||||||
|
|
||||||
PROG= man
|
|
||||||
SRCS= man.c manconf.c
|
|
||||||
MAN= man.1 man.conf.5
|
|
||||||
|
|
||||||
DPADD+= ${LIBMINIXUTIL}
|
|
||||||
LDADD+= -lminixutil
|
|
||||||
|
|
||||||
FILES=man.conf
|
|
||||||
FILESDIR=/etc
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,6 +0,0 @@
|
||||||
_version BSD.2
|
|
||||||
_subdir man[1-9]
|
|
||||||
_suffix .0
|
|
||||||
_build .[1-9] mandoc %s
|
|
||||||
_build .tbl tbl %s | mandoc
|
|
||||||
_default /usr/man /usr/pkg/X11R6/man /usr/pkg/man /usr/pkg/gcc44/man
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?xml version='1.0' encoding="utf-8"?>
|
|
||||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
|
|
||||||
<xsl:output encoding="utf-8" method="html" indent="yes" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
|
|
||||||
<xsl:template match="/changelog">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>mdocml - CVS-ChangeLog</title>
|
|
||||||
<link rel="stylesheet" href="index.css" type="text/css" media="all" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<xsl:for-each select="entry">
|
|
||||||
<div class="clhead">
|
|
||||||
<xsl:text>Files modified by </xsl:text>
|
|
||||||
<xsl:value-of select="concat(author, ': ', date, ' (', time, ')')" />
|
|
||||||
</div>
|
|
||||||
<div class="clbody">
|
|
||||||
<strong>
|
|
||||||
<xsl:text>Note: </xsl:text>
|
|
||||||
</strong>
|
|
||||||
<xsl:value-of select="msg"/>
|
|
||||||
<ul class="clbody">
|
|
||||||
<xsl:for-each select="file">
|
|
||||||
<li>
|
|
||||||
<xsl:value-of select="name"/>
|
|
||||||
<span class="rev">
|
|
||||||
<xsl:text> — Rev: </xsl:text>
|
|
||||||
<xsl:value-of select="revision"/>
|
|
||||||
<xsl:text>, Status: </xsl:text>
|
|
||||||
<xsl:value-of select="cvsstate"/>
|
|
||||||
<xsl:if test="tag">
|
|
||||||
<xsl:text>, Tag: </xsl:text>
|
|
||||||
<xsl:value-of select="tag" />
|
|
||||||
</xsl:if>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</xsl:for-each>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</xsl:for-each>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
</xsl:template>
|
|
||||||
</xsl:stylesheet>
|
|
|
@ -1,36 +0,0 @@
|
||||||
|
|
||||||
VERSION = 1.10.2
|
|
||||||
VDATE = 19 June 2010
|
|
||||||
|
|
||||||
VFLAGS = -DVERSION="\"$(VERSION)\""
|
|
||||||
|
|
||||||
.if ${CC} == gcc
|
|
||||||
WFLAGS = -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings
|
|
||||||
CFLAGS += -g $(WFLAGS) $(VFLAGS) -DHAVE_CONFIG_H
|
|
||||||
ARFLAGS = rs
|
|
||||||
.else
|
|
||||||
CFLAGS += ${VFLAGS} -DHAVE_CONFIG_H
|
|
||||||
ARFLAGS = r
|
|
||||||
.endif
|
|
||||||
|
|
||||||
# Specify this if you want to hard-code the operating system to appear
|
|
||||||
# in the lower-left hand corner of -mdoc manuals.
|
|
||||||
# CFLAGS += -DOSNAME="\"OpenBSD 4.5\""
|
|
||||||
|
|
||||||
# Unset this if you don't want Xo/Xc allowing split `It' lines, which
|
|
||||||
# breaks symmetry.
|
|
||||||
CFLAGS += -DUGLY
|
|
||||||
|
|
||||||
SRCS = main.c mdoc_term.c chars.c term.c tree.c compat.c \
|
|
||||||
man_term.c html.c mdoc_html.c man_html.c out.c \
|
|
||||||
term_ps.c term_ascii.c man_macro.c man.c man_hash.c \
|
|
||||||
man_validate.c man_action.c mandoc.c man_argv.c roff.c \
|
|
||||||
mdoc_macro.c mdoc.c mdoc_hash.c mdoc_strings.c mdoc_argv.c \
|
|
||||||
mdoc_validate.c mdoc_action.c lib.c att.c arch.c vol.c \
|
|
||||||
msec.c st.c
|
|
||||||
|
|
||||||
MAN = mandoc.1 mdoc.3 mdoc.7 mandoc_char.7 man.7 man.3 roff.7 roff.3
|
|
||||||
|
|
||||||
PROG = mandoc
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,446 +0,0 @@
|
||||||
/* $Id: chars.in,v 1.25 2010/06/19 20:46:27 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The ASCII translation tables. STRING corresponds to predefined
|
|
||||||
* strings (cf. mdoc_samples.7 and tmac/mdoc/doc-nroff). CHAR
|
|
||||||
* corresponds to special characters (cf. groff_char.7). BOTH contains
|
|
||||||
* sequences that are equivalent in both STRING and CHAR.
|
|
||||||
*
|
|
||||||
* Either way, the left-hand side corresponds to the input sequence (\x,
|
|
||||||
* \(xx, \*(xx and so on) whose length is listed second element. The
|
|
||||||
* right-hand side is what's produced by the front-end, with the fourth
|
|
||||||
* element being its length.
|
|
||||||
*
|
|
||||||
* XXX - C-escape strings!
|
|
||||||
* XXX - update LINES_MAX if adding more!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Non-breaking, non-collapsing space uses unit separator. */
|
|
||||||
static const char ascii_nbrsp[2] = { ASCII_NBRSP, 0 };
|
|
||||||
|
|
||||||
CHAR_TBL_START
|
|
||||||
|
|
||||||
/* Spacing. */
|
|
||||||
CHAR("c", 1, "", 0, "", 0)
|
|
||||||
CHAR("0", 1, " ", 1, " ", 7)
|
|
||||||
CHAR(" ", 1, " ", 1, " ", 7)
|
|
||||||
CHAR("~", 1, ascii_nbrsp, 1, " ", 6)
|
|
||||||
CHAR("%", 1, "", 0, "", 0)
|
|
||||||
CHAR("&", 1, "", 0, "", 0)
|
|
||||||
CHAR("^", 1, "", 0, "", 0)
|
|
||||||
CHAR("|", 1, "", 0, "", 0)
|
|
||||||
CHAR("}", 1, "", 0, "", 0)
|
|
||||||
|
|
||||||
/* Accents. */
|
|
||||||
CHAR("a\"", 2, "\"", 1, "̋", 6)
|
|
||||||
CHAR("a-", 2, "-", 1, "¯", 6)
|
|
||||||
CHAR("a.", 2, ".", 1, "˙", 6)
|
|
||||||
CHAR("a^", 2, "^", 1, "̂", 6)
|
|
||||||
BOTH("\'", 1, "\'", 1, "́", 6)
|
|
||||||
BOTH("aa", 2, "\'", 1, "́", 6)
|
|
||||||
BOTH("ga", 2, "`", 1, "̀", 6)
|
|
||||||
BOTH("`", 1, "`", 1, "̀", 6)
|
|
||||||
CHAR("ab", 2, "`", 1, "̆", 6)
|
|
||||||
CHAR("ac", 2, ",", 1, "̧", 6)
|
|
||||||
CHAR("ad", 2, "\"", 1, "̈", 6)
|
|
||||||
CHAR("ah", 2, "v", 1, "ˇ", 6)
|
|
||||||
CHAR("ao", 2, "o", 1, "˚", 6)
|
|
||||||
CHAR("a~", 2, "~", 1, "̃", 6)
|
|
||||||
CHAR("ho", 2, ",", 1, "̨", 6)
|
|
||||||
CHAR("ha", 2, "^", 1, "^", 1)
|
|
||||||
CHAR("ti", 2, "~", 1, "~", 1)
|
|
||||||
|
|
||||||
/* Quotes. */
|
|
||||||
CHAR("Bq", 2, ",,", 2, "„", 7)
|
|
||||||
CHAR("bq", 2, ",", 1, "‚", 7)
|
|
||||||
BOTH("lq", 2, "``", 2, "“", 7)
|
|
||||||
BOTH("rq", 2, "\'\'", 2, "”", 7)
|
|
||||||
CHAR("oq", 2, "`", 1, "‘", 7)
|
|
||||||
CHAR("cq", 2, "\'", 1, "’", 7)
|
|
||||||
CHAR("aq", 2, "\'", 1, "\'", 1)
|
|
||||||
CHAR("dq", 2, "\"", 1, "\"", 1)
|
|
||||||
CHAR("Fo", 2, "<<", 2, "«", 6)
|
|
||||||
CHAR("Fc", 2, ">>", 2, "»", 6)
|
|
||||||
CHAR("fo", 2, "<", 1, "‹", 7)
|
|
||||||
CHAR("fc", 2, ">", 1, "›", 7)
|
|
||||||
|
|
||||||
/* Brackets. */
|
|
||||||
CHAR("lB", 2, "[", 1, "[", 1)
|
|
||||||
CHAR("rB", 2, "]", 1, "]", 1)
|
|
||||||
CHAR("lC", 2, "{", 1, "{", 1)
|
|
||||||
CHAR("rC", 2, "}", 1, "}", 1)
|
|
||||||
CHAR("la", 2, "<", 1, "⟨", 8)
|
|
||||||
CHAR("ra", 2, ">", 1, "⟩", 8)
|
|
||||||
CHAR("bv", 2, "|", 1, "⎪", 7)
|
|
||||||
CHAR("braceex", 7, "|", 1, "⎪", 7)
|
|
||||||
CHAR("bracketlefttp", 13, "|", 1, "⎡", 7)
|
|
||||||
CHAR("bracketleftbp", 13, "|", 1, "⎣", 7)
|
|
||||||
CHAR("bracketleftex", 13, "|", 1, "⎢", 7)
|
|
||||||
CHAR("bracketrighttp", 14, "|", 1, "⎤", 7)
|
|
||||||
CHAR("bracketrightbp", 14, "|", 1, "⎦", 7)
|
|
||||||
CHAR("bracketrightex", 14, "|", 1, "⎥", 7)
|
|
||||||
CHAR("lt", 2, ",-", 2, "⎧", 7)
|
|
||||||
CHAR("bracelefttp", 11, ",-", 2, "⎧", 7)
|
|
||||||
CHAR("lk", 2, "{", 1, "⎨", 7)
|
|
||||||
CHAR("braceleftmid", 12, "{", 1, "⎨", 7)
|
|
||||||
CHAR("lb", 2, ",-", 2, "⎩", 7)
|
|
||||||
CHAR("braceleftbp", 11, "`-", 2, "⎩", 7)
|
|
||||||
CHAR("braceleftex", 11, "|", 1, "⎪", 7)
|
|
||||||
CHAR("rt", 2, "-.", 2, "⎫", 7)
|
|
||||||
CHAR("bracerighttp", 12, "-.", 2, "⎫", 7)
|
|
||||||
CHAR("rk", 2, "}", 1, "⎬", 7)
|
|
||||||
CHAR("bracerightmid", 13, "}", 1, "⎬", 7)
|
|
||||||
CHAR("rb", 2, "-\'", 2, "⎭", 7)
|
|
||||||
CHAR("bracerightbp", 12, "-\'", 2, "⎭", 7)
|
|
||||||
CHAR("bracerightex", 12, "|", 1, "⎪", 7)
|
|
||||||
CHAR("parenlefttp", 11, "/", 1, "⎛", 7)
|
|
||||||
CHAR("parenleftbp", 11, "\\", 1, "⎝", 7)
|
|
||||||
CHAR("parenleftex", 11, "|", 1, "⎜", 7)
|
|
||||||
CHAR("parenrighttp", 12, "\\", 1, "⎞", 7)
|
|
||||||
CHAR("parenrightbp", 12, "/", 1, "⎠", 7)
|
|
||||||
CHAR("parenrightex", 12, "|", 1, "⎟", 7)
|
|
||||||
|
|
||||||
/* Greek characters. */
|
|
||||||
CHAR("*A", 2, "A", 1, "Α", 6)
|
|
||||||
CHAR("*B", 2, "B", 1, "Β", 6)
|
|
||||||
CHAR("*G", 2, "|", 1, "Γ", 6)
|
|
||||||
CHAR("*D", 2, "/\\", 2, "Δ", 6)
|
|
||||||
CHAR("*E", 2, "E", 1, "Ε", 6)
|
|
||||||
CHAR("*Z", 2, "Z", 1, "Ζ", 6)
|
|
||||||
CHAR("*Y", 2, "H", 1, "Η", 6)
|
|
||||||
CHAR("*H", 2, "O", 1, "Θ", 6)
|
|
||||||
CHAR("*I", 2, "I", 1, "Ι", 6)
|
|
||||||
CHAR("*K", 2, "K", 1, "Κ", 6)
|
|
||||||
CHAR("*L", 2, "/\\", 2, "Λ", 6)
|
|
||||||
CHAR("*M", 2, "M", 1, "Μ", 6)
|
|
||||||
CHAR("*N", 2, "N", 1, "Ν", 6)
|
|
||||||
CHAR("*C", 2, "H", 1, "Ξ", 6)
|
|
||||||
CHAR("*O", 2, "O", 1, "Ο", 6)
|
|
||||||
CHAR("*P", 2, "TT", 2, "Π", 6)
|
|
||||||
CHAR("*R", 2, "P", 1, "Ρ", 6)
|
|
||||||
CHAR("*S", 2, ">", 1, "Σ", 6)
|
|
||||||
CHAR("*T", 2, "T", 1, "Τ", 6)
|
|
||||||
CHAR("*U", 2, "Y", 1, "Υ", 6)
|
|
||||||
CHAR("*F", 2, "O_", 1, "Φ", 6)
|
|
||||||
CHAR("*X", 2, "X", 1, "Χ", 6)
|
|
||||||
CHAR("*Q", 2, "Y", 1, "Ψ", 6)
|
|
||||||
CHAR("*W", 2, "O", 1, "Ω", 6)
|
|
||||||
CHAR("*a", 2, "a", 1, "α", 6)
|
|
||||||
CHAR("*b", 2, "B", 1, "β", 6)
|
|
||||||
CHAR("*g", 2, "y", 1, "γ", 6)
|
|
||||||
CHAR("*d", 2, "d", 1, "δ", 6)
|
|
||||||
CHAR("*e", 2, "e", 1, "ε", 6)
|
|
||||||
CHAR("*z", 2, "C", 1, "ζ", 6)
|
|
||||||
CHAR("*y", 2, "n", 1, "η", 6)
|
|
||||||
CHAR("*h", 2, "0", 1, "θ", 6)
|
|
||||||
CHAR("*i", 2, "i", 1, "ι", 6)
|
|
||||||
CHAR("*k", 2, "k", 1, "κ", 6)
|
|
||||||
CHAR("*l", 2, "\\", 1, "λ", 6)
|
|
||||||
CHAR("*m", 2, "u", 1, "μ", 6)
|
|
||||||
CHAR("*n", 2, "v", 1, "ν", 6)
|
|
||||||
CHAR("*c", 2, "E", 1, "ξ", 6)
|
|
||||||
CHAR("*o", 2, "o", 1, "ο", 6)
|
|
||||||
CHAR("*p", 2, "n", 1, "π", 6)
|
|
||||||
CHAR("*r", 2, "p", 1, "ρ", 6)
|
|
||||||
CHAR("*s", 2, "o", 1, "σ", 6)
|
|
||||||
CHAR("*t", 2, "t", 1, "τ", 6)
|
|
||||||
CHAR("*u", 2, "u", 1, "υ", 6)
|
|
||||||
CHAR("*f", 2, "o", 1, "ϕ", 6)
|
|
||||||
CHAR("*x", 2, "x", 1, "χ", 6)
|
|
||||||
CHAR("*q", 2, "u", 1, "ψ", 6)
|
|
||||||
CHAR("*w", 2, "w", 1, "ω", 6)
|
|
||||||
CHAR("+h", 2, "0", 1, "ϑ", 6)
|
|
||||||
CHAR("+f", 2, "o", 1, "φ", 6)
|
|
||||||
CHAR("+p", 2, "w", 1, "ϖ", 6)
|
|
||||||
CHAR("+e", 2, "e", 1, "ϵ", 7)
|
|
||||||
CHAR("ts", 2, "s", 1, "ς", 6)
|
|
||||||
|
|
||||||
/* Accented letters. */
|
|
||||||
CHAR(",C", 2, "C", 1, "Ç", 6)
|
|
||||||
CHAR(",c", 2, "c", 1, "ç", 6)
|
|
||||||
CHAR("/L", 2, "L", 1, "Ł", 6)
|
|
||||||
CHAR("/O", 2, "O", 1, "Ø", 6)
|
|
||||||
CHAR("/l", 2, "l", 1, "ł", 6)
|
|
||||||
CHAR("/o", 2, "o", 1, "ø", 6)
|
|
||||||
CHAR("oA", 2, "A", 1, "Å", 6)
|
|
||||||
CHAR("oa", 2, "a", 1, "å", 6)
|
|
||||||
CHAR(":A", 2, "A", 1, "Ä", 6)
|
|
||||||
CHAR(":E", 2, "E", 1, "Ë", 6)
|
|
||||||
CHAR(":I", 2, "I", 1, "Ï", 6)
|
|
||||||
CHAR(":O", 2, "O", 1, "Ö", 6)
|
|
||||||
CHAR(":U", 2, "U", 1, "Ü", 6)
|
|
||||||
CHAR(":a", 2, "a", 1, "ä", 6)
|
|
||||||
CHAR(":e", 2, "e", 1, "ë", 6)
|
|
||||||
CHAR(":i", 2, "i", 1, "ï", 6)
|
|
||||||
CHAR(":o", 2, "o", 1, "õ", 6)
|
|
||||||
CHAR(":u", 2, "u", 1, "ü", 6)
|
|
||||||
CHAR(":y", 2, "y", 1, "ÿ", 6)
|
|
||||||
CHAR("\'A", 2, "A", 1, "Á", 6)
|
|
||||||
CHAR("\'E", 2, "E", 1, "É", 6)
|
|
||||||
CHAR("\'I", 2, "I", 1, "Í", 6)
|
|
||||||
CHAR("\'O", 2, "O", 1, "Ó", 6)
|
|
||||||
CHAR("\'U", 2, "U", 1, "Ú", 6)
|
|
||||||
CHAR("\'a", 2, "a", 1, "á", 6)
|
|
||||||
CHAR("\'e", 2, "e", 1, "é", 6)
|
|
||||||
CHAR("\'i", 2, "i", 1, "í", 6)
|
|
||||||
CHAR("\'o", 2, "o", 1, "ó", 6)
|
|
||||||
CHAR("\'u", 2, "u", 1, "ú", 6)
|
|
||||||
CHAR("^A", 2, "A", 1, "Â", 6)
|
|
||||||
CHAR("^E", 2, "E", 1, "Ê", 6)
|
|
||||||
CHAR("^I", 2, "I", 1, "Î", 6)
|
|
||||||
CHAR("^O", 2, "O", 1, "Ô", 6)
|
|
||||||
CHAR("^U", 2, "U", 1, "Û", 6)
|
|
||||||
CHAR("^a", 2, "a", 1, "â", 6)
|
|
||||||
CHAR("^e", 2, "e", 1, "ê", 6)
|
|
||||||
CHAR("^i", 2, "i", 1, "î", 6)
|
|
||||||
CHAR("^o", 2, "o", 1, "ô", 6)
|
|
||||||
CHAR("^u", 2, "u", 1, "û", 6)
|
|
||||||
CHAR("`A", 2, "A", 1, "À", 6)
|
|
||||||
CHAR("`E", 2, "E", 1, "È", 6)
|
|
||||||
CHAR("`I", 2, "I", 1, "Ì", 6)
|
|
||||||
CHAR("`O", 2, "O", 1, "Ò", 6)
|
|
||||||
CHAR("`U", 2, "U", 1, "Ù", 6)
|
|
||||||
CHAR("`a", 2, "a", 1, "à", 6)
|
|
||||||
CHAR("`e", 2, "e", 1, "è", 6)
|
|
||||||
CHAR("`i", 2, "i", 1, "ì", 6)
|
|
||||||
CHAR("`o", 2, "o", 1, "ò", 6)
|
|
||||||
CHAR("`u", 2, "u", 1, "ù", 6)
|
|
||||||
CHAR("~A", 2, "A", 1, "Ã", 6)
|
|
||||||
CHAR("~N", 2, "N", 1, "Ñ", 6)
|
|
||||||
CHAR("~O", 2, "O", 1, "Õ", 6)
|
|
||||||
CHAR("~a", 2, "a", 1, "ã", 6)
|
|
||||||
CHAR("~n", 2, "n", 1, "ñ", 6)
|
|
||||||
CHAR("~o", 2, "o", 1, "õ", 6)
|
|
||||||
|
|
||||||
/* Arrows and lines. */
|
|
||||||
CHAR("<-", 2, "<-", 2, "←", 7)
|
|
||||||
CHAR("->", 2, "->", 2, "→", 7)
|
|
||||||
CHAR("<>", 2, "<>", 2, "↔", 7)
|
|
||||||
CHAR("da", 2, "v", 1, "↓", 7)
|
|
||||||
BOTH("ua", 2, "^", 1, "↑", 7)
|
|
||||||
BOTH("va", 2, "^v", 2, "↕", 7)
|
|
||||||
CHAR("lA", 2, "<=", 2, "⇐", 7)
|
|
||||||
CHAR("rA", 2, "=>", 2, "⇒", 7)
|
|
||||||
CHAR("hA", 2, "<=>", 3, "⇔", 7)
|
|
||||||
CHAR("dA", 2, "v", 1, "⇓", 7)
|
|
||||||
CHAR("uA", 2, "^", 1, "⇑", 7)
|
|
||||||
CHAR("vA", 2, "^=v", 3, "⇕", 7)
|
|
||||||
|
|
||||||
/* Logic. */
|
|
||||||
CHAR("AN", 2, "^", 1, "∧", 7)
|
|
||||||
CHAR("OR", 2, "v", 1, "∨", 7)
|
|
||||||
CHAR("no", 2, "~", 1, "¬", 6)
|
|
||||||
CHAR("tno", 3, "~", 1, "¬", 6)
|
|
||||||
CHAR("te", 2, "3", 1, "∃", 7)
|
|
||||||
CHAR("fa", 2, "V", 1, "∀", 7)
|
|
||||||
CHAR("st", 2, "-)", 2, "∋", 7)
|
|
||||||
CHAR("tf", 2, ".:.", 3, "∴", 7)
|
|
||||||
CHAR("3d", 2, ".:.", 3, "∴", 7)
|
|
||||||
CHAR("or", 2, "|", 1, "|", 1)
|
|
||||||
|
|
||||||
/* Mathematicals. */
|
|
||||||
CHAR("pl", 2, "+", 1, "+", 5)
|
|
||||||
CHAR("mi", 2, "-", 1, "−", 7)
|
|
||||||
CHAR("-", 1, "-", 1, "-", 1)
|
|
||||||
CHAR("-+", 2, "-+", 2, "∓", 7)
|
|
||||||
CHAR("+-", 2, "+-", 2, "±", 6)
|
|
||||||
CHAR("t+-", 3, "+-", 2, "±", 6)
|
|
||||||
CHAR("pc", 2, ".", 1, "·", 6)
|
|
||||||
CHAR("md", 2, ".", 1, "⋅", 7)
|
|
||||||
CHAR("mu", 2, "x", 1, "×", 6)
|
|
||||||
CHAR("tmu", 3, "x", 1, "×", 6)
|
|
||||||
CHAR("c*", 2, "x", 1, "⊗", 7)
|
|
||||||
CHAR("c+", 2, "+", 1, "⊕", 7)
|
|
||||||
CHAR("di", 2, "-:-", 3, "÷", 6)
|
|
||||||
CHAR("tdi", 3, "-:-", 3, "÷", 6)
|
|
||||||
CHAR("f/", 2, "/", 1, "⁄", 7)
|
|
||||||
CHAR("**", 2, "*", 1, "∗", 7)
|
|
||||||
BOTH("<=", 2, "<=", 2, "≤", 7)
|
|
||||||
BOTH(">=", 2, ">=", 2, "≥", 7)
|
|
||||||
CHAR("<<", 2, "<<", 2, "≪", 7)
|
|
||||||
CHAR(">>", 2, ">>", 2, "≫", 7)
|
|
||||||
CHAR("eq", 2, "=", 1, "=", 5)
|
|
||||||
CHAR("!=", 2, "!=", 2, "≠", 7)
|
|
||||||
CHAR("==", 2, "==", 2, "≡", 7)
|
|
||||||
CHAR("ne", 2, "!==", 3, "≢", 7)
|
|
||||||
CHAR("=~", 2, "=~", 2, "≅", 7)
|
|
||||||
CHAR("-~", 2, "-~", 2, "≃", 7)
|
|
||||||
CHAR("ap", 2, "~", 1, "∼", 7)
|
|
||||||
CHAR("~~", 2, "~~", 2, "≈", 7)
|
|
||||||
CHAR("~=", 2, "~=", 2, "≌", 7)
|
|
||||||
CHAR("pt", 2, "oc", 2, "∝", 7)
|
|
||||||
CHAR("es", 2, "{}", 2, "∅", 7)
|
|
||||||
CHAR("mo", 2, "E", 1, "∈", 7)
|
|
||||||
CHAR("nm", 2, "!E", 2, "∉", 7)
|
|
||||||
CHAR("sb", 2, "(=", 2, "⊂", 7)
|
|
||||||
CHAR("nb", 2, "(!=", 3, "⊄", 7)
|
|
||||||
CHAR("sp", 2, "=)", 2, "⊃", 7)
|
|
||||||
CHAR("nc", 2, "!=)", 3, "⊅", 7)
|
|
||||||
CHAR("ib", 2, "(=", 2, "⊆", 7)
|
|
||||||
CHAR("ip", 2, "=)", 2, "⊇", 7)
|
|
||||||
CHAR("ca", 2, "(^)", 3, "∩", 7)
|
|
||||||
CHAR("cu", 2, "U", 1, "∪", 7)
|
|
||||||
CHAR("/_", 2, "/_", 2, "∠", 7)
|
|
||||||
CHAR("pp", 2, "_|_", 3, "⊥", 7)
|
|
||||||
CHAR("is", 2, "I", 1, "∫", 7)
|
|
||||||
CHAR("integral", 8, "I", 1, "∫", 7)
|
|
||||||
CHAR("sum", 3, "E", 1, "∑", 7)
|
|
||||||
CHAR("product", 7, "TT", 2, "∏", 7)
|
|
||||||
CHAR("coproduct", 9, "U", 1, "∐", 7)
|
|
||||||
CHAR("gr", 2, "V", 1, "∇", 7)
|
|
||||||
CHAR("sr", 2, "\\/", 2, "√", 7)
|
|
||||||
CHAR("sqrt", 4, "\\/", 2, "√", 7)
|
|
||||||
CHAR("lc", 2, "|~", 2, "⌈", 7)
|
|
||||||
CHAR("rc", 2, "~|", 2, "⌉", 7)
|
|
||||||
CHAR("lf", 2, "|_", 2, "⌊", 7)
|
|
||||||
CHAR("rf", 2, "_|", 2, "⌋", 7)
|
|
||||||
CHAR("if", 2, "oo", 2, "∞", 7)
|
|
||||||
CHAR("Ah", 2, "N", 1, "ℵ", 7)
|
|
||||||
CHAR("Im", 2, "I", 1, "ℑ", 7)
|
|
||||||
CHAR("Re", 2, "R", 1, "ℜ", 7)
|
|
||||||
CHAR("pd", 2, "a", 1, "∂", 7)
|
|
||||||
CHAR("-h", 2, "/h", 2, "ℏ", 7)
|
|
||||||
|
|
||||||
/* Ligatures. */
|
|
||||||
CHAR("ff", 2, "ff", 2, "ff", 8)
|
|
||||||
CHAR("fi", 2, "fi", 2, "fi", 8)
|
|
||||||
CHAR("fl", 2, "fl", 2, "fl", 8)
|
|
||||||
CHAR("Fi", 2, "ffi", 3, "ffi", 8)
|
|
||||||
CHAR("Fl", 2, "ffl", 3, "ffl", 8)
|
|
||||||
BOTH("AE", 2, "AE", 2, "Æ", 6)
|
|
||||||
BOTH("ae", 2, "ae", 2, "æ", 6)
|
|
||||||
CHAR("OE", 2, "OE", 2, "Œ", 6)
|
|
||||||
CHAR("oe", 2, "oe", 2, "œ", 6)
|
|
||||||
CHAR("ss", 2, "ss", 2, "ß", 6)
|
|
||||||
CHAR("IJ", 2, "IJ", 2, "IJ", 6)
|
|
||||||
CHAR("ij", 2, "ij", 2, "ij", 6)
|
|
||||||
|
|
||||||
/* Special letters. */
|
|
||||||
CHAR("-D", 2, "D", 1, "Ð", 6)
|
|
||||||
CHAR("Sd", 2, "o", 1, "ð", 6)
|
|
||||||
CHAR("TP", 2, "b", 1, "Þ", 6)
|
|
||||||
CHAR("Tp", 2, "b", 1, "þ", 6)
|
|
||||||
CHAR(".i", 2, "i", 1, "ı", 6)
|
|
||||||
CHAR(".j", 2, "j", 1, "ȷ", 6)
|
|
||||||
|
|
||||||
/* Currency. */
|
|
||||||
CHAR("Do", 2, "$", 1, "$", 1)
|
|
||||||
CHAR("ct", 2, "c", 1, "¢", 6)
|
|
||||||
CHAR("Eu", 2, "EUR", 3, "€", 7)
|
|
||||||
CHAR("eu", 2, "EUR", 3, "€", 7)
|
|
||||||
CHAR("Ye", 2, "Y", 1, "¥", 6)
|
|
||||||
CHAR("Po", 2, "L", 1, "£", 6)
|
|
||||||
CHAR("Cs", 2, "x", 1, "¤", 6)
|
|
||||||
CHAR("Fn", 2, "f", 1, "ƒ", 6)
|
|
||||||
|
|
||||||
/* pod2man holdovers. */
|
|
||||||
STRING("--", 2, "--", 2, "—", 7)
|
|
||||||
STRING("PI", 2, "pi", 2, "π", 6)
|
|
||||||
STRING("L\"", 2, "``", 2, "“", 7)
|
|
||||||
STRING("R\"", 2, "\'\'", 2, "”", 7)
|
|
||||||
STRING("C+", 2, "C++", 3, "C++", 3)
|
|
||||||
STRING("C`", 2, "`", 1, "‘", 7)
|
|
||||||
STRING("C\'", 2, "\'", 1, "’", 7)
|
|
||||||
STRING("Aq", 2, "\'", 1, "\'", 1)
|
|
||||||
STRING("^", 1, "^", 1, "^", 1)
|
|
||||||
STRING(",", 1, ",", 1, ",", 1)
|
|
||||||
STRING("~", 1, "~", 1, "~", 1)
|
|
||||||
STRING("/", 1, "/", 1, "/", 1)
|
|
||||||
STRING(":", 1, "\"", 1, "̈", 6)
|
|
||||||
STRING("8", 1, "B", 1, "β", 6)
|
|
||||||
STRING("o", 1, "o", 1, "°", 6)
|
|
||||||
STRING("D-", 2, "D", 1, "Ð", 6)
|
|
||||||
STRING("d-", 2, "o", 1, "ð", 6)
|
|
||||||
STRING("Th", 2, "b", 1, "Þ", 6)
|
|
||||||
STRING("th", 2, "b", 1, "þ", 6)
|
|
||||||
|
|
||||||
/* Old style. */
|
|
||||||
STRING("Am", 2, "&", 1, "&", 5)
|
|
||||||
STRING("Ba", 2, "|", 1, "|", 1)
|
|
||||||
STRING("Ge", 2, ">=", 2, "≥", 7)
|
|
||||||
STRING("Gt", 2, ">", 1, ">", 4)
|
|
||||||
STRING("If", 2, "infinity", 8, "infinity", 8)
|
|
||||||
STRING("Le", 2, "<=", 2, "≤", 7)
|
|
||||||
STRING("Lq", 2, "``", 2, "“", 7)
|
|
||||||
STRING("Lt", 2, "<", 1, "<", 4)
|
|
||||||
STRING("Na", 2, "NaN", 3, "NaN", 3)
|
|
||||||
STRING("Ne", 2, "!=", 2, "≠", 7)
|
|
||||||
STRING("Pi", 2, "pi", 2, "π", 6)
|
|
||||||
STRING("Pm", 2, "+-", 2, "±", 6)
|
|
||||||
STRING("R", 1, "(R)", 3, "®", 6)
|
|
||||||
STRING("Rq", 2, "\'\'", 2, "”", 7)
|
|
||||||
STRING("Tm", 2, "tm", 2, "™", 7)
|
|
||||||
STRING("left-bracket", 12, "[", 1, "[", 1)
|
|
||||||
STRING("left-parenthesis", 16, "(", 1, "(", 1)
|
|
||||||
STRING("left-singlequote", 16, "`", 1, "‘", 7)
|
|
||||||
STRING("lp", 2, "(", 1, "(", 1)
|
|
||||||
STRING("q", 1, "\"", 1, """, 6)
|
|
||||||
STRING("quote-left", 10, "`", 1, "‘", 7)
|
|
||||||
STRING("quote-right", 11, "\'", 1, "’", 7)
|
|
||||||
STRING("right-bracket", 13, "]", 1, "]", 1)
|
|
||||||
STRING("right-parenthesis", 17, ")", 1, ")", 1)
|
|
||||||
STRING("right-singlequote", 17, "\'", 1, "’", 7)
|
|
||||||
STRING("rp", 2, ")", 1, ")", 1)
|
|
||||||
|
|
||||||
/* Lines. */
|
|
||||||
CHAR("ba", 2, "|", 1, "|", 6)
|
|
||||||
CHAR("br", 2, "|", 1, "│", 7)
|
|
||||||
CHAR("ul", 2, "_", 1, "_", 5)
|
|
||||||
CHAR("rl", 2, "-", 1, "‾", 7)
|
|
||||||
CHAR("bb", 2, "|", 1, "¦", 6)
|
|
||||||
CHAR("sl", 2, "/", 1, "/", 5)
|
|
||||||
CHAR("rs", 2, "\\", 1, "\", 5)
|
|
||||||
|
|
||||||
/* Text markers. */
|
|
||||||
CHAR("ci", 2, "o", 1, "○", 7)
|
|
||||||
CHAR("bu", 2, "o", 1, "•", 7)
|
|
||||||
CHAR("dd", 2, "=", 1, "‡", 7)
|
|
||||||
CHAR("dg", 2, "-", 1, "†", 7)
|
|
||||||
CHAR("lz", 2, "<>", 2, "◊", 7)
|
|
||||||
CHAR("sq", 2, "[]", 2, "□", 7)
|
|
||||||
CHAR("ps", 2, "9|", 2, "¶", 6)
|
|
||||||
CHAR("sc", 2, "S", 1, "§", 6)
|
|
||||||
CHAR("lh", 2, "<=", 2, "☜", 7)
|
|
||||||
CHAR("rh", 2, "=>", 2, "☞", 7)
|
|
||||||
CHAR("at", 2, "@", 1, "@", 5)
|
|
||||||
CHAR("sh", 2, "#", 1, "#", 5)
|
|
||||||
CHAR("CR", 2, "_|", 2, "↵", 7)
|
|
||||||
CHAR("OK", 2, "\\/", 2, "✓", 8)
|
|
||||||
|
|
||||||
/* Legal symbols. */
|
|
||||||
CHAR("co", 2, "(C)", 3, "©", 6)
|
|
||||||
CHAR("rg", 2, "(R)", 3, "®", 6)
|
|
||||||
CHAR("tm", 2, "tm", 2, "™", 7)
|
|
||||||
|
|
||||||
/* Punctuation. */
|
|
||||||
CHAR(".", 1, ".", 1, ".", 1)
|
|
||||||
CHAR("r!", 2, "i", 1, "¡", 6)
|
|
||||||
CHAR("r?", 2, "c", 1, "¿", 6)
|
|
||||||
CHAR("em", 2, "--", 2, "—", 7)
|
|
||||||
CHAR("en", 2, "-", 1, "–", 7)
|
|
||||||
CHAR("hy", 2, "-", 1, "‐", 7)
|
|
||||||
CHAR("e", 1, "\\", 1, "\\", 1)
|
|
||||||
|
|
||||||
/* Units. */
|
|
||||||
CHAR("de", 2, "o", 1, "°", 6)
|
|
||||||
CHAR("%0", 2, "%o", 2, "‰", 7)
|
|
||||||
CHAR("fm", 2, "\'", 1, "′", 7)
|
|
||||||
CHAR("sd", 2, "\"", 1, "″", 7)
|
|
||||||
CHAR("mc", 2, "mu", 2, "µ", 6)
|
|
||||||
|
|
||||||
CHAR_TBL_END
|
|
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
#ifndef MANDOC_CONFIG_H
|
|
||||||
#define MANDOC_CONFIG_H
|
|
||||||
|
|
||||||
#define HAVE_STRLCAT
|
|
||||||
#define HAVE_STRLCPY
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#define inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _DIAGASSERT
|
|
||||||
#define _DIAGASSERT assert
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* MANDOC_CONFIG_H */
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/* $Id: example.style.css,v 1.20 2010/04/08 08:17:55 kristaps Exp $ */
|
|
||||||
|
|
||||||
div.body { font-family: monospace;
|
|
||||||
min-width: 580px; width: 580px; } /* Top-most div tag. */
|
|
||||||
|
|
||||||
div.sec-head { font-weight: bold; font-style: normal; } /* Sections (Sh). */
|
|
||||||
div.sec-body { }
|
|
||||||
div.sec-block { }
|
|
||||||
|
|
||||||
div.ssec-head { font-weight: bold; font-style: normal; } /* Sub-sections (Ss). */
|
|
||||||
div.ssec-body { }
|
|
||||||
div.ssec-block { }
|
|
||||||
|
|
||||||
span.addr { } /* Address (Ad). */
|
|
||||||
span.arg { font-style: italic; font-weight: normal; } /* Command argument (Ar). */
|
|
||||||
span.author { } /* Author name (An). */
|
|
||||||
span.bold { font-weight: bold; font-style: normal; } /* Generically bold (SB, BI, IB, BR, RB, B). */
|
|
||||||
span.cmd { font-weight: bold; font-style: normal; } /* Command (Cm). */
|
|
||||||
span.config { font-weight: bold; font-style: normal; } /* Config statement (Cd). */
|
|
||||||
span.define { } /* Defines (Dv). */
|
|
||||||
span.desc { } /* Nd. After em-dash. */
|
|
||||||
span.diag { font-weight: bold; font-style: normal; } /* Diagnostic (Bl -diag). */
|
|
||||||
span.emph { font-style: italic; font-weight: normal; } /* Emphasis (Em). */
|
|
||||||
span.env { } /* Environment variables (Ev). */
|
|
||||||
span.errno { } /* Error string (Er). */
|
|
||||||
span.farg { font-style: italic; font-weight: normal; } /* Function argument (Fa, Fn). */
|
|
||||||
span.file { font-style: italic; font-weight: normal; } /* File (Pa). */
|
|
||||||
span.flag { font-weight: bold; font-style: normal; } /* Flag (Fl, Cm). */
|
|
||||||
span.fname { font-weight: bold; font-style: normal; } /* Function name (Fa, Fn, Rv). */
|
|
||||||
span.ftype { font-style: italic; font-weight: normal; } /* Function types (Ft, Fn). */
|
|
||||||
span.includes { font-weight: bold; font-style: normal; } /* Header includes (In). */
|
|
||||||
span.italic { font-style: italic; font-weight: normal; } /* Generically italic (BI, IB, I). */
|
|
||||||
span.lib { } /* Library (Lb). */
|
|
||||||
span.lit { } /* Literals (Bf -literal). */
|
|
||||||
span.macro { font-weight: bold; font-style: normal; } /* Macro-ish thing (Fd). */
|
|
||||||
span.name { font-weight: bold; font-style: normal; } /* Name of utility (Nm). */
|
|
||||||
span.opt { } /* Options (Op, Oo/Oc). */
|
|
||||||
span.ref { } /* Citations (Rs). */
|
|
||||||
span.ref-auth { } /* Reference author (%A). */
|
|
||||||
span.ref-book { font-style: italic; font-weight: normal; } /* Reference book (%B). */
|
|
||||||
span.ref-city { } /* Reference city (%C). */
|
|
||||||
span.ref-date { } /* Reference date (%D). */
|
|
||||||
span.ref-issue { font-style: italic; font-weight: normal; } /* Reference issuer/publisher (%I). */
|
|
||||||
span.ref-jrnl { font-style: italic; font-weight: normal; } /* Reference journal (%J). */
|
|
||||||
span.ref-num { } /* Reference number (%N). */
|
|
||||||
span.ref-opt { } /* Reference optionals (%O). */
|
|
||||||
span.ref-page { } /* Reference page (%P). */
|
|
||||||
span.ref-corp { } /* Reference corporate/foreign author (%Q). */
|
|
||||||
span.ref-rep { } /* Reference report (%R). */
|
|
||||||
span.ref-title { text-decoration: underline; } /* Reference title (%T). */
|
|
||||||
span.ref-vol { } /* Reference volume (%V). */
|
|
||||||
span.roman { font-style: normal; font-weight: normal; } /* Generic font. */
|
|
||||||
span.small { font-size: smaller; } /* Generically small (SB, SM). */
|
|
||||||
span.symb { font-weight: bold; font-style: normal; } /* Symbols. */
|
|
||||||
span.type { font-style: italic; font-weight: normal; } /* Variable types (Vt). */
|
|
||||||
span.unix { } /* Unices (Ux, Ox, Nx, Fx, Bx, Bsx, Dx). */
|
|
||||||
span.utility { font-weight: bold; font-style: normal; } /* Name of utility (Ex). */
|
|
||||||
span.var { font-weight: bold; font-style: normal; } /* Variables (Rv). */
|
|
||||||
|
|
||||||
a.link-ext { } /* Off-site link (Lk). */
|
|
||||||
a.link-includes { } /* Include-file link (In). */
|
|
||||||
a.link-mail { } /* Mailto links (Mt). */
|
|
||||||
a.link-man { } /* Manual links (Xr). */
|
|
||||||
a.link-ref { } /* Reference section links (%Q). */
|
|
||||||
a.link-sec { } /* Section links (Sx). */
|
|
||||||
|
|
||||||
div.emph { font-style: italic; font-weight: normal; } /* Emphasis (Bl -emphasis). */
|
|
||||||
div.lit { } /* Literal (D1, Bd -literal, Dl, Bd -literal). */
|
|
||||||
div.symb { font-weight: bold; font-style: normal; } /* Symbols (Bl -symbolic). */
|
|
||||||
|
|
||||||
table.footer { } /* Document footer. */
|
|
||||||
table.header { } /* Document header. */
|
|
Binary file not shown.
Before Width: | Height: | Size: 165 B |
|
@ -1,48 +0,0 @@
|
||||||
body { color: #333333;
|
|
||||||
font-size: smaller;
|
|
||||||
font-family: Verdana, Tahoma, Arial, sans-serif; }
|
|
||||||
|
|
||||||
table.frame { max-width: 800px;
|
|
||||||
padding-left: 10px; }
|
|
||||||
|
|
||||||
table { padding-left: 40px; }
|
|
||||||
|
|
||||||
p { padding-left: 40px;
|
|
||||||
text-align: justify; }
|
|
||||||
|
|
||||||
h1 { font-weight: bold;
|
|
||||||
font-size: small;
|
|
||||||
font-family: Verdana, Tahoma, Arial, sans-serif; }
|
|
||||||
|
|
||||||
h2 { font-weight: bold;
|
|
||||||
font-size: small;
|
|
||||||
padding-left: 20px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
font-family: Verdana, Tahoma, Arial, sans-serif; }
|
|
||||||
|
|
||||||
span.nm { color: #000000; font-weight: bold; }
|
|
||||||
|
|
||||||
span.attn { color: #000000; font-weight: bold; }
|
|
||||||
|
|
||||||
span.flag { font-weight: bold; }
|
|
||||||
|
|
||||||
div.head { border-bottom: 1px solid #dddddd;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
text-align: right; }
|
|
||||||
|
|
||||||
div.subhead { font-size: smaller;
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
|
|
||||||
div.foot { border-top: 1px solid #dddddd;
|
|
||||||
padding-top: 5px;
|
|
||||||
font-size: smaller;
|
|
||||||
text-align: right; }
|
|
||||||
|
|
||||||
a.external { background: transparent url(external.png) center right no-repeat;
|
|
||||||
padding-right: 12px; }
|
|
||||||
|
|
||||||
span.date { color: #000000; }
|
|
||||||
|
|
||||||
div.news { margin-bottom: 2em; }
|
|
||||||
|
|
||||||
div.news ul { margin-left: 4em; }
|
|
|
@ -1,420 +0,0 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
|
||||||
<META NAME="resource-type" CONTENT="document">
|
|
||||||
<LINK REL="stylesheet" HREF="index.css" TYPE="text/css" MEDIA="all">
|
|
||||||
<TITLE>mdocml | mdoc macro compiler</TITLE>
|
|
||||||
</HEAD>
|
|
||||||
<BODY>
|
|
||||||
<TABLE CLASS="frame" SUMMARY="[frame]">
|
|
||||||
<COL WIDTH="100%">
|
|
||||||
<TBODY>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
<DIV CLASS="head">
|
|
||||||
<B>mdocml</B> – mdoc macro compiler
|
|
||||||
</DIV>
|
|
||||||
<DIV CLASS="subhead">
|
|
||||||
<A HREF="#description">Description</A> |
|
|
||||||
<A HREF="#sources">Sources</A> |
|
|
||||||
<A HREF="#documentation">Documentation</A> |
|
|
||||||
<A HREF="#contact">Contact</A> |
|
|
||||||
<A HREF="#news">News</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
<H1>
|
|
||||||
<A NAME="description">DESCRIPTION</A>
|
|
||||||
</H1>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<SPAN CLASS="nm">mdocml</SPAN> is a suite of tools compiling <Q>-mdoc</Q>, the roff macro package
|
|
||||||
of choice for BSD manual pages, and <Q>-man</Q>, the predominant historical package for UNIX
|
|
||||||
manuals. The mission of <SPAN CLASS="nm">mdocml</SPAN> is to deprecate <A
|
|
||||||
HREF="http://www.gnu.org/software/groff/" CLASS="external">groff</A>, the GNU roff implementation, for
|
|
||||||
displaying -mdoc pages whilst providing token support for -man.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Why? groff amounts to over 5 MB of source code, most of which is C++ and all of which is GPL. It runs
|
|
||||||
slowly, produces uncertain output, and varies in operation from system to system. mdocml strives to fix
|
|
||||||
this (respectively small, C, ISC-licensed, fast and regular).
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
The core of <SPAN CLASS="nm">mdocml</SPAN> is composed of the <A HREF="mdoc.3.html">libmdoc</A>, <A
|
|
||||||
HREF="man.3.html">libman</A>, and <A HREF="roff.3.html">libroff</A> validating compiler libraries. All
|
|
||||||
are simple, fast libraries operating on memory buffers, so they may be used for a variety of front-ends
|
|
||||||
(terminal-based, CGI and so on). The front-end is <A HREF="mandoc.1.html">mandoc</A>, which formats
|
|
||||||
manuals for display.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
The <SPAN CLASS="nm">mdocml</SPAN> suite is a <A CLASS="external" HREF="http://bsd.lv/">BSD.lv
|
|
||||||
Project</A> member.
|
|
||||||
</P>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
<H1>
|
|
||||||
<A NAME="sources">SOURCES</A>
|
|
||||||
</H1>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Sources correctly build and install on DragonFly BSD, FreeBSD, OpenBSD, NetBSD, GNU/Linux, and many
|
|
||||||
other operating systems, tested variously on i386, AMD64, alpha, and others. The most current version
|
|
||||||
is <SPAN CLASS="attn">@VERSION@</SPAN>, dated <SPAN class="attn">@VDATE@</SPAN>. A full <A
|
|
||||||
HREF="ChangeLog.html">ChangeLog</A> (<A HREF="ChangeLog.txt">txt</A>) is written with each release.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H2>
|
|
||||||
Current
|
|
||||||
</H2>
|
|
||||||
|
|
||||||
<TABLE WIDTH="100%" SUMMARY="Current Sources">
|
|
||||||
<COL WIDTH="200">
|
|
||||||
<COL>
|
|
||||||
<TBODY>
|
|
||||||
<TR>
|
|
||||||
<TD>Source archive</TD>
|
|
||||||
<TD>
|
|
||||||
<A HREF="/snapshots/mdocml.tar.gz">/snapshots/mdocml.tar.gz</A>
|
|
||||||
(<A HREF="/snapshots/mdocml.md5">md5</A>)
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>Online source</TD>
|
|
||||||
<TD>
|
|
||||||
<A HREF="http://mdocml.bsd.lv/cgi-bin/cvsweb/?cvsroot=mdocml">cvsweb</A>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
</TBODY>
|
|
||||||
</TABLE>
|
|
||||||
|
|
||||||
<H2>
|
|
||||||
Downstream
|
|
||||||
</H2>
|
|
||||||
|
|
||||||
<TABLE WIDTH="100%" SUMMARY="Downstream Sources">
|
|
||||||
<COL WIDTH="200">
|
|
||||||
<COL>
|
|
||||||
<TBODY>
|
|
||||||
<TR>
|
|
||||||
<TD>DragonFly BSD</TD>
|
|
||||||
<TD>
|
|
||||||
<A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/usr.bin/mandoc"
|
|
||||||
CLASS="external">usr.bin/mandoc</A>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>FreeBSD</TD>
|
|
||||||
<TD>
|
|
||||||
<A HREF="http://www.freebsd.org/cgi/cvsweb.cgi/ports/textproc/mdocml/"
|
|
||||||
CLASS="external">ports/textproc/mdocml</A>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>NetBSD</TD>
|
|
||||||
<TD>
|
|
||||||
<A HREF="http://cvsweb.netbsd.org/bsdweb.cgi/src/external/bsd/mdocml/"
|
|
||||||
CLASS="external">src/external/bsd/mdocml</A>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>OpenBSD</TD>
|
|
||||||
<TD>
|
|
||||||
<A HREF="http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/mandoc/"
|
|
||||||
CLASS="external">src/usr.bin/mandoc</A>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
</TBODY>
|
|
||||||
</TABLE>
|
|
||||||
|
|
||||||
<H2>
|
|
||||||
Historical
|
|
||||||
</H2>
|
|
||||||
|
|
||||||
<TABLE WIDTH="100%" SUMMARY="Archived Sources">
|
|
||||||
<COL WIDTH="200">
|
|
||||||
<COL>
|
|
||||||
<TBODY>
|
|
||||||
<TR>
|
|
||||||
<TD>Source archive</TD>
|
|
||||||
<TD>
|
|
||||||
<A HREF="/snapshots/">/snapshots/</A>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
</TBODY>
|
|
||||||
</TABLE>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
<H1>
|
|
||||||
<A NAME="documentation">DOCUMENTATION</A>
|
|
||||||
</H1>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
These manuals are generated automatically and refer to the current snapshot.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<TABLE WIDTH="100%" SUMMARY="Documentation">
|
|
||||||
<COL WIDTH="200">
|
|
||||||
<COL>
|
|
||||||
<TBODY>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="man.3.html">man(3)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
man macro compiler library
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="man.3.txt">text</A> | <A HREF="man.3.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="man.7.html">man(7)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
man language reference
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="man.7.txt">text</A> | <A HREF="man.7.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="mandoc.1.html">mandoc(1)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
format and display UNIX manuals
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="mandoc.1.txt">text</A> | <A HREF="mandoc.1.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="mandoc_char.7.html">mandoc_char(7)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
mandoc special characters
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="mandoc_char.7.txt">text</A> | <A HREF="mandoc_char.7.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="mdoc.3.html">mdoc(3)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
mdoc macro compiler library
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="mdoc.3.txt">text</A> | <A HREF="mdoc.3.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="mdoc.7.html">mdoc(7)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
mdoc language reference
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="mdoc.7.txt">text</A> | <A HREF="mdoc.7.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="roff.3.html">roff(3)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
roff macro compiler library
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="roff.3.txt">text</A> | <A HREF="roff.3.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VALIGN="top"><A HREF="roff.7.html">roff(7)</A></TD>
|
|
||||||
<TD VALIGN="top">
|
|
||||||
roff-mandoc language reference
|
|
||||||
<DIV STYLE="font-size: smaller;">
|
|
||||||
<A HREF="roff.7.txt">text</A> | <A HREF="roff.7.ps">postscript</A>
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
</TBODY>
|
|
||||||
</TABLE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
See <Q><A CLASS="external" HREF="http://manpages.bsd.lv">Writing UNIX Manual Pages</A></Q> for a general
|
|
||||||
introduction to manpages and mdoc.
|
|
||||||
</P>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
<H1>
|
|
||||||
<A NAME="contact">CONTACT</A>
|
|
||||||
</H1>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
For all issues related to <SPAN CLASS="nm">mdocml</SPAN>, contact Kristaps Dzonsons, kris<A
|
|
||||||
CLASS="external"
|
|
||||||
HREF="http://mailhide.recaptcha.net/d?k=01M6h_w7twDp58ZgH57eWC_w==&c=Q2DBUt401ePlSeupJFrq_Q=="
|
|
||||||
TITLE="Reveal this e-mail address">...</A>@bsd.lv.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
You may also subscribe to several mailing lists (these require subscription, which is moderated). An
|
|
||||||
archive is not yet available on-line, although you may request one once subscribed.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<TABLE WIDTH="100%" SUMMARY="Mailing Lists">
|
|
||||||
<COL WIDTH="200">
|
|
||||||
<COL>
|
|
||||||
<TBODY>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
disc<A CLASS="external" TITLE="Reveal this e-mail address"
|
|
||||||
HREF="http://www.google.com/recaptcha/mailhide/d?k=01KQ80PFH5n3BBNpF5Gs4sRg==&c=EV1QytpQqTHSItc2IXvZyocgYLPnG5K0JKw_gwMC9yc=">...</A>@mdocml.bsd.lv
|
|
||||||
</TD>
|
|
||||||
<TD>high-level discussions and version announcements</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
tec<A CLASS="external" TITLE="Reveal this e-mail address"
|
|
||||||
HREF="http://www.google.com/recaptcha/mailhide/d?k=01qDX_iV0RlUOarEvb6mR28g==&c=gRXsTjza0NNCFPaYu-Taj2tF0pmYZSc90EZkFkhkxgo=">...</A>@mdocml.bsd.lv
|
|
||||||
</TD>
|
|
||||||
<TD>low-level discussions</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
sou<A CLASS="external" TITLE="Reveal this e-mail address"
|
|
||||||
HREF="http://www.google.com/recaptcha/mailhide/d?k=01prQrAZhhl2EbIwVcRfABsQ==&c=KtTW4Yic9xk-8g40KzJoca4fR3MYXv28g8NC6OQV-T8=">...</A>@mdocml.bsd.lv
|
|
||||||
</TD>
|
|
||||||
<TD>source commit messages</TD>
|
|
||||||
</TR>
|
|
||||||
</TBODY>
|
|
||||||
</TABLE>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
<H1>
|
|
||||||
<A NAME="news">NEWS</A>
|
|
||||||
</H1>
|
|
||||||
<DIV CLASS="news">
|
|
||||||
<P>
|
|
||||||
<SPAN CLASS="date">19-06-2010</SPAN>:
|
|
||||||
version 1.10.2
|
|
||||||
</P>
|
|
||||||
<P>
|
|
||||||
Small release featuring text-decoration in <SPAN CLASS="flag">-Tps</SPAN> output, a few
|
|
||||||
minor relaxations of errors, and some optimisations.
|
|
||||||
</P>
|
|
||||||
</DIV>
|
|
||||||
<DIV CLASS="news">
|
|
||||||
<P>
|
|
||||||
<SPAN CLASS="date">07-06-2010</SPAN>:
|
|
||||||
version 1.10.1
|
|
||||||
</P>
|
|
||||||
<P>
|
|
||||||
This primarily focusses on the <Q>Bl</Q> and <Q>It</Q> macros described in <A
|
|
||||||
HREF="mdoc.7.html">mdoc</A>. Multi-line column support is now fully compatible with
|
|
||||||
groff, as are implicit list entries for columns. Removed manuals.7 in favour of <A
|
|
||||||
CLASS="external" HREF="http://manpages.bsd.lv">http://manpages.bsd.lv</A>. The way we
|
|
||||||
handle the SYNOPSIS section (see the SYNOPSIS documentation in <A
|
|
||||||
HREF="mdoc.7.html#x4d414e55414cx20x535452554354555245">MANUAL STRUCTURE</A>) has also
|
|
||||||
been considerably simplified compared to groff's method. Furthermore, the <SPAN
|
|
||||||
CLASS="flag">-Owidth=width</SPAN> output option has been added to <SPAN
|
|
||||||
CLASS="flag">-Tascii</SPAN> (see <A HREF="mandoc.1.html">mandoc</A>). Lastly, initial
|
|
||||||
PostScript output has been added with the <SPAN CLASS="flag">-Tps</SPAN> option to <A
|
|
||||||
HREF="mandoc.1.html">mandoc</A>. It's brutally simple at the moment: fixed-font, with
|
|
||||||
no font decorations.
|
|
||||||
</P>
|
|
||||||
</DIV>
|
|
||||||
<DIV CLASS="news">
|
|
||||||
<P>
|
|
||||||
<SPAN CLASS="date">29-05-2010</SPAN>:
|
|
||||||
version 1.10.0
|
|
||||||
</P>
|
|
||||||
<P>
|
|
||||||
Release consisting of the results from the m2k10 hackathon and up-merge from OpenBSD.
|
|
||||||
This requires a significant note of thanks to Ingo Schwarze (OpenBSD) and Joerg
|
|
||||||
Sonnenberger (NetBSD) for their hard work, and again to Joerg for hosting m2k10.
|
|
||||||
Highlights (mostly cribbed from Ingo's m2k10 report) follow in no particular order:
|
|
||||||
</P>
|
|
||||||
<UL>
|
|
||||||
<LI>a <A HREF="roff.3.html">libroff</A> preprocessor in front of <A
|
|
||||||
HREF="mdoc.3.html">libmdoc</A> and <A HREF="man.3.html">libman</A> stripping out
|
|
||||||
<A HREF="roff.7.html">roff</A> instructions;</LI>
|
|
||||||
<LI>end-of-sentence (EOS) detection in free-form and macro lines;</LI>
|
|
||||||
<LI>correct handling of tab-separated columnar lists in <SPAN
|
|
||||||
CLASS="flag">-mdoc</SPAN>;</LI>
|
|
||||||
<LI>improved main calling routines to optionally use mmap() for better
|
|
||||||
performance;</LI>
|
|
||||||
<LI>cleaned up exiting when invoked as <SPAN CLASS="flag">-Tlint</SPAN> or over
|
|
||||||
multiple files with <SPAN CLASS="flag">-fign-errors</SPAN>;</LI>
|
|
||||||
<LI>error and warning message handling re-written to be unified for <A
|
|
||||||
HREF="roff.3.html">libroff</A>, <A HREF="mdoc.3.html">libmdoc</A>, and <A
|
|
||||||
HREF="man.3.html">libman</A>;</LI>
|
|
||||||
<LI>handling of badly-nested explicit-scoped macros;</LI>
|
|
||||||
<LI>improved free-form text parsing in <A HREF="man.3.html">libman</A> and <A
|
|
||||||
HREF="mdoc.3.html">libmdoc</A>;</LI>
|
|
||||||
<LI>significant GNU troff compatibility improvements in <SPAN
|
|
||||||
CLASS="flag">-Tascii</SPAN>, largely in terms of spacing;</LI>
|
|
||||||
<LI>a regression framework for making sure the many fragilities of GNU troff
|
|
||||||
aren't trampled in subsequent work;</LI>
|
|
||||||
<LI>support for <SPAN CLASS="flag">-Tascii</SPAN> breaking at hyphens
|
|
||||||
encountered in free-form text;</LI>
|
|
||||||
<LI>and many more minor fixes and improvements (no really, consult <A
|
|
||||||
HREF="http://mdocml.bsd.lv/cgi-bin/cvsweb/?cvsroot=mdocml">cvsweb</A> and see
|
|
||||||
for yourself!).</LI>
|
|
||||||
</UL>
|
|
||||||
</DIV>
|
|
||||||
<DIV CLASS="news">
|
|
||||||
<P>
|
|
||||||
<SPAN CLASS="date">13-05-2010</SPAN>:
|
|
||||||
version 1.9.25
|
|
||||||
</P>
|
|
||||||
<P>
|
|
||||||
Fixed handling of <Q>\*(Ba</Q> escape. Backed out <SPAN
|
|
||||||
CLASS="flag">-fno-ign-chars</SPAN> (pointless complexity). Fixed erroneous
|
|
||||||
breaking of literal lines. Fixed SYNOPSIS breaking lines before non-initial
|
|
||||||
macros. Changed default section ordering. Most importantly, the framework for
|
|
||||||
end-of-sentence double-spacing is in place, now implemented for the
|
|
||||||
<Q>end-of-sentence, end-of-line</Q> rule. This is a stable roll-back point
|
|
||||||
before the mandoc hackathon in Rostock!
|
|
||||||
</P>
|
|
||||||
</DIV>
|
|
||||||
<DIV CLASS="news">
|
|
||||||
<P>
|
|
||||||
<SPAN CLASS="date">09-05-2010</SPAN>:
|
|
||||||
version 1.9.24
|
|
||||||
</P>
|
|
||||||
<P>
|
|
||||||
Rolled back break-at-hyphen. <SPAN CLASS="flag">-DUGLY</SPAN> is now the
|
|
||||||
default (no feature splits!). Free-form text is not de-chunked any more: lines
|
|
||||||
are passed whole-sale into the front-end, including whitespace. Added mailing
|
|
||||||
lists. Lastly, <SPAN CLASS="nm">mdocml</SPAN> is the focus of two <A
|
|
||||||
CLASS="external" HREF="http://socghop.appspot.com/">Google Summer of Code</A>
|
|
||||||
projects this year: <Q><A CLASS="external"
|
|
||||||
HREF="http://netbsd-soc.sourceforge.net/projects/mandoc_ps/">mandoc -Tps</A></Q>
|
|
||||||
(NetBSD) and <Q><A CLASS="external"
|
|
||||||
HREF="http://wiki.freebsd.org/SummerOfCode2010Projects">BSD-licensed
|
|
||||||
Text-Processing Tools</A></Q> (FreeBSD).
|
|
||||||
</P>
|
|
||||||
</DIV>
|
|
||||||
<P>
|
|
||||||
See <A HREF="http://mdocml.bsd.lv/cgi-bin/cvsweb/index.sgml?cvsroot=mdocml">cvsweb</A> for
|
|
||||||
historical notes.
|
|
||||||
</P>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD>
|
|
||||||
<DIV CLASS="foot">
|
|
||||||
Copyright © 2008–2010 Kristaps Dzonsons, $Date: 2010/06/19 20:43:35 $
|
|
||||||
</DIV>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
</TBODY>
|
|
||||||
</TABLE>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
|
@ -1,870 +0,0 @@
|
||||||
/* $Id: main.c,v 1.89 2010/06/19 20:46:27 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "mandoc.h"
|
|
||||||
#include "mdoc.h"
|
|
||||||
#include "man.h"
|
|
||||||
#include "roff.h"
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
|
|
||||||
|
|
||||||
/* FIXME: Intel's compiler? LLVM? pcc? */
|
|
||||||
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ < 2)
|
|
||||||
# if !defined(lint)
|
|
||||||
# define __attribute__(x)
|
|
||||||
# endif
|
|
||||||
#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
|
|
||||||
|
|
||||||
typedef void (*out_mdoc)(void *, const struct mdoc *);
|
|
||||||
typedef void (*out_man)(void *, const struct man *);
|
|
||||||
typedef void (*out_free)(void *);
|
|
||||||
|
|
||||||
struct buf {
|
|
||||||
char *buf;
|
|
||||||
size_t sz;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum intt {
|
|
||||||
INTT_AUTO,
|
|
||||||
INTT_MDOC,
|
|
||||||
INTT_MAN
|
|
||||||
};
|
|
||||||
|
|
||||||
enum outt {
|
|
||||||
OUTT_ASCII = 0,
|
|
||||||
OUTT_TREE,
|
|
||||||
OUTT_HTML,
|
|
||||||
OUTT_XHTML,
|
|
||||||
OUTT_LINT,
|
|
||||||
OUTT_PS
|
|
||||||
};
|
|
||||||
|
|
||||||
struct curparse {
|
|
||||||
const char *file; /* Current parse. */
|
|
||||||
int fd; /* Current parse. */
|
|
||||||
int wflags;
|
|
||||||
/* FIXME: set by max error */
|
|
||||||
#define WARN_WALL (1 << 0) /* All-warnings mask. */
|
|
||||||
#define WARN_WERR (1 << 2) /* Warnings->errors. */
|
|
||||||
int fflags;
|
|
||||||
#define FL_IGN_SCOPE (1 << 0) /* Ignore scope errors. */
|
|
||||||
#define FL_NIGN_ESCAPE (1 << 1) /* Don't ignore bad escapes. */
|
|
||||||
#define FL_NIGN_MACRO (1 << 2) /* Don't ignore bad macros. */
|
|
||||||
#define FL_IGN_ERRORS (1 << 4) /* Ignore failed parse. */
|
|
||||||
#define FL_STRICT FL_NIGN_ESCAPE | \
|
|
||||||
FL_NIGN_MACRO /* ignore nothing */
|
|
||||||
enum intt inttype; /* which parser to use */
|
|
||||||
struct man *man; /* man parser */
|
|
||||||
struct mdoc *mdoc; /* mdoc parser */
|
|
||||||
struct roff *roff; /* roff parser (!NULL) */
|
|
||||||
enum outt outtype; /* which output to use */
|
|
||||||
out_mdoc outmdoc; /* mdoc output ptr */
|
|
||||||
out_man outman; /* man output ptr */
|
|
||||||
out_free outfree; /* free output ptr */
|
|
||||||
void *outdata; /* data for output */
|
|
||||||
char outopts[BUFSIZ]; /* buf of output opts */
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char * const mandocerrs[MANDOCERR_MAX] = {
|
|
||||||
"ok",
|
|
||||||
"text should be uppercase",
|
|
||||||
"sections out of conventional order",
|
|
||||||
"section name repeats",
|
|
||||||
"out of order prologue",
|
|
||||||
"repeated prologue entry",
|
|
||||||
"list type must come first",
|
|
||||||
"bad standard",
|
|
||||||
"bad library",
|
|
||||||
"bad escape sequence",
|
|
||||||
"unterminated quoted string",
|
|
||||||
"argument requires the width argument",
|
|
||||||
"superfluous width argument",
|
|
||||||
"ignoring argument",
|
|
||||||
"bad date argument",
|
|
||||||
"bad width argument",
|
|
||||||
"unknown manual section",
|
|
||||||
"section not in conventional manual section",
|
|
||||||
"end of line whitespace",
|
|
||||||
"scope open on exit",
|
|
||||||
"NAME section must come first",
|
|
||||||
"bad Boolean value",
|
|
||||||
"child violates parent syntax",
|
|
||||||
"bad AT&T symbol",
|
|
||||||
"list type repeated",
|
|
||||||
"display type repeated",
|
|
||||||
"argument repeated",
|
|
||||||
"manual name not yet set",
|
|
||||||
"obsolete macro ignored",
|
|
||||||
"empty macro ignored",
|
|
||||||
"macro not allowed in body",
|
|
||||||
"macro not allowed in prologue",
|
|
||||||
"bad character",
|
|
||||||
"bad NAME section contents",
|
|
||||||
"no blank lines",
|
|
||||||
"no text in this context",
|
|
||||||
"bad comment style",
|
|
||||||
"unknown macro will be lost",
|
|
||||||
"line scope broken",
|
|
||||||
"scope broken",
|
|
||||||
"argument count wrong",
|
|
||||||
"request scope close w/none open",
|
|
||||||
"scope already open",
|
|
||||||
"macro requires line argument(s)",
|
|
||||||
"macro requires body argument(s)",
|
|
||||||
"macro requires argument(s)",
|
|
||||||
"no title in document",
|
|
||||||
"missing list type",
|
|
||||||
"missing display type",
|
|
||||||
"line argument(s) will be lost",
|
|
||||||
"body argument(s) will be lost",
|
|
||||||
"column syntax is inconsistent",
|
|
||||||
"missing font type",
|
|
||||||
"displays may not be nested",
|
|
||||||
"unsupported display type",
|
|
||||||
"no scope to rewind: syntax violated",
|
|
||||||
"scope broken, syntax violated",
|
|
||||||
"line scope broken, syntax violated",
|
|
||||||
"argument count wrong, violates syntax",
|
|
||||||
"child violates parent syntax",
|
|
||||||
"argument count wrong, violates syntax",
|
|
||||||
"no document body",
|
|
||||||
"no document prologue",
|
|
||||||
"utsname system call failed",
|
|
||||||
"memory exhausted",
|
|
||||||
};
|
|
||||||
|
|
||||||
static void fdesc(struct curparse *);
|
|
||||||
static void ffile(const char *, struct curparse *);
|
|
||||||
static int foptions(int *, char *);
|
|
||||||
static struct man *man_init(struct curparse *);
|
|
||||||
static struct mdoc *mdoc_init(struct curparse *);
|
|
||||||
static struct roff *roff_init(struct curparse *);
|
|
||||||
static int moptions(enum intt *, char *);
|
|
||||||
static int mmsg(enum mandocerr, void *,
|
|
||||||
int, int, const char *);
|
|
||||||
static int pset(const char *, int, struct curparse *,
|
|
||||||
struct man **, struct mdoc **);
|
|
||||||
static int toptions(struct curparse *, char *);
|
|
||||||
static void usage(void) __attribute__((noreturn));
|
|
||||||
static void version(void) __attribute__((noreturn));
|
|
||||||
static int woptions(int *, char *);
|
|
||||||
|
|
||||||
static const char *progname;
|
|
||||||
static int with_error;
|
|
||||||
static int with_warning;
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
struct curparse curp;
|
|
||||||
|
|
||||||
progname = strrchr(argv[0], '/');
|
|
||||||
if (progname == NULL)
|
|
||||||
progname = argv[0];
|
|
||||||
else
|
|
||||||
++progname;
|
|
||||||
|
|
||||||
memset(&curp, 0, sizeof(struct curparse));
|
|
||||||
|
|
||||||
curp.inttype = INTT_AUTO;
|
|
||||||
curp.outtype = OUTT_ASCII;
|
|
||||||
|
|
||||||
/* LINTED */
|
|
||||||
while (-1 != (c = getopt(argc, argv, "f:m:O:T:VW:")))
|
|
||||||
switch (c) {
|
|
||||||
case ('f'):
|
|
||||||
if ( ! foptions(&curp.fflags, optarg))
|
|
||||||
return(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case ('m'):
|
|
||||||
if ( ! moptions(&curp.inttype, optarg))
|
|
||||||
return(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case ('O'):
|
|
||||||
(void)strlcat(curp.outopts, optarg, BUFSIZ);
|
|
||||||
(void)strlcat(curp.outopts, ",", BUFSIZ);
|
|
||||||
break;
|
|
||||||
case ('T'):
|
|
||||||
if ( ! toptions(&curp, optarg))
|
|
||||||
return(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case ('W'):
|
|
||||||
if ( ! woptions(&curp.wflags, optarg))
|
|
||||||
return(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case ('V'):
|
|
||||||
version();
|
|
||||||
/* NOTREACHED */
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (NULL == *argv) {
|
|
||||||
curp.file = "<stdin>";
|
|
||||||
curp.fd = STDIN_FILENO;
|
|
||||||
|
|
||||||
fdesc(&curp);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*argv) {
|
|
||||||
ffile(*argv, &curp);
|
|
||||||
|
|
||||||
if (with_error && !(curp.fflags & FL_IGN_ERRORS))
|
|
||||||
break;
|
|
||||||
++argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curp.outfree)
|
|
||||||
(*curp.outfree)(curp.outdata);
|
|
||||||
if (curp.mdoc)
|
|
||||||
mdoc_free(curp.mdoc);
|
|
||||||
if (curp.man)
|
|
||||||
man_free(curp.man);
|
|
||||||
if (curp.roff)
|
|
||||||
roff_free(curp.roff);
|
|
||||||
|
|
||||||
return((with_warning || with_error) ?
|
|
||||||
EXIT_FAILURE : EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
version(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
(void)printf("%s %s\n", progname, VERSION);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
(void)fprintf(stderr, "usage: %s [-V] [-foption] "
|
|
||||||
"[-mformat] [-Ooption] [-Toutput] "
|
|
||||||
"[-Werr] [file...]\n", progname);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct man *
|
|
||||||
man_init(struct curparse *curp)
|
|
||||||
{
|
|
||||||
int pflags;
|
|
||||||
|
|
||||||
/* Defaults from mandoc.1. */
|
|
||||||
|
|
||||||
pflags = MAN_IGN_MACRO | MAN_IGN_ESCAPE;
|
|
||||||
|
|
||||||
if (curp->fflags & FL_NIGN_MACRO)
|
|
||||||
pflags &= ~MAN_IGN_MACRO;
|
|
||||||
if (curp->fflags & FL_NIGN_ESCAPE)
|
|
||||||
pflags &= ~MAN_IGN_ESCAPE;
|
|
||||||
|
|
||||||
return(man_alloc(curp, pflags, mmsg));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct roff *
|
|
||||||
roff_init(struct curparse *curp)
|
|
||||||
{
|
|
||||||
|
|
||||||
return(roff_alloc(mmsg, curp));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct mdoc *
|
|
||||||
mdoc_init(struct curparse *curp)
|
|
||||||
{
|
|
||||||
int pflags;
|
|
||||||
|
|
||||||
/* Defaults from mandoc.1. */
|
|
||||||
|
|
||||||
pflags = MDOC_IGN_MACRO | MDOC_IGN_ESCAPE;
|
|
||||||
|
|
||||||
if (curp->fflags & FL_IGN_SCOPE)
|
|
||||||
pflags |= MDOC_IGN_SCOPE;
|
|
||||||
if (curp->fflags & FL_NIGN_ESCAPE)
|
|
||||||
pflags &= ~MDOC_IGN_ESCAPE;
|
|
||||||
if (curp->fflags & FL_NIGN_MACRO)
|
|
||||||
pflags &= ~MDOC_IGN_MACRO;
|
|
||||||
|
|
||||||
return(mdoc_alloc(curp, pflags, mmsg));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ffile(const char *file, struct curparse *curp)
|
|
||||||
{
|
|
||||||
|
|
||||||
curp->file = file;
|
|
||||||
if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
|
|
||||||
perror(curp->file);
|
|
||||||
with_error = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fdesc(curp);
|
|
||||||
|
|
||||||
if (-1 == close(curp->fd))
|
|
||||||
perror(curp->file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
resize_buf(struct buf *buf, size_t initial)
|
|
||||||
{
|
|
||||||
void *tmp;
|
|
||||||
size_t sz;
|
|
||||||
|
|
||||||
if (buf->sz == 0)
|
|
||||||
sz = initial;
|
|
||||||
else
|
|
||||||
sz = 2 * buf->sz;
|
|
||||||
tmp = realloc(buf->buf, sz);
|
|
||||||
if (NULL == tmp) {
|
|
||||||
perror(NULL);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
buf->buf = tmp;
|
|
||||||
buf->sz = sz;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
size_t off;
|
|
||||||
ssize_t ssz;
|
|
||||||
|
|
||||||
if (-1 == fstat(curp->fd, &st)) {
|
|
||||||
perror(curp->file);
|
|
||||||
with_error = 1;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
/*
|
|
||||||
* If we're a regular file, try just reading in the whole entry
|
|
||||||
* via mmap(). This is faster than reading it into blocks, and
|
|
||||||
* since each file is only a few bytes to begin with, I'm not
|
|
||||||
* concerned that this is going to tank any machines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (S_ISREG(st.st_mode)) {
|
|
||||||
if (st.st_size >= (1U << 31)) {
|
|
||||||
fprintf(stderr, "%s: input too large\n",
|
|
||||||
curp->file);
|
|
||||||
with_error = 1;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
*with_mmap = 1;
|
|
||||||
fb->sz = (size_t)st.st_size;
|
|
||||||
fb->buf = mmap(NULL, fb->sz, PROT_READ,
|
|
||||||
MAP_FILE|MAP_SHARED, curp->fd, 0);
|
|
||||||
if (fb->buf != MAP_FAILED)
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this isn't a regular file (like, say, stdin), then we must
|
|
||||||
* go the old way and just read things in bit by bit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
*with_mmap = 0;
|
|
||||||
off = 0;
|
|
||||||
fb->sz = 0;
|
|
||||||
fb->buf = NULL;
|
|
||||||
for (;;) {
|
|
||||||
if (off == fb->sz) {
|
|
||||||
if (fb->sz == (1U << 31)) {
|
|
||||||
fprintf(stderr, "%s: input too large\n",
|
|
||||||
curp->file);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (! resize_buf(fb, 65536))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off);
|
|
||||||
if (ssz == 0) {
|
|
||||||
fb->sz = off;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
if (ssz == -1) {
|
|
||||||
perror(curp->file);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
off += (size_t)ssz;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(fb->buf);
|
|
||||||
fb->buf = NULL;
|
|
||||||
with_error = 1;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
fdesc(struct curparse *curp)
|
|
||||||
{
|
|
||||||
struct buf ln, blk;
|
|
||||||
int i, pos, lnn, lnn_start, with_mmap, of;
|
|
||||||
enum rofferr re;
|
|
||||||
struct man *man;
|
|
||||||
struct mdoc *mdoc;
|
|
||||||
struct roff *roff;
|
|
||||||
|
|
||||||
man = NULL;
|
|
||||||
mdoc = NULL;
|
|
||||||
roff = NULL;
|
|
||||||
memset(&ln, 0, sizeof(struct buf));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Two buffers: ln and buf. buf is the input file and may be
|
|
||||||
* memory mapped. ln is a line buffer and grows on-demand.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! read_whole_file(curp, &blk, &with_mmap))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (NULL == curp->roff)
|
|
||||||
curp->roff = roff_init(curp);
|
|
||||||
if (NULL == (roff = curp->roff))
|
|
||||||
goto bailout;
|
|
||||||
|
|
||||||
for (i = 0, lnn = 1; i < (int)blk.sz;) {
|
|
||||||
pos = 0;
|
|
||||||
lnn_start = lnn;
|
|
||||||
while (i < (int)blk.sz) {
|
|
||||||
if ('\n' == blk.buf[i]) {
|
|
||||||
++i;
|
|
||||||
++lnn;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Trailing backslash is like a plain character. */
|
|
||||||
if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
|
|
||||||
if (pos >= (int)ln.sz)
|
|
||||||
if (! resize_buf(&ln, 256))
|
|
||||||
goto bailout;
|
|
||||||
ln.buf[pos++] = blk.buf[i++];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Found an escape and at least one other character. */
|
|
||||||
if ('\n' == blk.buf[i + 1]) {
|
|
||||||
/* Escaped newlines are skipped over */
|
|
||||||
i += 2;
|
|
||||||
++lnn;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ('"' == blk.buf[i + 1]) {
|
|
||||||
i += 2;
|
|
||||||
/* Comment, skip to end of line */
|
|
||||||
for (; i < (int)blk.sz; ++i) {
|
|
||||||
if ('\n' == blk.buf[i]) {
|
|
||||||
++i;
|
|
||||||
++lnn;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Backout trailing whitespaces */
|
|
||||||
for (; pos > 0; --pos) {
|
|
||||||
if (ln.buf[pos - 1] != ' ')
|
|
||||||
break;
|
|
||||||
if (pos > 2 && ln.buf[pos - 2] == '\\')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Some other escape sequence, copy and continue. */
|
|
||||||
if (pos + 1 >= (int)ln.sz)
|
|
||||||
if (! resize_buf(&ln, 256))
|
|
||||||
goto bailout;
|
|
||||||
|
|
||||||
ln.buf[pos++] = blk.buf[i++];
|
|
||||||
ln.buf[pos++] = blk.buf[i++];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos >= (int)ln.sz)
|
|
||||||
if (! resize_buf(&ln, 256))
|
|
||||||
goto bailout;
|
|
||||||
ln.buf[pos] = '\0';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A significant amount of complexity is contained by
|
|
||||||
* the roff preprocessor. It's line-oriented but can be
|
|
||||||
* expressed on one line, so we need at times to
|
|
||||||
* readjust our starting point and re-run it. The roff
|
|
||||||
* preprocessor can also readjust the buffers with new
|
|
||||||
* data, so we pass them in wholesale.
|
|
||||||
*/
|
|
||||||
|
|
||||||
of = 0;
|
|
||||||
do {
|
|
||||||
re = roff_parseln(roff, lnn_start,
|
|
||||||
&ln.buf, &ln.sz, of, &of);
|
|
||||||
} while (ROFF_RERUN == re);
|
|
||||||
|
|
||||||
if (ROFF_IGN == re)
|
|
||||||
continue;
|
|
||||||
else if (ROFF_ERR == re)
|
|
||||||
goto bailout;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If input parsers have not been allocated, do so now.
|
|
||||||
* We keep these instanced betwen parsers, but set them
|
|
||||||
* locally per parse routine since we can use different
|
|
||||||
* parsers with each one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! (man || mdoc))
|
|
||||||
if ( ! pset(ln.buf + of, pos - of, curp, &man, &mdoc))
|
|
||||||
goto bailout;
|
|
||||||
|
|
||||||
/* Lastly, push down into the parsers themselves. */
|
|
||||||
|
|
||||||
if (man && ! man_parseln(man, lnn_start, ln.buf, of))
|
|
||||||
goto bailout;
|
|
||||||
if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of))
|
|
||||||
goto bailout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTE a parser may not have been assigned, yet. */
|
|
||||||
|
|
||||||
if ( ! (man || mdoc)) {
|
|
||||||
fprintf(stderr, "%s: Not a manual\n", curp->file);
|
|
||||||
goto bailout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up the parse routine ASTs. */
|
|
||||||
|
|
||||||
if (mdoc && ! mdoc_endparse(mdoc))
|
|
||||||
goto bailout;
|
|
||||||
if (man && ! man_endparse(man))
|
|
||||||
goto bailout;
|
|
||||||
if (roff && ! roff_endparse(roff))
|
|
||||||
goto bailout;
|
|
||||||
|
|
||||||
/* If unset, allocate output dev now (if applicable). */
|
|
||||||
|
|
||||||
if ( ! (curp->outman && curp->outmdoc)) {
|
|
||||||
switch (curp->outtype) {
|
|
||||||
case (OUTT_XHTML):
|
|
||||||
curp->outdata = xhtml_alloc(curp->outopts);
|
|
||||||
break;
|
|
||||||
case (OUTT_HTML):
|
|
||||||
curp->outdata = html_alloc(curp->outopts);
|
|
||||||
break;
|
|
||||||
case (OUTT_ASCII):
|
|
||||||
curp->outdata = ascii_alloc(curp->outopts);
|
|
||||||
curp->outfree = ascii_free;
|
|
||||||
break;
|
|
||||||
case (OUTT_PS):
|
|
||||||
curp->outdata = ps_alloc();
|
|
||||||
curp->outfree = ps_free;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (curp->outtype) {
|
|
||||||
case (OUTT_HTML):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (OUTT_XHTML):
|
|
||||||
curp->outman = html_man;
|
|
||||||
curp->outmdoc = html_mdoc;
|
|
||||||
curp->outfree = html_free;
|
|
||||||
break;
|
|
||||||
case (OUTT_TREE):
|
|
||||||
curp->outman = tree_man;
|
|
||||||
curp->outmdoc = tree_mdoc;
|
|
||||||
break;
|
|
||||||
case (OUTT_ASCII):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (OUTT_PS):
|
|
||||||
curp->outman = terminal_man;
|
|
||||||
curp->outmdoc = terminal_mdoc;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute the out device, if it exists. */
|
|
||||||
|
|
||||||
if (man && curp->outman)
|
|
||||||
(*curp->outman)(curp->outdata, man);
|
|
||||||
if (mdoc && curp->outmdoc)
|
|
||||||
(*curp->outmdoc)(curp->outdata, mdoc);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (mdoc)
|
|
||||||
mdoc_reset(mdoc);
|
|
||||||
if (man)
|
|
||||||
man_reset(man);
|
|
||||||
if (roff)
|
|
||||||
roff_reset(roff);
|
|
||||||
if (ln.buf)
|
|
||||||
free(ln.buf);
|
|
||||||
#ifdef __minix
|
|
||||||
assert(!with_mmap);
|
|
||||||
#else
|
|
||||||
if (with_mmap)
|
|
||||||
munmap(blk.buf, blk.sz);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
free(blk.buf);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
bailout:
|
|
||||||
with_error = 1;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
pset(const char *buf, int pos, struct curparse *curp,
|
|
||||||
struct man **man, struct mdoc **mdoc)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to intuit which kind of manual parser should be used. If
|
|
||||||
* passed in by command-line (-man, -mdoc), then use that
|
|
||||||
* explicitly. If passed as -mandoc, then try to guess from the
|
|
||||||
* line: either skip dot-lines, use -mdoc when finding `.Dt', or
|
|
||||||
* default to -man, which is more lenient.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ('.' == buf[0] || '\'' == buf[0]) {
|
|
||||||
for (i = 1; buf[i]; i++)
|
|
||||||
if (' ' != buf[i] && '\t' != buf[i])
|
|
||||||
break;
|
|
||||||
if (0 == buf[i])
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (curp->inttype) {
|
|
||||||
case (INTT_MDOC):
|
|
||||||
if (NULL == curp->mdoc)
|
|
||||||
curp->mdoc = mdoc_init(curp);
|
|
||||||
if (NULL == (*mdoc = curp->mdoc))
|
|
||||||
return(0);
|
|
||||||
return(1);
|
|
||||||
case (INTT_MAN):
|
|
||||||
if (NULL == curp->man)
|
|
||||||
curp->man = man_init(curp);
|
|
||||||
if (NULL == (*man = curp->man))
|
|
||||||
return(0);
|
|
||||||
return(1);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
|
|
||||||
if (NULL == curp->mdoc)
|
|
||||||
curp->mdoc = mdoc_init(curp);
|
|
||||||
if (NULL == (*mdoc = curp->mdoc))
|
|
||||||
return(0);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == curp->man)
|
|
||||||
curp->man = man_init(curp);
|
|
||||||
if (NULL == (*man = curp->man))
|
|
||||||
return(0);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
moptions(enum intt *tflags, char *arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (0 == strcmp(arg, "doc"))
|
|
||||||
*tflags = INTT_MDOC;
|
|
||||||
else if (0 == strcmp(arg, "andoc"))
|
|
||||||
*tflags = INTT_AUTO;
|
|
||||||
else if (0 == strcmp(arg, "an"))
|
|
||||||
*tflags = INTT_MAN;
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "%s: Bad argument\n", arg);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
toptions(struct curparse *curp, char *arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (0 == strcmp(arg, "ascii"))
|
|
||||||
curp->outtype = OUTT_ASCII;
|
|
||||||
else if (0 == strcmp(arg, "lint")) {
|
|
||||||
curp->outtype = OUTT_LINT;
|
|
||||||
curp->wflags |= WARN_WALL;
|
|
||||||
curp->fflags |= FL_STRICT;
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(arg, "tree"))
|
|
||||||
curp->outtype = OUTT_TREE;
|
|
||||||
else if (0 == strcmp(arg, "html"))
|
|
||||||
curp->outtype = OUTT_HTML;
|
|
||||||
else if (0 == strcmp(arg, "xhtml"))
|
|
||||||
curp->outtype = OUTT_XHTML;
|
|
||||||
else if (0 == strcmp(arg, "ps"))
|
|
||||||
curp->outtype = OUTT_PS;
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "%s: Bad argument\n", arg);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
foptions(int *fflags, char *arg)
|
|
||||||
{
|
|
||||||
char *v, *o;
|
|
||||||
const char *toks[8];
|
|
||||||
|
|
||||||
toks[0] = "ign-scope";
|
|
||||||
toks[1] = "no-ign-escape";
|
|
||||||
toks[2] = "no-ign-macro";
|
|
||||||
toks[3] = "ign-errors";
|
|
||||||
toks[4] = "strict";
|
|
||||||
toks[5] = "ign-escape";
|
|
||||||
toks[6] = NULL;
|
|
||||||
|
|
||||||
while (*arg) {
|
|
||||||
o = arg;
|
|
||||||
switch (getsubopt(&arg, UNCONST(toks), &v)) {
|
|
||||||
case (0):
|
|
||||||
*fflags |= FL_IGN_SCOPE;
|
|
||||||
break;
|
|
||||||
case (1):
|
|
||||||
*fflags |= FL_NIGN_ESCAPE;
|
|
||||||
break;
|
|
||||||
case (2):
|
|
||||||
*fflags |= FL_NIGN_MACRO;
|
|
||||||
break;
|
|
||||||
case (3):
|
|
||||||
*fflags |= FL_IGN_ERRORS;
|
|
||||||
break;
|
|
||||||
case (4):
|
|
||||||
*fflags |= FL_STRICT;
|
|
||||||
break;
|
|
||||||
case (5):
|
|
||||||
*fflags &= ~FL_NIGN_ESCAPE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "%s: Bad argument\n", o);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
woptions(int *wflags, char *arg)
|
|
||||||
{
|
|
||||||
char *v, *o;
|
|
||||||
const char *toks[3];
|
|
||||||
|
|
||||||
toks[0] = "all";
|
|
||||||
toks[1] = "error";
|
|
||||||
toks[2] = NULL;
|
|
||||||
|
|
||||||
while (*arg) {
|
|
||||||
o = arg;
|
|
||||||
switch (getsubopt(&arg, UNCONST(toks), &v)) {
|
|
||||||
case (0):
|
|
||||||
*wflags |= WARN_WALL;
|
|
||||||
break;
|
|
||||||
case (1):
|
|
||||||
*wflags |= WARN_WERR;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "%s: Bad argument\n", o);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
|
|
||||||
{
|
|
||||||
struct curparse *cp;
|
|
||||||
|
|
||||||
cp = (struct curparse *)arg;
|
|
||||||
|
|
||||||
if (t <= MANDOCERR_ERROR) {
|
|
||||||
if ( ! (cp->wflags & WARN_WALL))
|
|
||||||
return(1);
|
|
||||||
with_warning = 1;
|
|
||||||
} else
|
|
||||||
with_error = 1;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s:%d:%d: %s", cp->file,
|
|
||||||
ln, col + 1, mandocerrs[t]);
|
|
||||||
|
|
||||||
if (msg)
|
|
||||||
fprintf(stderr, ": %s", msg);
|
|
||||||
|
|
||||||
fputc('\n', stderr);
|
|
||||||
|
|
||||||
/* This is superfluous, but whatever. */
|
|
||||||
if (t > MANDOCERR_ERROR)
|
|
||||||
return(0);
|
|
||||||
if (cp->wflags & WARN_WERR) {
|
|
||||||
with_error = 1;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
return(1);
|
|
||||||
}
|
|
|
@ -1,280 +0,0 @@
|
||||||
/* $Id: man_action.c,v 1.39 2010/05/26 14:03:54 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "mandoc.h"
|
|
||||||
#include "libman.h"
|
|
||||||
#include "libmandoc.h"
|
|
||||||
|
|
||||||
struct actions {
|
|
||||||
int (*post)(struct man *);
|
|
||||||
};
|
|
||||||
|
|
||||||
static int post_TH(struct man *);
|
|
||||||
static int post_fi(struct man *);
|
|
||||||
static int post_nf(struct man *);
|
|
||||||
static int post_AT(struct man *);
|
|
||||||
static int post_UC(struct man *);
|
|
||||||
|
|
||||||
const struct actions man_actions[MAN_MAX] = {
|
|
||||||
{ NULL }, /* br */
|
|
||||||
{ post_TH }, /* TH */
|
|
||||||
{ NULL }, /* SH */
|
|
||||||
{ NULL }, /* SS */
|
|
||||||
{ NULL }, /* TP */
|
|
||||||
{ NULL }, /* LP */
|
|
||||||
{ NULL }, /* PP */
|
|
||||||
{ NULL }, /* P */
|
|
||||||
{ NULL }, /* IP */
|
|
||||||
{ NULL }, /* HP */
|
|
||||||
{ NULL }, /* SM */
|
|
||||||
{ NULL }, /* SB */
|
|
||||||
{ NULL }, /* BI */
|
|
||||||
{ NULL }, /* IB */
|
|
||||||
{ NULL }, /* BR */
|
|
||||||
{ NULL }, /* RB */
|
|
||||||
{ NULL }, /* R */
|
|
||||||
{ NULL }, /* B */
|
|
||||||
{ NULL }, /* I */
|
|
||||||
{ NULL }, /* IR */
|
|
||||||
{ NULL }, /* RI */
|
|
||||||
{ NULL }, /* na */
|
|
||||||
{ NULL }, /* i */
|
|
||||||
{ NULL }, /* sp */
|
|
||||||
{ post_nf }, /* nf */
|
|
||||||
{ post_fi }, /* fi */
|
|
||||||
{ NULL }, /* r */
|
|
||||||
{ NULL }, /* RE */
|
|
||||||
{ NULL }, /* RS */
|
|
||||||
{ NULL }, /* DT */
|
|
||||||
{ post_UC }, /* UC */
|
|
||||||
{ NULL }, /* PD */
|
|
||||||
{ NULL }, /* Sp */
|
|
||||||
{ post_nf }, /* Vb */
|
|
||||||
{ post_fi }, /* Ve */
|
|
||||||
{ post_AT }, /* AT */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
man_action_post(struct man *m)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (MAN_ACTED & m->last->flags)
|
|
||||||
return(1);
|
|
||||||
m->last->flags |= MAN_ACTED;
|
|
||||||
|
|
||||||
switch (m->last->type) {
|
|
||||||
case (MAN_TEXT):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (MAN_ROOT):
|
|
||||||
return(1);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == man_actions[m->last->tok].post)
|
|
||||||
return(1);
|
|
||||||
return((*man_actions[m->last->tok].post)(m));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
post_fi(struct man *m)
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( ! (MAN_LITERAL & m->flags))
|
|
||||||
if ( ! man_nmsg(m, m->last, MANDOCERR_NOSCOPE))
|
|
||||||
return(0);
|
|
||||||
m->flags &= ~MAN_LITERAL;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
post_nf(struct man *m)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (MAN_LITERAL & m->flags)
|
|
||||||
if ( ! man_nmsg(m, m->last, MANDOCERR_SCOPEREP))
|
|
||||||
return(0);
|
|
||||||
m->flags |= MAN_LITERAL;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
post_TH(struct man *m)
|
|
||||||
{
|
|
||||||
struct man_node *n;
|
|
||||||
|
|
||||||
if (m->meta.title)
|
|
||||||
free(m->meta.title);
|
|
||||||
if (m->meta.vol)
|
|
||||||
free(m->meta.vol);
|
|
||||||
if (m->meta.source)
|
|
||||||
free(m->meta.source);
|
|
||||||
if (m->meta.msec)
|
|
||||||
free(m->meta.msec);
|
|
||||||
if (m->meta.rawdate)
|
|
||||||
free(m->meta.rawdate);
|
|
||||||
|
|
||||||
m->meta.title = m->meta.vol = m->meta.rawdate =
|
|
||||||
m->meta.msec = m->meta.source = NULL;
|
|
||||||
m->meta.date = 0;
|
|
||||||
|
|
||||||
/* ->TITLE<- MSEC DATE SOURCE VOL */
|
|
||||||
|
|
||||||
n = m->last->child;
|
|
||||||
assert(n);
|
|
||||||
m->meta.title = mandoc_strdup(n->string);
|
|
||||||
|
|
||||||
/* TITLE ->MSEC<- DATE SOURCE VOL */
|
|
||||||
|
|
||||||
n = n->next;
|
|
||||||
assert(n);
|
|
||||||
m->meta.msec = mandoc_strdup(n->string);
|
|
||||||
|
|
||||||
/* TITLE MSEC ->DATE<- SOURCE VOL */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to parse the date. If this works, stash the epoch (this
|
|
||||||
* is optimal because we can reformat it in the canonical form).
|
|
||||||
* If it doesn't parse, isn't specified at all, or is an empty
|
|
||||||
* string, then use the current date.
|
|
||||||
*/
|
|
||||||
|
|
||||||
n = n->next;
|
|
||||||
if (n && n->string && *n->string) {
|
|
||||||
m->meta.date = mandoc_a2time
|
|
||||||
(MTIME_ISO_8601, n->string);
|
|
||||||
if (0 == m->meta.date) {
|
|
||||||
if ( ! man_nmsg(m, n, MANDOCERR_BADDATE))
|
|
||||||
return(0);
|
|
||||||
m->meta.rawdate = mandoc_strdup(n->string);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
m->meta.date = time(NULL);
|
|
||||||
|
|
||||||
/* TITLE MSEC DATE ->SOURCE<- VOL */
|
|
||||||
|
|
||||||
if (n && (n = n->next))
|
|
||||||
m->meta.source = mandoc_strdup(n->string);
|
|
||||||
|
|
||||||
/* TITLE MSEC DATE SOURCE ->VOL<- */
|
|
||||||
|
|
||||||
if (n && (n = n->next))
|
|
||||||
m->meta.vol = mandoc_strdup(n->string);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove the `TH' node after we've processed it for our
|
|
||||||
* meta-data.
|
|
||||||
*/
|
|
||||||
man_node_delete(m, m->last);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
post_AT(struct man *m)
|
|
||||||
{
|
|
||||||
static const char * const unix_versions[] = {
|
|
||||||
"7th Edition",
|
|
||||||
"System III",
|
|
||||||
"System V",
|
|
||||||
"System V Release 2",
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *p, *s;
|
|
||||||
struct man_node *n, *nn;
|
|
||||||
|
|
||||||
n = m->last->child;
|
|
||||||
|
|
||||||
if (NULL == n || MAN_TEXT != n->type)
|
|
||||||
p = unix_versions[0];
|
|
||||||
else {
|
|
||||||
s = n->string;
|
|
||||||
if (0 == strcmp(s, "3"))
|
|
||||||
p = unix_versions[0];
|
|
||||||
else if (0 == strcmp(s, "4"))
|
|
||||||
p = unix_versions[1];
|
|
||||||
else if (0 == strcmp(s, "5")) {
|
|
||||||
nn = n->next;
|
|
||||||
if (nn && MAN_TEXT == nn->type && nn->string[0])
|
|
||||||
p = unix_versions[3];
|
|
||||||
else
|
|
||||||
p = unix_versions[2];
|
|
||||||
} else
|
|
||||||
p = unix_versions[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m->meta.source)
|
|
||||||
free(m->meta.source);
|
|
||||||
|
|
||||||
m->meta.source = mandoc_strdup(p);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
post_UC(struct man *m)
|
|
||||||
{
|
|
||||||
static const char * const bsd_versions[] = {
|
|
||||||
"3rd Berkeley Distribution",
|
|
||||||
"4th Berkeley Distribution",
|
|
||||||
"4.2 Berkeley Distribution",
|
|
||||||
"4.3 Berkeley Distribution",
|
|
||||||
"4.4 Berkeley Distribution",
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *p, *s;
|
|
||||||
struct man_node *n;
|
|
||||||
|
|
||||||
n = m->last->child;
|
|
||||||
|
|
||||||
if (NULL == n || MAN_TEXT != n->type)
|
|
||||||
p = bsd_versions[0];
|
|
||||||
else {
|
|
||||||
s = n->string;
|
|
||||||
if (0 == strcmp(s, "3"))
|
|
||||||
p = bsd_versions[0];
|
|
||||||
else if (0 == strcmp(s, "4"))
|
|
||||||
p = bsd_versions[1];
|
|
||||||
else if (0 == strcmp(s, "5"))
|
|
||||||
p = bsd_versions[2];
|
|
||||||
else if (0 == strcmp(s, "6"))
|
|
||||||
p = bsd_versions[3];
|
|
||||||
else if (0 == strcmp(s, "7"))
|
|
||||||
p = bsd_versions[4];
|
|
||||||
else
|
|
||||||
p = bsd_versions[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m->meta.source)
|
|
||||||
free(m->meta.source);
|
|
||||||
|
|
||||||
m->meta.source = mandoc_strdup(p);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
/* $Id: man_argv.c,v 1.4 2010/06/19 20:46:28 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "mandoc.h"
|
|
||||||
#include "libman.h"
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
man_args(struct man *m, int line, int *pos, char *buf, char **v)
|
|
||||||
{
|
|
||||||
|
|
||||||
assert(*pos);
|
|
||||||
assert(' ' != buf[*pos]);
|
|
||||||
|
|
||||||
if (0 == buf[*pos])
|
|
||||||
return(ARGS_EOLN);
|
|
||||||
|
|
||||||
*v = &buf[*pos];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process a quoted literal. A quote begins with a double-quote
|
|
||||||
* and ends with a double-quote NOT preceded by a double-quote.
|
|
||||||
* Whitespace is NOT involved in literal termination.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ('\"' == buf[*pos]) {
|
|
||||||
*v = &buf[++(*pos)];
|
|
||||||
|
|
||||||
for ( ; buf[*pos]; (*pos)++) {
|
|
||||||
if ('\"' != buf[*pos])
|
|
||||||
continue;
|
|
||||||
if ('\"' != buf[*pos + 1])
|
|
||||||
break;
|
|
||||||
(*pos)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == buf[*pos]) {
|
|
||||||
if ( ! man_pmsg(m, line, *pos, MANDOCERR_BADQUOTE))
|
|
||||||
return(ARGS_ERROR);
|
|
||||||
return(ARGS_QWORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[(*pos)++] = 0;
|
|
||||||
|
|
||||||
if (0 == buf[*pos])
|
|
||||||
return(ARGS_QWORD);
|
|
||||||
|
|
||||||
while (' ' == buf[*pos])
|
|
||||||
(*pos)++;
|
|
||||||
|
|
||||||
if (0 == buf[*pos])
|
|
||||||
if ( ! man_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
|
|
||||||
return(ARGS_ERROR);
|
|
||||||
|
|
||||||
return(ARGS_QWORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A non-quoted term progresses until either the end of line or
|
|
||||||
* a non-escaped whitespace.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for ( ; buf[*pos]; (*pos)++)
|
|
||||||
if (' ' == buf[*pos] && '\\' != buf[*pos - 1])
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (0 == buf[*pos])
|
|
||||||
return(ARGS_WORD);
|
|
||||||
|
|
||||||
buf[(*pos)++] = 0;
|
|
||||||
|
|
||||||
while (' ' == buf[*pos])
|
|
||||||
(*pos)++;
|
|
||||||
|
|
||||||
if (0 == buf[*pos])
|
|
||||||
if ( ! man_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
|
|
||||||
return(ARGS_ERROR);
|
|
||||||
|
|
||||||
return(ARGS_WORD);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,328 +0,0 @@
|
||||||
/* $Id: man_validate.c,v 1.44 2010/06/19 20:46:28 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "mandoc.h"
|
|
||||||
#include "libman.h"
|
|
||||||
#include "libmandoc.h"
|
|
||||||
|
|
||||||
#define CHKARGS struct man *m, struct man_node *n
|
|
||||||
|
|
||||||
typedef int (*v_check)(CHKARGS);
|
|
||||||
|
|
||||||
struct man_valid {
|
|
||||||
v_check *pres;
|
|
||||||
v_check *posts;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int check_bline(CHKARGS);
|
|
||||||
static int check_eq0(CHKARGS);
|
|
||||||
static int check_le1(CHKARGS);
|
|
||||||
static int check_ge2(CHKARGS);
|
|
||||||
static int check_le5(CHKARGS);
|
|
||||||
static int check_par(CHKARGS);
|
|
||||||
static int check_part(CHKARGS);
|
|
||||||
static int check_root(CHKARGS);
|
|
||||||
static int check_sec(CHKARGS);
|
|
||||||
static int check_text(CHKARGS);
|
|
||||||
static int check_title(CHKARGS);
|
|
||||||
|
|
||||||
static v_check posts_eq0[] = { check_eq0, NULL };
|
|
||||||
static v_check posts_th[] = { check_ge2, check_le5, check_title, NULL };
|
|
||||||
static v_check posts_par[] = { check_par, NULL };
|
|
||||||
static v_check posts_part[] = { check_part, NULL };
|
|
||||||
static v_check posts_sec[] = { check_sec, NULL };
|
|
||||||
static v_check posts_le1[] = { check_le1, NULL };
|
|
||||||
static v_check pres_bline[] = { check_bline, NULL };
|
|
||||||
|
|
||||||
static const struct man_valid man_valids[MAN_MAX] = {
|
|
||||||
{ NULL, posts_eq0 }, /* br */
|
|
||||||
{ pres_bline, posts_th }, /* TH */
|
|
||||||
{ pres_bline, posts_sec }, /* SH */
|
|
||||||
{ pres_bline, posts_sec }, /* SS */
|
|
||||||
{ pres_bline, posts_par }, /* TP */
|
|
||||||
{ pres_bline, posts_par }, /* LP */
|
|
||||||
{ pres_bline, posts_par }, /* PP */
|
|
||||||
{ pres_bline, posts_par }, /* P */
|
|
||||||
{ pres_bline, posts_par }, /* IP */
|
|
||||||
{ pres_bline, posts_par }, /* HP */
|
|
||||||
{ NULL, NULL }, /* SM */
|
|
||||||
{ NULL, NULL }, /* SB */
|
|
||||||
{ NULL, NULL }, /* BI */
|
|
||||||
{ NULL, NULL }, /* IB */
|
|
||||||
{ NULL, NULL }, /* BR */
|
|
||||||
{ NULL, NULL }, /* RB */
|
|
||||||
{ NULL, NULL }, /* R */
|
|
||||||
{ NULL, NULL }, /* B */
|
|
||||||
{ NULL, NULL }, /* I */
|
|
||||||
{ NULL, NULL }, /* IR */
|
|
||||||
{ NULL, NULL }, /* RI */
|
|
||||||
{ NULL, posts_eq0 }, /* na */
|
|
||||||
{ NULL, NULL }, /* i */
|
|
||||||
{ NULL, posts_le1 }, /* sp */
|
|
||||||
{ pres_bline, posts_eq0 }, /* nf */
|
|
||||||
{ pres_bline, posts_eq0 }, /* fi */
|
|
||||||
{ NULL, NULL }, /* r */
|
|
||||||
{ NULL, NULL }, /* RE */
|
|
||||||
{ NULL, posts_part }, /* RS */
|
|
||||||
{ NULL, NULL }, /* DT */
|
|
||||||
{ NULL, NULL }, /* UC */
|
|
||||||
{ NULL, NULL }, /* PD */
|
|
||||||
{ NULL, posts_le1 }, /* Sp */
|
|
||||||
{ pres_bline, posts_le1 }, /* Vb */
|
|
||||||
{ pres_bline, posts_eq0 }, /* Ve */
|
|
||||||
{ NULL, NULL }, /* AT */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
man_valid_pre(struct man *m, struct man_node *n)
|
|
||||||
{
|
|
||||||
v_check *cp;
|
|
||||||
|
|
||||||
if (MAN_TEXT == n->type)
|
|
||||||
return(1);
|
|
||||||
if (MAN_ROOT == n->type)
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
if (NULL == (cp = man_valids[n->tok].pres))
|
|
||||||
return(1);
|
|
||||||
for ( ; *cp; cp++)
|
|
||||||
if ( ! (*cp)(m, n))
|
|
||||||
return(0);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
man_valid_post(struct man *m)
|
|
||||||
{
|
|
||||||
v_check *cp;
|
|
||||||
|
|
||||||
if (MAN_VALID & m->last->flags)
|
|
||||||
return(1);
|
|
||||||
m->last->flags |= MAN_VALID;
|
|
||||||
|
|
||||||
switch (m->last->type) {
|
|
||||||
case (MAN_TEXT):
|
|
||||||
return(check_text(m, m->last));
|
|
||||||
case (MAN_ROOT):
|
|
||||||
return(check_root(m, m->last));
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == (cp = man_valids[m->last->tok].posts))
|
|
||||||
return(1);
|
|
||||||
for ( ; *cp; cp++)
|
|
||||||
if ( ! (*cp)(m, m->last))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_root(CHKARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (MAN_BLINE & m->flags)
|
|
||||||
return(man_nmsg(m, n, MANDOCERR_SCOPEEXIT));
|
|
||||||
if (MAN_ELINE & m->flags)
|
|
||||||
return(man_nmsg(m, n, MANDOCERR_SCOPEEXIT));
|
|
||||||
|
|
||||||
m->flags &= ~MAN_BLINE;
|
|
||||||
m->flags &= ~MAN_ELINE;
|
|
||||||
|
|
||||||
if (NULL == m->first->child) {
|
|
||||||
man_nmsg(m, n, MANDOCERR_NODOCBODY);
|
|
||||||
return(0);
|
|
||||||
} else if (NULL == m->meta.title) {
|
|
||||||
if ( ! man_nmsg(m, n, MANDOCERR_NOTITLE))
|
|
||||||
return(0);
|
|
||||||
/*
|
|
||||||
* If a title hasn't been set, do so now (by
|
|
||||||
* implication, date and section also aren't set).
|
|
||||||
*
|
|
||||||
* FIXME: this should be in man_action.c.
|
|
||||||
*/
|
|
||||||
m->meta.title = mandoc_strdup("unknown");
|
|
||||||
m->meta.date = time(NULL);
|
|
||||||
m->meta.msec = mandoc_strdup("1");
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_title(CHKARGS)
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
|
|
||||||
assert(n->child);
|
|
||||||
/* FIXME: is this sufficient? */
|
|
||||||
if ('\0' == *n->child->string) {
|
|
||||||
man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (p = n->child->string; '\0' != *p; p++)
|
|
||||||
if (isalpha((u_char)*p) && ! isupper((u_char)*p))
|
|
||||||
if ( ! man_nmsg(m, n, MANDOCERR_UPPERCASE))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_text(CHKARGS)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
int pos, c;
|
|
||||||
|
|
||||||
assert(n->string);
|
|
||||||
|
|
||||||
for (p = n->string, pos = n->pos + 1; *p; p++, pos++) {
|
|
||||||
if ('\\' == *p) {
|
|
||||||
c = mandoc_special(p);
|
|
||||||
if (c) {
|
|
||||||
p += c - 1;
|
|
||||||
pos += c - 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
|
|
||||||
if ( ! (MAN_IGN_ESCAPE & m->pflags) && ! c)
|
|
||||||
return(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('\t' == *p || isprint((u_char)*p) || ASCII_HYPH == *p)
|
|
||||||
continue;
|
|
||||||
if ( ! man_pmsg(m, n->line, pos, MANDOCERR_BADCHAR))
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define INEQ_DEFINE(x, ineq, name) \
|
|
||||||
static int \
|
|
||||||
check_##name(CHKARGS) \
|
|
||||||
{ \
|
|
||||||
if (n->nchild ineq (x)) \
|
|
||||||
return(1); \
|
|
||||||
man_vmsg(m, MANDOCERR_SYNTARGCOUNT, n->line, n->pos, \
|
|
||||||
"line arguments %s %d (have %d)", \
|
|
||||||
#ineq, (x), n->nchild); \
|
|
||||||
return(0); \
|
|
||||||
}
|
|
||||||
|
|
||||||
INEQ_DEFINE(0, ==, eq0)
|
|
||||||
INEQ_DEFINE(1, <=, le1)
|
|
||||||
INEQ_DEFINE(2, >=, ge2)
|
|
||||||
INEQ_DEFINE(5, <=, le5)
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_sec(CHKARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (MAN_HEAD == n->type && 0 == n->nchild) {
|
|
||||||
man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
|
|
||||||
return(0);
|
|
||||||
} else if (MAN_BODY == n->type && 0 == n->nchild)
|
|
||||||
return(man_nmsg(m, n, MANDOCERR_NOBODY));
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_part(CHKARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (MAN_BODY == n->type && 0 == n->nchild)
|
|
||||||
return(man_nmsg(m, n, MANDOCERR_NOBODY));
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_par(CHKARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (MAN_BODY == n->type)
|
|
||||||
switch (n->tok) {
|
|
||||||
case (MAN_IP):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (MAN_HP):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (MAN_TP):
|
|
||||||
/* Body-less lists are ok. */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (n->nchild)
|
|
||||||
break;
|
|
||||||
return(man_nmsg(m, n, MANDOCERR_NOBODY));
|
|
||||||
}
|
|
||||||
if (MAN_HEAD == n->type)
|
|
||||||
switch (n->tok) {
|
|
||||||
case (MAN_PP):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (MAN_P):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (MAN_LP):
|
|
||||||
if (0 == n->nchild)
|
|
||||||
break;
|
|
||||||
return(man_nmsg(m, n, MANDOCERR_ARGSLOST));
|
|
||||||
default:
|
|
||||||
if (n->nchild)
|
|
||||||
break;
|
|
||||||
return(man_nmsg(m, n, MANDOCERR_NOARGS));
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_bline(CHKARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
assert( ! (MAN_ELINE & m->flags));
|
|
||||||
if (MAN_BLINE & m->flags) {
|
|
||||||
man_nmsg(m, n, MANDOCERR_SYNTLINESCOPE);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,396 +0,0 @@
|
||||||
/* $Id: mandoc.c,v 1.19 2010/06/19 20:46:28 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "mandoc.h"
|
|
||||||
#include "libmandoc.h"
|
|
||||||
|
|
||||||
static int a2time(time_t *, const char *, const char *);
|
|
||||||
static int spec_norm(char *, int);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "Normalise" a special string by converting its ASCII_HYPH entries
|
|
||||||
* into actual hyphens.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
spec_norm(char *p, int sz)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < sz; i++)
|
|
||||||
if (ASCII_HYPH == p[i])
|
|
||||||
p[i] = '-';
|
|
||||||
|
|
||||||
return(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
mandoc_special(char *p)
|
|
||||||
{
|
|
||||||
int terminator; /* Terminator for \s. */
|
|
||||||
int lim; /* Limit for N in \s. */
|
|
||||||
int c, i;
|
|
||||||
char *sv;
|
|
||||||
|
|
||||||
sv = p;
|
|
||||||
|
|
||||||
if ('\\' != *p++)
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
|
|
||||||
switch (*p) {
|
|
||||||
case ('\''):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('`'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('q'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ASCII_HYPH):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('-'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('~'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('^'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('%'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('0'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (' '):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('}'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('|'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('&'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('.'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (':'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('c'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('e'):
|
|
||||||
return(spec_norm(sv, 2));
|
|
||||||
case ('s'):
|
|
||||||
if ('\0' == *++p)
|
|
||||||
return(spec_norm(sv, 2));
|
|
||||||
|
|
||||||
c = 2;
|
|
||||||
terminator = 0;
|
|
||||||
lim = 1;
|
|
||||||
|
|
||||||
if (*p == '\'') {
|
|
||||||
lim = 0;
|
|
||||||
terminator = 1;
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
} else if (*p == '[') {
|
|
||||||
lim = 0;
|
|
||||||
terminator = 2;
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
} else if (*p == '(') {
|
|
||||||
lim = 2;
|
|
||||||
terminator = 3;
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == '+' || *p == '-') {
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == '\'') {
|
|
||||||
if (terminator)
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
lim = 0;
|
|
||||||
terminator = 1;
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
} else if (*p == '[') {
|
|
||||||
if (terminator)
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
lim = 0;
|
|
||||||
terminator = 2;
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
} else if (*p == '(') {
|
|
||||||
if (terminator)
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
lim = 2;
|
|
||||||
terminator = 3;
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: needs to handle floating point. */
|
|
||||||
|
|
||||||
if ( ! isdigit((u_char)*p))
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
|
|
||||||
for (i = 0; isdigit((u_char)*p); i++) {
|
|
||||||
if (lim && i >= lim)
|
|
||||||
break;
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (terminator && terminator < 3) {
|
|
||||||
if (1 == terminator && *p != '\'')
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
if (2 == terminator && *p != ']')
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
++p;
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(spec_norm(sv, c));
|
|
||||||
case ('f'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('F'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('*'):
|
|
||||||
if ('\0' == *++p || isspace((u_char)*p))
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
switch (*p) {
|
|
||||||
case ('('):
|
|
||||||
if ('\0' == *++p || isspace((u_char)*p))
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
return(spec_norm(sv, 4));
|
|
||||||
case ('['):
|
|
||||||
for (c = 3, p++; *p && ']' != *p; p++, c++)
|
|
||||||
if (isspace((u_char)*p))
|
|
||||||
break;
|
|
||||||
return(spec_norm(sv, *p == ']' ? c : 0));
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return(spec_norm(sv, 3));
|
|
||||||
case ('('):
|
|
||||||
if ('\0' == *++p || isspace((u_char)*p))
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
if ('\0' == *++p || isspace((u_char)*p))
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
return(spec_norm(sv, 4));
|
|
||||||
case ('['):
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return(spec_norm(sv, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (c = 3, p++; *p && ']' != *p; p++, c++)
|
|
||||||
if (isspace((u_char)*p))
|
|
||||||
break;
|
|
||||||
|
|
||||||
return(spec_norm(sv, *p == ']' ? c : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
mandoc_calloc(size_t num, size_t size)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
ptr = calloc(num, size);
|
|
||||||
if (NULL == ptr) {
|
|
||||||
perror(NULL);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
mandoc_malloc(size_t size)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
ptr = malloc(size);
|
|
||||||
if (NULL == ptr) {
|
|
||||||
perror(NULL);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
mandoc_realloc(void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
|
|
||||||
ptr = realloc(ptr, size);
|
|
||||||
if (NULL == ptr) {
|
|
||||||
perror(NULL);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
mandoc_strdup(const char *ptr)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
p = strdup(ptr);
|
|
||||||
if (NULL == p) {
|
|
||||||
perror(NULL);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
a2time(time_t *t, const char *fmt, const char *p)
|
|
||||||
{
|
|
||||||
struct tm tm;
|
|
||||||
char *pp;
|
|
||||||
|
|
||||||
memset(&tm, 0, sizeof(struct tm));
|
|
||||||
|
|
||||||
pp = strptime(p, fmt, &tm);
|
|
||||||
if (NULL != pp && '\0' == *pp) {
|
|
||||||
*t = mktime(&tm);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert from a manual date string (see mdoc(7) and man(7)) into a
|
|
||||||
* date according to the stipulated date type.
|
|
||||||
*/
|
|
||||||
time_t
|
|
||||||
mandoc_a2time(int flags, const char *p)
|
|
||||||
{
|
|
||||||
time_t t;
|
|
||||||
|
|
||||||
if (MTIME_MDOCDATE & flags) {
|
|
||||||
if (0 == strcmp(p, "$" "Mdocdate$"))
|
|
||||||
return(time(NULL));
|
|
||||||
if (a2time(&t, "$" "Mdocdate: %b %d %Y $", p))
|
|
||||||
return(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MTIME_CANONICAL & flags || MTIME_REDUCED & flags)
|
|
||||||
if (a2time(&t, "%b %d, %Y", p))
|
|
||||||
return(t);
|
|
||||||
|
|
||||||
if (MTIME_ISO_8601 & flags)
|
|
||||||
if (a2time(&t, "%Y-%m-%d", p))
|
|
||||||
return(t);
|
|
||||||
|
|
||||||
if (MTIME_REDUCED & flags) {
|
|
||||||
if (a2time(&t, "%d, %Y", p))
|
|
||||||
return(t);
|
|
||||||
if (a2time(&t, "%Y", p))
|
|
||||||
return(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
mandoc_eos(const char *p, size_t sz)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (0 == sz)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* End-of-sentence recognition must include situations where
|
|
||||||
* some symbols, such as `)', allow prior EOS punctuation to
|
|
||||||
* propogate outward.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for ( ; sz; sz--) {
|
|
||||||
switch (p[(int)sz - 1]) {
|
|
||||||
case ('\"'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('\''):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (']'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (')'):
|
|
||||||
break;
|
|
||||||
case ('.'):
|
|
||||||
/* Escaped periods. */
|
|
||||||
if (sz > 1 && '\\' == p[(int)sz - 2])
|
|
||||||
return(0);
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('!'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('?'):
|
|
||||||
return(1);
|
|
||||||
default:
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
mandoc_hyph(const char *start, const char *c)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Choose whether to break at a hyphenated character. We only
|
|
||||||
* do this if it's free-standing within a word.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Skip first/last character of buffer. */
|
|
||||||
if (c == start || '\0' == *(c + 1))
|
|
||||||
return(0);
|
|
||||||
/* Skip first/last character of word. */
|
|
||||||
if ('\t' == *(c + 1) || '\t' == *(c - 1))
|
|
||||||
return(0);
|
|
||||||
if (' ' == *(c + 1) || ' ' == *(c - 1))
|
|
||||||
return(0);
|
|
||||||
/* Skip double invocations. */
|
|
||||||
if ('-' == *(c + 1) || '-' == *(c - 1))
|
|
||||||
return(0);
|
|
||||||
/* Skip escapes. */
|
|
||||||
if ('\\' == *(c - 1))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
/* $Id: mandoc.h,v 1.12 2010/06/12 11:41:50 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifndef MANDOC_H
|
|
||||||
#define MANDOC_H
|
|
||||||
|
|
||||||
#define ASCII_NBRSP 31 /* non-breaking space */
|
|
||||||
#define ASCII_HYPH 30 /* breakable hyphen */
|
|
||||||
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
|
||||||
|
|
||||||
enum mandocerr {
|
|
||||||
MANDOCERR_OK,
|
|
||||||
MANDOCERR_UPPERCASE, /* text should be uppercase */
|
|
||||||
MANDOCERR_SECOOO, /* sections out of conventional order */
|
|
||||||
MANDOCERR_SECREP, /* section name repeats */
|
|
||||||
MANDOCERR_PROLOGOOO, /* out of order prologue */
|
|
||||||
MANDOCERR_PROLOGREP, /* repeated prologue entry */
|
|
||||||
MANDOCERR_LISTFIRST, /* list type must come first */
|
|
||||||
MANDOCERR_BADSTANDARD, /* bad standard */
|
|
||||||
MANDOCERR_BADLIB, /* bad library */
|
|
||||||
MANDOCERR_BADESCAPE, /* bad escape sequence */
|
|
||||||
MANDOCERR_BADQUOTE, /* unterminated quoted string */
|
|
||||||
MANDOCERR_NOWIDTHARG, /* argument requires the width argument */
|
|
||||||
/* FIXME: merge with MANDOCERR_IGNARGV. */
|
|
||||||
MANDOCERR_WIDTHARG, /* superfluous width argument */
|
|
||||||
MANDOCERR_IGNARGV, /* macro ignoring argv */
|
|
||||||
MANDOCERR_BADDATE, /* bad date argument */
|
|
||||||
MANDOCERR_BADWIDTH, /* bad width argument */
|
|
||||||
MANDOCERR_BADMSEC, /* unknown manual section */
|
|
||||||
MANDOCERR_SECMSEC, /* section not in conventional manual section */
|
|
||||||
MANDOCERR_EOLNSPACE, /* end of line whitespace */
|
|
||||||
MANDOCERR_SCOPEEXIT, /* scope open on exit */
|
|
||||||
#define MANDOCERR_WARNING MANDOCERR_SCOPEEXIT
|
|
||||||
|
|
||||||
MANDOCERR_NAMESECFIRST, /* NAME section must come first */
|
|
||||||
MANDOCERR_BADBOOL, /* bad Boolean value */
|
|
||||||
MANDOCERR_CHILD, /* child violates parent syntax */
|
|
||||||
MANDOCERR_BADATT, /* bad AT&T symbol */
|
|
||||||
MANDOCERR_LISTREP, /* list type repeated */
|
|
||||||
MANDOCERR_DISPREP, /* display type repeated */
|
|
||||||
MANDOCERR_ARGVREP, /* argument repeated */
|
|
||||||
MANDOCERR_NONAME, /* manual name not yet set */
|
|
||||||
MANDOCERR_MACROOBS, /* obsolete macro ignored */
|
|
||||||
MANDOCERR_MACROEMPTY, /* empty macro ignored */
|
|
||||||
MANDOCERR_BADBODY, /* macro not allowed in body */
|
|
||||||
MANDOCERR_BADPROLOG, /* macro not allowed in prologue */
|
|
||||||
MANDOCERR_BADCHAR, /* bad character */
|
|
||||||
MANDOCERR_BADNAMESEC, /* bad NAME section contents */
|
|
||||||
MANDOCERR_NOBLANKLN, /* no blank lines */
|
|
||||||
MANDOCERR_NOTEXT, /* no text in this context */
|
|
||||||
MANDOCERR_BADCOMMENT, /* bad comment style */
|
|
||||||
MANDOCERR_MACRO, /* unknown macro will be lost */
|
|
||||||
MANDOCERR_LINESCOPE, /* line scope broken */
|
|
||||||
MANDOCERR_SCOPE, /* scope broken */
|
|
||||||
MANDOCERR_ARGCOUNT, /* argument count wrong */
|
|
||||||
MANDOCERR_NOSCOPE, /* request scope close w/none open */
|
|
||||||
MANDOCERR_SCOPEREP, /* scope already open */
|
|
||||||
/* FIXME: merge following with MANDOCERR_ARGCOUNT */
|
|
||||||
MANDOCERR_NOARGS, /* macro requires line argument(s) */
|
|
||||||
MANDOCERR_NOBODY, /* macro requires body argument(s) */
|
|
||||||
MANDOCERR_NOARGV, /* macro requires argument(s) */
|
|
||||||
MANDOCERR_NOTITLE, /* no title in document */
|
|
||||||
MANDOCERR_LISTTYPE, /* missing list type */
|
|
||||||
MANDOCERR_DISPTYPE, /* missing display type */
|
|
||||||
MANDOCERR_ARGSLOST, /* line argument(s) will be lost */
|
|
||||||
MANDOCERR_BODYLOST, /* body argument(s) will be lost */
|
|
||||||
#define MANDOCERR_ERROR MANDOCERR_BODYLOST
|
|
||||||
|
|
||||||
MANDOCERR_COLUMNS, /* column syntax is inconsistent */
|
|
||||||
/* FIXME: this should be a MANDOCERR_ERROR */
|
|
||||||
MANDOCERR_FONTTYPE, /* missing font type */
|
|
||||||
/* FIXME: this should be a MANDOCERR_ERROR */
|
|
||||||
MANDOCERR_NESTEDDISP, /* displays may not be nested */
|
|
||||||
MANDOCERR_BADDISP, /* unsupported display type */
|
|
||||||
MANDOCERR_SYNTNOSCOPE, /* request scope close w/none open */
|
|
||||||
MANDOCERR_SYNTSCOPE, /* scope broken, syntax violated */
|
|
||||||
MANDOCERR_SYNTLINESCOPE, /* line scope broken, syntax violated */
|
|
||||||
MANDOCERR_SYNTARGVCOUNT, /* argument count wrong, violates syntax */
|
|
||||||
MANDOCERR_SYNTCHILD, /* child violates parent syntax */
|
|
||||||
MANDOCERR_SYNTARGCOUNT, /* argument count wrong, violates syntax */
|
|
||||||
MANDOCERR_NODOCBODY, /* no document body */
|
|
||||||
MANDOCERR_NODOCPROLOG, /* no document prologue */
|
|
||||||
MANDOCERR_UTSNAME, /* utsname() system call failed */
|
|
||||||
MANDOCERR_MEM, /* memory exhausted */
|
|
||||||
#define MANDOCERR_FATAL MANDOCERR_MEM
|
|
||||||
|
|
||||||
MANDOCERR_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int (*mandocmsg)(enum mandocerr,
|
|
||||||
void *, int, int, const char *);
|
|
||||||
|
|
||||||
__END_DECLS
|
|
||||||
|
|
||||||
#endif /*!MANDOC_H*/
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,399 +0,0 @@
|
||||||
/* $Id: out.c,v 1.16 2010/06/19 20:46:28 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "out.h"
|
|
||||||
|
|
||||||
/* See a2roffdeco(). */
|
|
||||||
#define C2LIM(c, l) do { \
|
|
||||||
(l) = 1; \
|
|
||||||
if ('[' == (c) || '\'' == (c)) \
|
|
||||||
(l) = 0; \
|
|
||||||
else if ('(' == (c)) \
|
|
||||||
(l) = 2; } \
|
|
||||||
while (/* CONSTCOND */ 0)
|
|
||||||
|
|
||||||
/* See a2roffdeco(). */
|
|
||||||
#define C2TERM(c, t) do { \
|
|
||||||
(t) = 0; \
|
|
||||||
if ('\'' == (c)) \
|
|
||||||
(t) = 1; \
|
|
||||||
else if ('[' == (c)) \
|
|
||||||
(t) = 2; \
|
|
||||||
else if ('(' == (c)) \
|
|
||||||
(t) = 3; } \
|
|
||||||
while (/* CONSTCOND */ 0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert a `scaling unit' to a consistent form, or fail. Scaling
|
|
||||||
* units are documented in groff.7, mdoc.7, man.7.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
|
|
||||||
{
|
|
||||||
char buf[BUFSIZ], hasd;
|
|
||||||
int i;
|
|
||||||
enum roffscale unit;
|
|
||||||
|
|
||||||
if ('\0' == *src)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
i = hasd = 0;
|
|
||||||
|
|
||||||
switch (*src) {
|
|
||||||
case ('+'):
|
|
||||||
src++;
|
|
||||||
break;
|
|
||||||
case ('-'):
|
|
||||||
buf[i++] = *src++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('\0' == *src)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
while (i < BUFSIZ) {
|
|
||||||
if ( ! isdigit((u_char)*src)) {
|
|
||||||
if ('.' != *src)
|
|
||||||
break;
|
|
||||||
else if (hasd)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
hasd = 1;
|
|
||||||
}
|
|
||||||
buf[i++] = *src++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BUFSIZ == i || (*src && *(src + 1)))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
buf[i] = '\0';
|
|
||||||
|
|
||||||
switch (*src) {
|
|
||||||
case ('c'):
|
|
||||||
unit = SCALE_CM;
|
|
||||||
break;
|
|
||||||
case ('i'):
|
|
||||||
unit = SCALE_IN;
|
|
||||||
break;
|
|
||||||
case ('P'):
|
|
||||||
unit = SCALE_PC;
|
|
||||||
break;
|
|
||||||
case ('p'):
|
|
||||||
unit = SCALE_PT;
|
|
||||||
break;
|
|
||||||
case ('f'):
|
|
||||||
unit = SCALE_FS;
|
|
||||||
break;
|
|
||||||
case ('v'):
|
|
||||||
unit = SCALE_VS;
|
|
||||||
break;
|
|
||||||
case ('m'):
|
|
||||||
unit = SCALE_EM;
|
|
||||||
break;
|
|
||||||
case ('\0'):
|
|
||||||
if (SCALE_MAX == def)
|
|
||||||
return(0);
|
|
||||||
unit = SCALE_BU;
|
|
||||||
break;
|
|
||||||
case ('u'):
|
|
||||||
unit = SCALE_BU;
|
|
||||||
break;
|
|
||||||
case ('M'):
|
|
||||||
unit = SCALE_MM;
|
|
||||||
break;
|
|
||||||
case ('n'):
|
|
||||||
unit = SCALE_EN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dst->scale = atof(buf)) < 0)
|
|
||||||
dst->scale = 0;
|
|
||||||
dst->unit = unit;
|
|
||||||
dst->pt = hasd;
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Correctly writes the time in nroff form, which differs from standard
|
|
||||||
* form in that a space isn't printed in lieu of the extra %e field for
|
|
||||||
* single-digit dates.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
time2a(time_t t, char *dst, size_t sz)
|
|
||||||
{
|
|
||||||
struct tm tm;
|
|
||||||
char buf[5];
|
|
||||||
char *p;
|
|
||||||
size_t nsz;
|
|
||||||
|
|
||||||
assert(sz > 1);
|
|
||||||
localtime_r(&t, &tm);
|
|
||||||
|
|
||||||
p = dst;
|
|
||||||
nsz = 0;
|
|
||||||
|
|
||||||
dst[0] = '\0';
|
|
||||||
|
|
||||||
if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
p += (int)nsz;
|
|
||||||
sz -= nsz;
|
|
||||||
|
|
||||||
if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
|
|
||||||
|
|
||||||
if (nsz >= sz)
|
|
||||||
return;
|
|
||||||
|
|
||||||
p += (int)nsz;
|
|
||||||
sz -= nsz;
|
|
||||||
|
|
||||||
(void)strftime(p, sz, "%Y", &tm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns length of parsed string (the leading "\" should NOT be
|
|
||||||
* included). This can be zero if the current character is the nil
|
|
||||||
* terminator. "d" is set to the type of parsed decorator, which may
|
|
||||||
* have an adjoining "word" of size "sz" (e.g., "(ab" -> "ab", 2).
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
a2roffdeco(enum roffdeco *d,
|
|
||||||
const char **word, size_t *sz)
|
|
||||||
{
|
|
||||||
int j, term, lim;
|
|
||||||
char set;
|
|
||||||
const char *wp, *sp;
|
|
||||||
|
|
||||||
*d = DECO_NONE;
|
|
||||||
wp = *word;
|
|
||||||
|
|
||||||
switch ((set = *wp)) {
|
|
||||||
case ('\0'):
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
case ('('):
|
|
||||||
if ('\0' == *(++wp))
|
|
||||||
return(1);
|
|
||||||
if ('\0' == *(wp + 1))
|
|
||||||
return(2);
|
|
||||||
|
|
||||||
*d = DECO_SPECIAL;
|
|
||||||
*sz = 2;
|
|
||||||
*word = wp;
|
|
||||||
return(3);
|
|
||||||
|
|
||||||
case ('F'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('f'):
|
|
||||||
/*
|
|
||||||
* FIXME: this needs work and consolidation (it should
|
|
||||||
* follow the sequence that special characters do, for
|
|
||||||
* one), but isn't a priority at the moment. Note, for
|
|
||||||
* one, that in reality \fB != \FB, although here we let
|
|
||||||
* these slip by.
|
|
||||||
*/
|
|
||||||
switch (*(++wp)) {
|
|
||||||
case ('\0'):
|
|
||||||
return(1);
|
|
||||||
case ('3'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('B'):
|
|
||||||
*d = DECO_BOLD;
|
|
||||||
return(2);
|
|
||||||
case ('2'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('I'):
|
|
||||||
*d = DECO_ITALIC;
|
|
||||||
return(2);
|
|
||||||
case ('P'):
|
|
||||||
*d = DECO_PREVIOUS;
|
|
||||||
return(2);
|
|
||||||
case ('1'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('R'):
|
|
||||||
*d = DECO_ROMAN;
|
|
||||||
return(2);
|
|
||||||
case ('('):
|
|
||||||
if ('\0' == *(++wp))
|
|
||||||
return(2);
|
|
||||||
if ('\0' == *(wp + 1))
|
|
||||||
return(3);
|
|
||||||
|
|
||||||
*d = 'F' == set ? DECO_FFONT : DECO_FONT;
|
|
||||||
*sz = 2;
|
|
||||||
*word = wp;
|
|
||||||
return(4);
|
|
||||||
case ('['):
|
|
||||||
*word = ++wp;
|
|
||||||
for (j = 0; *wp && ']' != *wp; wp++, j++)
|
|
||||||
/* Loop... */ ;
|
|
||||||
|
|
||||||
if ('\0' == *wp)
|
|
||||||
return(j + 2);
|
|
||||||
|
|
||||||
*d = 'F' == set ? DECO_FFONT : DECO_FONT;
|
|
||||||
*sz = (size_t)j;
|
|
||||||
return(j + 3);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*d = 'F' == set ? DECO_FFONT : DECO_FONT;
|
|
||||||
*sz = 1;
|
|
||||||
*word = wp;
|
|
||||||
return(2);
|
|
||||||
|
|
||||||
case ('*'):
|
|
||||||
switch (*(++wp)) {
|
|
||||||
case ('\0'):
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
case ('('):
|
|
||||||
if ('\0' == *(++wp))
|
|
||||||
return(2);
|
|
||||||
if ('\0' == *(wp + 1))
|
|
||||||
return(3);
|
|
||||||
|
|
||||||
*d = DECO_RESERVED;
|
|
||||||
*sz = 2;
|
|
||||||
*word = wp;
|
|
||||||
return(4);
|
|
||||||
|
|
||||||
case ('['):
|
|
||||||
*word = ++wp;
|
|
||||||
for (j = 0; *wp && ']' != *wp; wp++, j++)
|
|
||||||
/* Loop... */ ;
|
|
||||||
|
|
||||||
if ('\0' == *wp)
|
|
||||||
return(j + 2);
|
|
||||||
|
|
||||||
*d = DECO_RESERVED;
|
|
||||||
*sz = (size_t)j;
|
|
||||||
return(j + 3);
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*d = DECO_RESERVED;
|
|
||||||
*sz = 1;
|
|
||||||
*word = wp;
|
|
||||||
return(2);
|
|
||||||
|
|
||||||
case ('s'):
|
|
||||||
sp = wp;
|
|
||||||
if ('\0' == *(++wp))
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
C2LIM(*wp, lim);
|
|
||||||
C2TERM(*wp, term);
|
|
||||||
|
|
||||||
if (term)
|
|
||||||
wp++;
|
|
||||||
|
|
||||||
*word = wp;
|
|
||||||
|
|
||||||
if (*wp == '+' || *wp == '-')
|
|
||||||
++wp;
|
|
||||||
|
|
||||||
switch (*wp) {
|
|
||||||
case ('\''):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('['):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('('):
|
|
||||||
if (term)
|
|
||||||
return((int)(wp - sp));
|
|
||||||
|
|
||||||
C2LIM(*wp, lim);
|
|
||||||
C2TERM(*wp, term);
|
|
||||||
wp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! isdigit((u_char)*wp))
|
|
||||||
return((int)(wp - sp));
|
|
||||||
|
|
||||||
for (j = 0; isdigit((u_char)*wp); j++) {
|
|
||||||
if (lim && j >= lim)
|
|
||||||
break;
|
|
||||||
++wp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (term && term < 3) {
|
|
||||||
if (1 == term && *wp != '\'')
|
|
||||||
return((int)(wp - sp));
|
|
||||||
if (2 == term && *wp != ']')
|
|
||||||
return((int)(wp - sp));
|
|
||||||
++wp;
|
|
||||||
}
|
|
||||||
|
|
||||||
*d = DECO_SIZE;
|
|
||||||
return((int)(wp - sp));
|
|
||||||
|
|
||||||
case ('['):
|
|
||||||
*word = ++wp;
|
|
||||||
|
|
||||||
for (j = 0; *wp && ']' != *wp; wp++, j++)
|
|
||||||
/* Loop... */ ;
|
|
||||||
|
|
||||||
if ('\0' == *wp)
|
|
||||||
return(j + 1);
|
|
||||||
|
|
||||||
*d = DECO_SPECIAL;
|
|
||||||
*sz = (size_t)j;
|
|
||||||
return(j + 2);
|
|
||||||
|
|
||||||
case ('c'):
|
|
||||||
*d = DECO_NOSPACE;
|
|
||||||
*sz = 1;
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*d = DECO_SPECIAL;
|
|
||||||
*word = wp;
|
|
||||||
*sz = 1;
|
|
||||||
return(1);
|
|
||||||
}
|
|
|
@ -1,304 +0,0 @@
|
||||||
.\" $Id: roff.7,v 1.9 2010/06/10 21:42:02 kristaps Exp $
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
.\"
|
|
||||||
.\" 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.
|
|
||||||
.\"
|
|
||||||
.Dd $Mdocdate: June 10 2010 $
|
|
||||||
.Dt ROFF 7
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm roff
|
|
||||||
.Nd roff language reference
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm roff
|
|
||||||
language is a general-purpose text-formatting language. The purpose of
|
|
||||||
this document is to consistently describe those language constructs
|
|
||||||
accepted by the
|
|
||||||
.Xr mandoc 1
|
|
||||||
utility. It is a work in progress.
|
|
||||||
.Pp
|
|
||||||
An
|
|
||||||
.Nm
|
|
||||||
document follows simple rules: lines beginning with the control
|
|
||||||
characters
|
|
||||||
.Sq \.
|
|
||||||
or
|
|
||||||
.Sq \(aq
|
|
||||||
are parsed for macros. Other lines are interpreted within the scope of
|
|
||||||
prior macros:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
\&.xx Macro lines change control state.
|
|
||||||
Other lines are interpreted within the current state.
|
|
||||||
.Ed
|
|
||||||
.Sh LANGUAGE SYNTAX
|
|
||||||
.Nm
|
|
||||||
documents may contain only graphable 7-bit ASCII characters, the space
|
|
||||||
character, and, in certain circumstances, the tab character. All
|
|
||||||
manuals must have
|
|
||||||
.Ux
|
|
||||||
line terminators.
|
|
||||||
.Sh MACRO SYNTAX
|
|
||||||
Macros are arbitrary in length and begin with a control character ,
|
|
||||||
.Sq \.
|
|
||||||
or
|
|
||||||
.Sq \(aq ,
|
|
||||||
at the beginning of the line.
|
|
||||||
An arbitrary amount of whitespace may sit between the control character
|
|
||||||
and the macro name.
|
|
||||||
Thus, the following are equivalent:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
\&.if
|
|
||||||
\&.\ \ \ \&if
|
|
||||||
.Ed
|
|
||||||
.Sh REFERENCE
|
|
||||||
This section is a canonical reference of all macros, arranged
|
|
||||||
alphabetically.
|
|
||||||
.Ss \&am
|
|
||||||
The syntax of this macro is the same as that of
|
|
||||||
.Sx \&ig ,
|
|
||||||
except that a leading argument must be specified.
|
|
||||||
It is ignored, as are its children.
|
|
||||||
.Ss \&ami
|
|
||||||
The syntax of this macro is the same as that of
|
|
||||||
.Sx \&ig ,
|
|
||||||
except that a leading argument must be specified.
|
|
||||||
It is ignored, as are its children.
|
|
||||||
.Ss \&am1
|
|
||||||
The syntax of this macro is the same as that of
|
|
||||||
.Sx \&ig ,
|
|
||||||
except that a leading argument must be specified.
|
|
||||||
It is ignored, as are its children.
|
|
||||||
.Ss \&de
|
|
||||||
The syntax of this macro is the same as that of
|
|
||||||
.Sx \&ig ,
|
|
||||||
except that a leading argument must be specified.
|
|
||||||
It is ignored, as are its children.
|
|
||||||
.Ss \&dei
|
|
||||||
The syntax of this macro is the same as that of
|
|
||||||
.Sx \&ig ,
|
|
||||||
except that a leading argument must be specified.
|
|
||||||
It is ignored, as are its children.
|
|
||||||
.Ss \&ds
|
|
||||||
Define a string.
|
|
||||||
This macro is intended to have two arguments,
|
|
||||||
the name of the string to define and its content.
|
|
||||||
Currently, it is ignored including its arguments,
|
|
||||||
and the number of arguments is not checked.
|
|
||||||
.Ss \&de1
|
|
||||||
The syntax of this macro is the same as that of
|
|
||||||
.Sx \&ig ,
|
|
||||||
except that a leading argument must be specified.
|
|
||||||
It is ignored, as are its children.
|
|
||||||
.Ss \&el
|
|
||||||
The
|
|
||||||
.Qq else
|
|
||||||
half of an if/else conditional.
|
|
||||||
Pops a result off the stack of conditional evaluations pushed by
|
|
||||||
.Sx \&ie
|
|
||||||
and uses it as its conditional.
|
|
||||||
If no stack entries are present (e.g., due to no prior
|
|
||||||
.Sx \&ie
|
|
||||||
calls)
|
|
||||||
then false is assumed.
|
|
||||||
The syntax of this macro is similar to
|
|
||||||
.Sx \&if
|
|
||||||
except that the conditional is missing.
|
|
||||||
.Ss \&ie
|
|
||||||
The
|
|
||||||
.Qq if
|
|
||||||
half of an if/else conditional.
|
|
||||||
The result of the conditional is pushed into a stack used by subsequent
|
|
||||||
invocations of
|
|
||||||
.Sx \&el ,
|
|
||||||
which may be separated by any intervening input (or not exist at all).
|
|
||||||
Its syntax is equivalent to
|
|
||||||
.Sx \&if .
|
|
||||||
.Ss \&if
|
|
||||||
Begins a conditional.
|
|
||||||
Right now, the conditional evaluates to true
|
|
||||||
if and only if it starts with the letter
|
|
||||||
.Sy n ,
|
|
||||||
indicating processing in
|
|
||||||
.Xr nroff 1
|
|
||||||
style as opposed to
|
|
||||||
.Xr troff 1
|
|
||||||
style.
|
|
||||||
If a conditional is false, its children are not processed, but are
|
|
||||||
syntactically interpreted to preserve the integrity of the input
|
|
||||||
document.
|
|
||||||
Thus,
|
|
||||||
.Pp
|
|
||||||
.D1 \&.if t \e .ig
|
|
||||||
.Pp
|
|
||||||
will discard the
|
|
||||||
.Sq \&.ig ,
|
|
||||||
which may lead to interesting results, but
|
|
||||||
.Pp
|
|
||||||
.D1 \&.if t \e .if t \e{\e
|
|
||||||
.Pp
|
|
||||||
will continue to syntactically interpret to the block close of the final
|
|
||||||
conditional.
|
|
||||||
Sub-conditionals, in this case, obviously inherit the truth value of
|
|
||||||
the parent.
|
|
||||||
This macro has the following syntax:
|
|
||||||
.Pp
|
|
||||||
.Bd -literal -offset indent -compact
|
|
||||||
\&.if COND \e{\e
|
|
||||||
BODY...
|
|
||||||
\&.\e}
|
|
||||||
.Ed
|
|
||||||
.Bd -literal -offset indent -compact
|
|
||||||
\&.if COND \e{ BODY
|
|
||||||
BODY... \e}
|
|
||||||
.Ed
|
|
||||||
.Bd -literal -offset indent -compact
|
|
||||||
\&.if COND \e{ BODY
|
|
||||||
BODY...
|
|
||||||
\&.\e}
|
|
||||||
.Ed
|
|
||||||
.Bd -literal -offset indent -compact
|
|
||||||
\&.if COND \e
|
|
||||||
BODY
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
COND is a conditional statement.
|
|
||||||
roff allows for complicated conditionals; mandoc is much simpler.
|
|
||||||
At this time, mandoc supports only
|
|
||||||
.Sq n ,
|
|
||||||
evaluating to true;
|
|
||||||
and
|
|
||||||
.Sq t ,
|
|
||||||
.Sq e ,
|
|
||||||
and
|
|
||||||
.Sq o ,
|
|
||||||
evaluating to false.
|
|
||||||
All other invocations are read up to the next end of line or space and
|
|
||||||
evaluate as false.
|
|
||||||
.Pp
|
|
||||||
If the BODY section is begun by an escaped brace
|
|
||||||
.Sq \e{ ,
|
|
||||||
scope continues until a closing-brace macro
|
|
||||||
.Sq \.\e} .
|
|
||||||
If the BODY is not enclosed in braces, scope continues until the next
|
|
||||||
macro or word.
|
|
||||||
If the COND is followed by a BODY on the same line, whether after a
|
|
||||||
brace or not, then macros
|
|
||||||
.Em must
|
|
||||||
begin with a control character.
|
|
||||||
It is generally more intuitive, in this case, to write
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
\&.if COND \e{\e
|
|
||||||
\&.foo
|
|
||||||
bar
|
|
||||||
\&.\e}
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
than having the macro follow as
|
|
||||||
.Pp
|
|
||||||
.D1 \&.if COND \e{ .foo
|
|
||||||
.Pp
|
|
||||||
The scope of a conditional is always parsed, but only executed if the
|
|
||||||
conditional evaluates to true.
|
|
||||||
.Pp
|
|
||||||
Note that text subsequent a
|
|
||||||
.Sq \&.\e}
|
|
||||||
macro is discarded.
|
|
||||||
Furthermore, if an explicit closing sequence
|
|
||||||
.Sq \e}
|
|
||||||
is specified in a free-form line, the entire line is accepted within the
|
|
||||||
scope of the prior macro, not only the text preceding the close, with the
|
|
||||||
.Sq \e}
|
|
||||||
collapsing into a zero-width space.
|
|
||||||
.Ss \&ig
|
|
||||||
Ignore input.
|
|
||||||
Accepts the following syntax:
|
|
||||||
.Pp
|
|
||||||
.Bd -literal -offset indent -compact
|
|
||||||
\&.ig
|
|
||||||
BODY...
|
|
||||||
\&..
|
|
||||||
.Ed
|
|
||||||
.Bd -literal -offset indent -compact
|
|
||||||
\&.ig END
|
|
||||||
BODY...
|
|
||||||
\&.END
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
In the first case, input is ignored until a
|
|
||||||
.Sq \&..
|
|
||||||
macro is encountered on its own line.
|
|
||||||
In the second case, input is ignored until a
|
|
||||||
.Sq \&.END
|
|
||||||
is encountered.
|
|
||||||
Text subsequent the
|
|
||||||
.Sq \&.END
|
|
||||||
or
|
|
||||||
.Sq \&..
|
|
||||||
is discarded.
|
|
||||||
.Pp
|
|
||||||
Do not use the escape
|
|
||||||
.Sq \e
|
|
||||||
anywhere in the definition of END.
|
|
||||||
It causes very strange behaviour.
|
|
||||||
Furthermore, if you redefine a
|
|
||||||
.Nm
|
|
||||||
macro, such as
|
|
||||||
.Pp
|
|
||||||
.D1 \&.ig if
|
|
||||||
.Pp
|
|
||||||
the subsequent invocation of
|
|
||||||
.Sx \&if
|
|
||||||
will first signify the end of comment, then be invoked as a macro.
|
|
||||||
This behaviour really shouldn't be counted upon.
|
|
||||||
.Ss \&rm
|
|
||||||
Remove a request, macro or string.
|
|
||||||
This macro is intended to have one argument,
|
|
||||||
the name of the request, macro or string to be undefined.
|
|
||||||
Currently, it is ignored including its arguments,
|
|
||||||
and the number of arguments is not checked.
|
|
||||||
.Ss \&tr
|
|
||||||
Output character translation.
|
|
||||||
This macro is intended to have one argument,
|
|
||||||
consisting of an even number of characters.
|
|
||||||
Currently, it is ignored including its arguments,
|
|
||||||
and the number of arguments is not checked.
|
|
||||||
.Sh COMPATIBILITY
|
|
||||||
This section documents compatibility between mandoc and other other
|
|
||||||
troff implementations, at this time limited to GNU troff
|
|
||||||
.Pq Qq groff .
|
|
||||||
The term
|
|
||||||
.Qq historic groff
|
|
||||||
refers to groff versions before the
|
|
||||||
.Pa doc.tmac
|
|
||||||
file re-write
|
|
||||||
.Pq somewhere between 1.15 and 1.19 .
|
|
||||||
.Pp
|
|
||||||
.Bl -dash -compact
|
|
||||||
.It
|
|
||||||
Historic groff did not accept white-space buffering the custom END tag
|
|
||||||
for the
|
|
||||||
.Sx \&ig
|
|
||||||
macro.
|
|
||||||
.It
|
|
||||||
The
|
|
||||||
.Sx \&if
|
|
||||||
and family would print funny white-spaces with historic groff when
|
|
||||||
depending on next-line syntax.
|
|
||||||
.El
|
|
||||||
.Sh AUTHORS
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
reference was written by
|
|
||||||
.An Kristaps Dzonsons Aq kristaps@bsd.lv .
|
|
|
@ -1,857 +0,0 @@
|
||||||
/* $Id: roff.c,v 1.88 2010/06/10 21:42:02 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "mandoc.h"
|
|
||||||
#include "roff.h"
|
|
||||||
|
|
||||||
#define RSTACK_MAX 128
|
|
||||||
|
|
||||||
#define ROFF_CTL(c) \
|
|
||||||
('.' == (c) || '\'' == (c))
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#if 1
|
|
||||||
#define ROFF_DEBUG(fmt, args...) \
|
|
||||||
do { /* Nothing. */ } while (/*CONSTCOND*/ 0)
|
|
||||||
#else
|
|
||||||
#define ROFF_DEBUG(fmt, args...) \
|
|
||||||
do { fprintf(stderr, fmt , ##args); } while (/*CONSTCOND*/ 0)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
void do_nothing(char *fmt, ...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#if 1
|
|
||||||
#define ROFF_DEBUG do_nothing
|
|
||||||
#else
|
|
||||||
#define ROFF_DEBUG fprintf
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum rofft {
|
|
||||||
ROFF_am,
|
|
||||||
ROFF_ami,
|
|
||||||
ROFF_am1,
|
|
||||||
ROFF_de,
|
|
||||||
ROFF_dei,
|
|
||||||
ROFF_de1,
|
|
||||||
ROFF_ds,
|
|
||||||
ROFF_el,
|
|
||||||
ROFF_ie,
|
|
||||||
ROFF_if,
|
|
||||||
ROFF_ig,
|
|
||||||
ROFF_rm,
|
|
||||||
ROFF_tr,
|
|
||||||
ROFF_cblock,
|
|
||||||
ROFF_ccond,
|
|
||||||
ROFF_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
enum roffrule {
|
|
||||||
ROFFRULE_ALLOW,
|
|
||||||
ROFFRULE_DENY
|
|
||||||
};
|
|
||||||
|
|
||||||
struct roff {
|
|
||||||
struct roffnode *last; /* leaf of stack */
|
|
||||||
mandocmsg msg; /* err/warn/fatal messages */
|
|
||||||
void *data; /* privdata for messages */
|
|
||||||
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */
|
|
||||||
int rstackpos; /* position in rstack */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct roffnode {
|
|
||||||
enum rofft tok; /* type of node */
|
|
||||||
struct roffnode *parent; /* up one in stack */
|
|
||||||
int line; /* parse line */
|
|
||||||
int col; /* parse col */
|
|
||||||
char *end; /* end-rules: custom token */
|
|
||||||
int endspan; /* end-rules: next-line or infty */
|
|
||||||
enum roffrule rule; /* current evaluation rule */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ROFF_ARGS struct roff *r, /* parse ctx */ \
|
|
||||||
enum rofft tok, /* tok of macro */ \
|
|
||||||
char **bufp, /* input buffer */ \
|
|
||||||
size_t *szp, /* size of input buffer */ \
|
|
||||||
int ln, /* parse line */ \
|
|
||||||
int ppos, /* original pos in buffer */ \
|
|
||||||
int pos, /* current pos in buffer */ \
|
|
||||||
int *offs /* reset offset of buffer data */
|
|
||||||
|
|
||||||
typedef enum rofferr (*roffproc)(ROFF_ARGS);
|
|
||||||
|
|
||||||
struct roffmac {
|
|
||||||
const char *name; /* macro name */
|
|
||||||
roffproc proc; /* process new macro */
|
|
||||||
roffproc text; /* process as child text of macro */
|
|
||||||
roffproc sub; /* process as child of macro */
|
|
||||||
int flags;
|
|
||||||
#define ROFFMAC_STRUCT (1 << 0) /* always interpret */
|
|
||||||
struct roffmac *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static enum rofferr roff_block(ROFF_ARGS);
|
|
||||||
static enum rofferr roff_block_text(ROFF_ARGS);
|
|
||||||
static enum rofferr roff_block_sub(ROFF_ARGS);
|
|
||||||
static enum rofferr roff_cblock(ROFF_ARGS);
|
|
||||||
static enum rofferr roff_ccond(ROFF_ARGS);
|
|
||||||
static enum rofferr roff_cond(ROFF_ARGS);
|
|
||||||
static enum rofferr roff_cond_text(ROFF_ARGS);
|
|
||||||
static enum rofferr roff_cond_sub(ROFF_ARGS);
|
|
||||||
static enum roffrule roff_evalcond(const char *, int *);
|
|
||||||
static enum rofferr roff_line(ROFF_ARGS);
|
|
||||||
|
|
||||||
/* See roff_hash_find() */
|
|
||||||
|
|
||||||
#define ASCII_HI 126
|
|
||||||
#define ASCII_LO 33
|
|
||||||
#define HASHWIDTH (ASCII_HI - ASCII_LO + 1)
|
|
||||||
|
|
||||||
static struct roffmac *hash[HASHWIDTH];
|
|
||||||
|
|
||||||
static struct roffmac roffs[ROFF_MAX] = {
|
|
||||||
{ "am", roff_block, roff_block_text, roff_block_sub, 0, NULL },
|
|
||||||
{ "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL },
|
|
||||||
{ "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
|
|
||||||
{ "de", roff_block, roff_block_text, roff_block_sub, 0, NULL },
|
|
||||||
{ "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL },
|
|
||||||
{ "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
|
|
||||||
{ "ds", roff_line, NULL, NULL, 0, NULL },
|
|
||||||
{ "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
|
|
||||||
{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
|
|
||||||
{ "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
|
|
||||||
{ "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL },
|
|
||||||
{ "rm", roff_line, NULL, NULL, 0, NULL },
|
|
||||||
{ "tr", roff_line, NULL, NULL, 0, NULL },
|
|
||||||
{ ".", roff_cblock, NULL, NULL, 0, NULL },
|
|
||||||
{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
static void roff_free1(struct roff *);
|
|
||||||
static enum rofft roff_hash_find(const char *);
|
|
||||||
static void roff_hash_init(void);
|
|
||||||
static void roffnode_cleanscope(struct roff *);
|
|
||||||
static int roffnode_push(struct roff *,
|
|
||||||
enum rofft, int, int);
|
|
||||||
static void roffnode_pop(struct roff *);
|
|
||||||
static enum rofft roff_parse(const char *, int *);
|
|
||||||
|
|
||||||
/* See roff_hash_find() */
|
|
||||||
#define ROFF_HASH(p) (p[0] - ASCII_LO)
|
|
||||||
|
|
||||||
static void
|
|
||||||
roff_hash_init(void)
|
|
||||||
{
|
|
||||||
struct roffmac *n;
|
|
||||||
int buc, i;
|
|
||||||
|
|
||||||
for (i = 0; i < (int)ROFF_MAX; i++) {
|
|
||||||
assert(roffs[i].name[0] >= ASCII_LO);
|
|
||||||
assert(roffs[i].name[0] <= ASCII_HI);
|
|
||||||
|
|
||||||
buc = ROFF_HASH(roffs[i].name);
|
|
||||||
|
|
||||||
if (NULL != (n = hash[buc])) {
|
|
||||||
for ( ; n->next; n = n->next)
|
|
||||||
/* Do nothing. */ ;
|
|
||||||
n->next = &roffs[i];
|
|
||||||
} else
|
|
||||||
hash[buc] = &roffs[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look up a roff token by its name. Returns ROFF_MAX if no macro by
|
|
||||||
* the nil-terminated string name could be found.
|
|
||||||
*/
|
|
||||||
static enum rofft
|
|
||||||
roff_hash_find(const char *p)
|
|
||||||
{
|
|
||||||
int buc;
|
|
||||||
struct roffmac *n;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* libroff has an extremely simple hashtable, for the time
|
|
||||||
* being, which simply keys on the first character, which must
|
|
||||||
* be printable, then walks a chain. It works well enough until
|
|
||||||
* optimised.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (p[0] < ASCII_LO || p[0] > ASCII_HI)
|
|
||||||
return(ROFF_MAX);
|
|
||||||
|
|
||||||
buc = ROFF_HASH(p);
|
|
||||||
|
|
||||||
if (NULL == (n = hash[buc]))
|
|
||||||
return(ROFF_MAX);
|
|
||||||
for ( ; n; n = n->next)
|
|
||||||
if (0 == strcmp(n->name, p))
|
|
||||||
return((enum rofft)(n - roffs));
|
|
||||||
|
|
||||||
return(ROFF_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pop the current node off of the stack of roff instructions currently
|
|
||||||
* pending.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
roffnode_pop(struct roff *r)
|
|
||||||
{
|
|
||||||
struct roffnode *p;
|
|
||||||
|
|
||||||
assert(r->last);
|
|
||||||
p = r->last;
|
|
||||||
|
|
||||||
if (ROFF_el == p->tok)
|
|
||||||
if (r->rstackpos > -1)
|
|
||||||
r->rstackpos--;
|
|
||||||
|
|
||||||
r->last = r->last->parent;
|
|
||||||
if (p->end)
|
|
||||||
free(p->end);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Push a roff node onto the instruction stack. This must later be
|
|
||||||
* removed with roffnode_pop().
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
roffnode_push(struct roff *r, enum rofft tok, int line, int col)
|
|
||||||
{
|
|
||||||
struct roffnode *p;
|
|
||||||
|
|
||||||
if (NULL == (p = calloc(1, sizeof(struct roffnode)))) {
|
|
||||||
(*r->msg)(MANDOCERR_MEM, r->data, line, col, NULL);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
p->tok = tok;
|
|
||||||
p->parent = r->last;
|
|
||||||
p->line = line;
|
|
||||||
p->col = col;
|
|
||||||
p->rule = p->parent ? p->parent->rule : ROFFRULE_DENY;
|
|
||||||
|
|
||||||
r->last = p;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
roff_free1(struct roff *r)
|
|
||||||
{
|
|
||||||
|
|
||||||
while (r->last)
|
|
||||||
roffnode_pop(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
roff_reset(struct roff *r)
|
|
||||||
{
|
|
||||||
|
|
||||||
roff_free1(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
roff_free(struct roff *r)
|
|
||||||
{
|
|
||||||
|
|
||||||
roff_free1(r);
|
|
||||||
free(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct roff *
|
|
||||||
roff_alloc(const mandocmsg msg, void *data)
|
|
||||||
{
|
|
||||||
struct roff *r;
|
|
||||||
|
|
||||||
if (NULL == (r = calloc(1, sizeof(struct roff)))) {
|
|
||||||
(*msg)(MANDOCERR_MEM, data, 0, 0, NULL);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
r->msg = msg;
|
|
||||||
r->data = data;
|
|
||||||
r->rstackpos = -1;
|
|
||||||
|
|
||||||
roff_hash_init();
|
|
||||||
return(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum rofferr
|
|
||||||
roff_parseln(struct roff *r, int ln,
|
|
||||||
char **bufp, size_t *szp, int pos, int *offs)
|
|
||||||
{
|
|
||||||
enum rofft t;
|
|
||||||
int ppos;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, if a scope is open and we're not a macro, pass the
|
|
||||||
* text through the macro's filter. If a scope isn't open and
|
|
||||||
* we're not a macro, just let it through.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (r->last && ! ROFF_CTL((*bufp)[pos])) {
|
|
||||||
t = r->last->tok;
|
|
||||||
assert(roffs[t].text);
|
|
||||||
|
|
||||||
ROFF_DEBUG("roff: intercept scoped text: %s, [%s]\n",
|
|
||||||
roffs[t].name, &(*bufp)[pos]);
|
|
||||||
return((*roffs[t].text)
|
|
||||||
(r, t, bufp, szp, ln, pos, pos, offs));
|
|
||||||
} else if ( ! ROFF_CTL((*bufp)[pos])) {
|
|
||||||
ROFF_DEBUG("roff: pass non-scoped text: [%s]\n",
|
|
||||||
&(*bufp)[pos]);
|
|
||||||
return(ROFF_CONT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If a scope is open, go to the child handler for that macro,
|
|
||||||
* as it may want to preprocess before doing anything with it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (r->last) {
|
|
||||||
t = r->last->tok;
|
|
||||||
assert(roffs[t].sub);
|
|
||||||
ROFF_DEBUG("roff: intercept scoped context: %s\n",
|
|
||||||
roffs[t].name);
|
|
||||||
return((*roffs[t].sub)
|
|
||||||
(r, t, bufp, szp, ln, pos, pos, offs));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lastly, as we've no scope open, try to look up and execute
|
|
||||||
* the new macro. If no macro is found, simply return and let
|
|
||||||
* the compilers handle it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ppos = pos;
|
|
||||||
if (ROFF_MAX == (t = roff_parse(*bufp, &pos))) {
|
|
||||||
ROFF_DEBUG("roff: pass non-scoped non-macro: [%s]\n",
|
|
||||||
&(*bufp)[pos]);
|
|
||||||
return(ROFF_CONT);
|
|
||||||
}
|
|
||||||
|
|
||||||
ROFF_DEBUG("roff: intercept new-scope: %s, [%s]\n",
|
|
||||||
roffs[t].name, &(*bufp)[pos]);
|
|
||||||
assert(roffs[t].proc);
|
|
||||||
return((*roffs[t].proc)
|
|
||||||
(r, t, bufp, szp, ln, ppos, pos, offs));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
roff_endparse(struct roff *r)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (NULL == r->last)
|
|
||||||
return(1);
|
|
||||||
return((*r->msg)(MANDOCERR_SCOPEEXIT, r->data, r->last->line,
|
|
||||||
r->last->col, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse a roff node's type from the input buffer. This must be in the
|
|
||||||
* form of ".foo xxx" in the usual way.
|
|
||||||
*/
|
|
||||||
static enum rofft
|
|
||||||
roff_parse(const char *buf, int *pos)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
char mac[5];
|
|
||||||
enum rofft t;
|
|
||||||
|
|
||||||
assert(ROFF_CTL(buf[*pos]));
|
|
||||||
(*pos)++;
|
|
||||||
|
|
||||||
while (buf[*pos] && (' ' == buf[*pos] || '\t' == buf[*pos]))
|
|
||||||
(*pos)++;
|
|
||||||
|
|
||||||
if ('\0' == buf[*pos])
|
|
||||||
return(ROFF_MAX);
|
|
||||||
|
|
||||||
for (j = 0; j < 4; j++, (*pos)++)
|
|
||||||
if ('\0' == (mac[j] = buf[*pos]))
|
|
||||||
break;
|
|
||||||
else if (' ' == buf[*pos] || (j && '\\' == buf[*pos]))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (j == 4 || j < 1)
|
|
||||||
return(ROFF_MAX);
|
|
||||||
|
|
||||||
mac[j] = '\0';
|
|
||||||
|
|
||||||
if (ROFF_MAX == (t = roff_hash_find(mac)))
|
|
||||||
return(t);
|
|
||||||
|
|
||||||
while (buf[*pos] && ' ' == buf[*pos])
|
|
||||||
(*pos)++;
|
|
||||||
|
|
||||||
return(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_cblock(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A block-close `..' should only be invoked as a child of an
|
|
||||||
* ignore macro, otherwise raise a warning and just ignore it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (NULL == r->last) {
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (r->last->tok) {
|
|
||||||
case (ROFF_am):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_ami):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_am1):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_de):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_dei):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_de1):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_ig):
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*bufp)[pos])
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
|
|
||||||
roffnode_pop(r);
|
|
||||||
roffnode_cleanscope(r);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
roffnode_cleanscope(struct roff *r)
|
|
||||||
{
|
|
||||||
|
|
||||||
while (r->last) {
|
|
||||||
if (--r->last->endspan < 0)
|
|
||||||
break;
|
|
||||||
roffnode_pop(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_ccond(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (NULL == r->last) {
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (r->last->tok) {
|
|
||||||
case (ROFF_el):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_ie):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (ROFF_if):
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r->last->endspan > -1) {
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*bufp)[pos])
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
|
|
||||||
roffnode_pop(r);
|
|
||||||
roffnode_cleanscope(r);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_block(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
int sv;
|
|
||||||
size_t sz;
|
|
||||||
|
|
||||||
if (ROFF_ig != tok && '\0' == (*bufp)[pos]) {
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
} else if (ROFF_ig != tok) {
|
|
||||||
while ((*bufp)[pos] && ' ' != (*bufp)[pos])
|
|
||||||
pos++;
|
|
||||||
while (' ' == (*bufp)[pos])
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! roffnode_push(r, tok, ln, ppos))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
|
|
||||||
if ('\0' == (*bufp)[pos])
|
|
||||||
return(ROFF_IGN);
|
|
||||||
|
|
||||||
sv = pos;
|
|
||||||
while ((*bufp)[pos] && ' ' != (*bufp)[pos] &&
|
|
||||||
'\t' != (*bufp)[pos])
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: groff does NOT like escape characters in the input.
|
|
||||||
* Instead of detecting this, we're just going to let it fly and
|
|
||||||
* to hell with it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert(pos > sv);
|
|
||||||
sz = (size_t)(pos - sv);
|
|
||||||
|
|
||||||
if (1 == sz && '.' == (*bufp)[sv])
|
|
||||||
return(ROFF_IGN);
|
|
||||||
|
|
||||||
r->last->end = malloc(sz + 1);
|
|
||||||
|
|
||||||
if (NULL == r->last->end) {
|
|
||||||
(*r->msg)(MANDOCERR_MEM, r->data, ln, pos, NULL);
|
|
||||||
return(ROFF_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(r->last->end, *bufp + sv, sz);
|
|
||||||
r->last->end[(int)sz] = '\0';
|
|
||||||
|
|
||||||
if ((*bufp)[pos])
|
|
||||||
if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_block_sub(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
enum rofft t;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First check whether a custom macro exists at this level. If
|
|
||||||
* it does, then check against it. This is some of groff's
|
|
||||||
* stranger behaviours. If we encountered a custom end-scope
|
|
||||||
* tag and that tag also happens to be a "real" macro, then we
|
|
||||||
* need to try interpreting it again as a real macro. If it's
|
|
||||||
* not, then return ignore. Else continue.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (r->last->end) {
|
|
||||||
i = pos + 1;
|
|
||||||
while (' ' == (*bufp)[i] || '\t' == (*bufp)[i])
|
|
||||||
i++;
|
|
||||||
|
|
||||||
for (j = 0; r->last->end[j]; j++, i++)
|
|
||||||
if ((*bufp)[i] != r->last->end[j])
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ('\0' == r->last->end[j] &&
|
|
||||||
('\0' == (*bufp)[i] ||
|
|
||||||
' ' == (*bufp)[i] ||
|
|
||||||
'\t' == (*bufp)[i])) {
|
|
||||||
roffnode_pop(r);
|
|
||||||
roffnode_cleanscope(r);
|
|
||||||
|
|
||||||
if (ROFF_MAX != roff_parse(*bufp, &pos))
|
|
||||||
return(ROFF_RERUN);
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we have no custom end-query or lookup failed, then try
|
|
||||||
* pulling it out of the hashtable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ppos = pos;
|
|
||||||
t = roff_parse(*bufp, &pos);
|
|
||||||
|
|
||||||
/* If we're not a comment-end, then throw it away. */
|
|
||||||
if (ROFF_cblock != t)
|
|
||||||
return(ROFF_IGN);
|
|
||||||
|
|
||||||
assert(roffs[t].proc);
|
|
||||||
return((*roffs[t].proc)(r, t, bufp,
|
|
||||||
szp, ln, ppos, pos, offs));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_block_text(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_cond_sub(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
enum rofft t;
|
|
||||||
enum roffrule rr;
|
|
||||||
struct roffnode *l;
|
|
||||||
|
|
||||||
ppos = pos;
|
|
||||||
rr = r->last->rule;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clean out scope. If we've closed ourselves, then don't
|
|
||||||
* continue.
|
|
||||||
*/
|
|
||||||
|
|
||||||
l = r->last;
|
|
||||||
roffnode_cleanscope(r);
|
|
||||||
|
|
||||||
if (l != r->last)
|
|
||||||
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
|
|
||||||
|
|
||||||
if (ROFF_MAX == (t = roff_parse(*bufp, &pos)))
|
|
||||||
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A denied conditional must evaluate its children if and only
|
|
||||||
* if they're either structurally required (such as loops and
|
|
||||||
* conditionals) or a closing macro.
|
|
||||||
*/
|
|
||||||
if (ROFFRULE_DENY == rr)
|
|
||||||
if ( ! (ROFFMAC_STRUCT & roffs[t].flags))
|
|
||||||
if (ROFF_ccond != t)
|
|
||||||
return(ROFF_IGN);
|
|
||||||
|
|
||||||
assert(roffs[t].proc);
|
|
||||||
return((*roffs[t].proc)
|
|
||||||
(r, t, bufp, szp, ln, ppos, pos, offs));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_cond_text(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
char *ep, *st;
|
|
||||||
enum roffrule rr;
|
|
||||||
|
|
||||||
rr = r->last->rule;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We display the value of the text if out current evaluation
|
|
||||||
* scope permits us to do so.
|
|
||||||
*/
|
|
||||||
|
|
||||||
st = &(*bufp)[pos];
|
|
||||||
if (NULL == (ep = strstr(st, "\\}"))) {
|
|
||||||
roffnode_cleanscope(r);
|
|
||||||
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ep == st || (ep > st && '\\' != *(ep - 1)))
|
|
||||||
roffnode_pop(r);
|
|
||||||
|
|
||||||
roffnode_cleanscope(r);
|
|
||||||
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum roffrule
|
|
||||||
roff_evalcond(const char *v, int *pos)
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (v[*pos]) {
|
|
||||||
case ('n'):
|
|
||||||
(*pos)++;
|
|
||||||
return(ROFFRULE_ALLOW);
|
|
||||||
case ('e'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('o'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('t'):
|
|
||||||
(*pos)++;
|
|
||||||
return(ROFFRULE_DENY);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (v[*pos] && ' ' != v[*pos])
|
|
||||||
(*pos)++;
|
|
||||||
return(ROFFRULE_DENY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_cond(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
int sv;
|
|
||||||
enum roffrule rule;
|
|
||||||
|
|
||||||
/* Stack overflow! */
|
|
||||||
|
|
||||||
if (ROFF_ie == tok && r->rstackpos == RSTACK_MAX - 1) {
|
|
||||||
(*r->msg)(MANDOCERR_MEM, r->data, ln, ppos, NULL);
|
|
||||||
return(ROFF_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First, evaluate the conditional. */
|
|
||||||
|
|
||||||
if (ROFF_el == tok) {
|
|
||||||
/*
|
|
||||||
* An `.el' will get the value of the current rstack
|
|
||||||
* entry set in prior `ie' calls or defaults to DENY.
|
|
||||||
*/
|
|
||||||
if (r->rstackpos < 0)
|
|
||||||
rule = ROFFRULE_DENY;
|
|
||||||
else
|
|
||||||
rule = r->rstack[r->rstackpos];
|
|
||||||
} else
|
|
||||||
rule = roff_evalcond(*bufp, &pos);
|
|
||||||
|
|
||||||
sv = pos;
|
|
||||||
|
|
||||||
while (' ' == (*bufp)[pos])
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Roff is weird. If we have just white-space after the
|
|
||||||
* conditional, it's considered the BODY and we exit without
|
|
||||||
* really doing anything. Warn about this. It's probably
|
|
||||||
* wrong.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ('\0' == (*bufp)[pos] && sv != pos) {
|
|
||||||
if ((*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL))
|
|
||||||
return(ROFF_IGN);
|
|
||||||
return(ROFF_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! roffnode_push(r, tok, ln, ppos))
|
|
||||||
return(ROFF_ERR);
|
|
||||||
|
|
||||||
r->last->rule = rule;
|
|
||||||
|
|
||||||
ROFF_DEBUG("roff: cond: %s -> %s\n", roffs[tok].name,
|
|
||||||
ROFFRULE_ALLOW == rule ? "allow" : "deny");
|
|
||||||
|
|
||||||
if (ROFF_ie == tok) {
|
|
||||||
/*
|
|
||||||
* An if-else will put the NEGATION of the current
|
|
||||||
* evaluated conditional into the stack.
|
|
||||||
*/
|
|
||||||
r->rstackpos++;
|
|
||||||
if (ROFFRULE_DENY == r->last->rule)
|
|
||||||
r->rstack[r->rstackpos] = ROFFRULE_ALLOW;
|
|
||||||
else
|
|
||||||
r->rstack[r->rstackpos] = ROFFRULE_DENY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the parent has false as its rule, then so do we. */
|
|
||||||
|
|
||||||
if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) {
|
|
||||||
r->last->rule = ROFFRULE_DENY;
|
|
||||||
ROFF_DEBUG("roff: cond override: %s -> deny\n",
|
|
||||||
roffs[tok].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Determine scope. If we're invoked with "\{" trailing the
|
|
||||||
* conditional, then we're in a multiline scope. Else our scope
|
|
||||||
* expires on the next line.
|
|
||||||
*/
|
|
||||||
|
|
||||||
r->last->endspan = 1;
|
|
||||||
|
|
||||||
if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) {
|
|
||||||
r->last->endspan = -1;
|
|
||||||
pos += 2;
|
|
||||||
ROFF_DEBUG("roff: cond-scope: %s, multi-line\n",
|
|
||||||
roffs[tok].name);
|
|
||||||
} else
|
|
||||||
ROFF_DEBUG("roff: cond-scope: %s, one-line\n",
|
|
||||||
roffs[tok].name);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If there are no arguments on the line, the next-line scope is
|
|
||||||
* assumed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ('\0' == (*bufp)[pos])
|
|
||||||
return(ROFF_IGN);
|
|
||||||
|
|
||||||
/* Otherwise re-run the roff parser after recalculating. */
|
|
||||||
|
|
||||||
*offs = pos;
|
|
||||||
return(ROFF_RERUN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static enum rofferr
|
|
||||||
roff_line(ROFF_ARGS)
|
|
||||||
{
|
|
||||||
|
|
||||||
return(ROFF_IGN);
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
div.body { color: #333333;
|
|
||||||
max-width: 800px;
|
|
||||||
padding-left: 10px;
|
|
||||||
font-size: smaller;
|
|
||||||
font-family: Verdana, Tahoma, Arial, sans-serif; }
|
|
||||||
|
|
||||||
div.sec-head { color: #000000;
|
|
||||||
font-weight: bold; }
|
|
||||||
div.sec-body { }
|
|
||||||
div.sec-block { padding-bottom: 1em; }
|
|
||||||
div.ssec-head { color: #000000;
|
|
||||||
font-weight: bold; }
|
|
||||||
div.ssec-body { }
|
|
||||||
div.ssec-block { }
|
|
||||||
|
|
||||||
span.addr { } /* Address (Ad). */
|
|
||||||
span.arg { font-style: italic; } /* Command argument (Ar). */
|
|
||||||
span.author { } /* Author name (An). */
|
|
||||||
span.cmd { font-weight: bold; } /* Command (Cm). */
|
|
||||||
span.config { font-weight: bold; } /* Config statement (Cd). */
|
|
||||||
span.define { } /* Defines (Dv). */
|
|
||||||
span.desc { } /* Nd. After em-dash. */
|
|
||||||
span.diag { font-weight: bold; } /* Diagnostic (Bl -diag). */
|
|
||||||
span.emph { font-style: italic; } /* Emphasis (Em). */
|
|
||||||
span.env { } /* Environment variables (Ev). */
|
|
||||||
span.errno { } /* Error string (Er). */
|
|
||||||
span.farg { font-style: italic; } /* Function argument (Fa, Fn). */
|
|
||||||
span.file { font-style: italic; } /* File (Pa). */
|
|
||||||
span.flag { font-weight: bold; } /* Flag (Fl, Cm). */
|
|
||||||
span.fname { font-weight: bold; } /* Function name (Fa, Fn, Rv). */
|
|
||||||
span.ftype { font-style: italic; } /* Function types (Ft, Fn). */
|
|
||||||
span.includes { font-weight: bold; } /* Header includes (In). */
|
|
||||||
span.lib { } /* Library (Lb). */
|
|
||||||
span.lit { font-family: monospace; } /* Literals (Bf -literal). */
|
|
||||||
span.macro { font-weight: bold; } /* Macro-ish thing (Fd). */
|
|
||||||
span.name { color: #003333; font-weight: bold; } /* Name of utility (Nm). */
|
|
||||||
span.opt { } /* Options (Op, Oo/Oc). */
|
|
||||||
span.ref { } /* Citations (Rs). */
|
|
||||||
span.ref-auth { } /* Reference author (%A). */
|
|
||||||
span.ref-book { font-style: italic; } /* Reference book (%B). */
|
|
||||||
span.ref-city { } /* Reference city (%C). */
|
|
||||||
span.ref-date { } /* Reference date (%D). */
|
|
||||||
span.ref-issue { font-style: italic; } /* Reference issuer/publisher (%I). */
|
|
||||||
span.ref-jrnl { font-style: italic; } /* Reference journal (%J). */
|
|
||||||
span.ref-num { } /* Reference number (%N). */
|
|
||||||
span.ref-opt { } /* Reference optionals (%O). */
|
|
||||||
span.ref-page { } /* Reference page (%P). */
|
|
||||||
span.ref-corp { } /* Reference corporate/foreign author (%Q). */
|
|
||||||
span.ref-rep { } /* Reference report (%R). */
|
|
||||||
span.ref-title { } /* Reference title (%T). */
|
|
||||||
span.ref-vol { } /* Reference volume (%V). */
|
|
||||||
span.symb { font-weight: bold; } /* Symbols. */
|
|
||||||
span.type { font-style: italic; } /* Variable types (Vt). */
|
|
||||||
span.unix { } /* Unices (Ux, Ox, Nx, Fx, Bx, Bsx, Dx). */
|
|
||||||
span.utility { font-weight: bold; } /* Name of utility (Ex). */
|
|
||||||
span.var { font-weight: bold; } /* Variables (Rv). */
|
|
||||||
|
|
||||||
a.link-ext { background: transparent url(external.png) center right no-repeat; padding-right: 12px; }/* Off-site link (Lk). */
|
|
||||||
a.link-includes { } /* Include-file link (In). */
|
|
||||||
a.link-mail { background: transparent url(external.png) center right no-repeat; padding-right: 12px; }/* Mailto links (Mt). */
|
|
||||||
a.link-man { } /* Manual links (Xr). */
|
|
||||||
a.link-sec { text-decoration: none; border-bottom: 1px dotted #339999; } /* Section links (Sx). */
|
|
||||||
|
|
||||||
div.emph { font-style: italic; } /* Emphasis (Bl -emphasis). */
|
|
||||||
div.lit { margin: 3px;
|
|
||||||
padding: 3px;
|
|
||||||
background-color: #EEEEEE;
|
|
||||||
border: 1px solid #339999;
|
|
||||||
color: #000000;
|
|
||||||
font-family: monospace; }
|
|
||||||
div.symb { font-weight: bold; } /* Symbols (Bl -symbolic). */
|
|
||||||
|
|
||||||
table.header { border-bottom: 1px dotted #dddddd;
|
|
||||||
color: #999999; }
|
|
||||||
table.footer { border-top: 1px dotted #dddddd;
|
|
||||||
color: #999999; }
|
|
||||||
|
|
|
@ -1,427 +0,0 @@
|
||||||
/* $Id: term_ps.c,v 1.10 2010/06/19 20:46:28 kristaps Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "out.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "term.h"
|
|
||||||
|
|
||||||
#define PS_CHAR_WIDTH 6
|
|
||||||
#define PS_CHAR_HEIGHT 12
|
|
||||||
#define PS_CHAR_TOPMARG (792 - 24)
|
|
||||||
#define PS_CHAR_TOP (PS_CHAR_TOPMARG - 36)
|
|
||||||
#define PS_CHAR_LEFT 36
|
|
||||||
#define PS_CHAR_BOTMARG 24
|
|
||||||
#define PS_CHAR_BOT (PS_CHAR_BOTMARG + 36)
|
|
||||||
|
|
||||||
#define PS_BUFSLOP 128
|
|
||||||
#define PS_GROWBUF(p, sz) \
|
|
||||||
do if ((p)->engine.ps.psmargcur + (sz) > \
|
|
||||||
(p)->engine.ps.psmargsz) { \
|
|
||||||
(p)->engine.ps.psmargsz += /* CONSTCOND */ \
|
|
||||||
MAX(PS_BUFSLOP, (sz)); \
|
|
||||||
(p)->engine.ps.psmarg = realloc \
|
|
||||||
((p)->engine.ps.psmarg, \
|
|
||||||
(p)->engine.ps.psmargsz); \
|
|
||||||
if (NULL == (p)->engine.ps.psmarg) { \
|
|
||||||
perror(NULL); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} \
|
|
||||||
} while (/* CONSTCOND */ 0)
|
|
||||||
|
|
||||||
|
|
||||||
static void ps_letter(struct termp *, char);
|
|
||||||
static void ps_begin(struct termp *);
|
|
||||||
static void ps_end(struct termp *);
|
|
||||||
static void ps_advance(struct termp *, size_t);
|
|
||||||
static void ps_endline(struct termp *);
|
|
||||||
static void ps_fclose(struct termp *);
|
|
||||||
static void ps_pclose(struct termp *);
|
|
||||||
static void ps_pletter(struct termp *, char);
|
|
||||||
static void ps_printf(struct termp *, const char *, ...);
|
|
||||||
static void ps_putchar(struct termp *, char);
|
|
||||||
static void ps_setfont(struct termp *, enum termfont);
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
ps_alloc(void)
|
|
||||||
{
|
|
||||||
struct termp *p;
|
|
||||||
|
|
||||||
if (NULL == (p = term_alloc(TERMENC_ASCII)))
|
|
||||||
return(NULL);
|
|
||||||
|
|
||||||
p->type = TERMTYPE_PS;
|
|
||||||
p->letter = ps_letter;
|
|
||||||
p->begin = ps_begin;
|
|
||||||
p->end = ps_end;
|
|
||||||
p->advance = ps_advance;
|
|
||||||
p->endline = ps_endline;
|
|
||||||
return(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ps_free(void *arg)
|
|
||||||
{
|
|
||||||
struct termp *p;
|
|
||||||
|
|
||||||
p = (struct termp *)arg;
|
|
||||||
|
|
||||||
if (p->engine.ps.psmarg)
|
|
||||||
free(p->engine.ps.psmarg);
|
|
||||||
|
|
||||||
term_free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_printf(struct termp *p, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're running in regular mode, then pipe directly into
|
|
||||||
* vprintf(). If we're processing margins, then push the data
|
|
||||||
* into our growable margin buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! (PS_MARGINS & p->engine.ps.psstate)) {
|
|
||||||
vprintf(fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX: I assume that the in-margin print won't exceed
|
|
||||||
* PS_BUFSLOP (128 bytes), which is reasonable but still an
|
|
||||||
* assumption that will cause pukeage if it's not the case.
|
|
||||||
*/
|
|
||||||
|
|
||||||
PS_GROWBUF(p, PS_BUFSLOP);
|
|
||||||
|
|
||||||
pos = (int)p->engine.ps.psmargcur;
|
|
||||||
vsnprintf(&p->engine.ps.psmarg[pos], PS_BUFSLOP, fmt, ap);
|
|
||||||
p->engine.ps.psmargcur = strlen(p->engine.ps.psmarg);
|
|
||||||
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_putchar(struct termp *p, char c)
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
/* See ps_printf(). */
|
|
||||||
|
|
||||||
if ( ! (PS_MARGINS & p->engine.ps.psstate)) {
|
|
||||||
putchar(c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PS_GROWBUF(p, 2);
|
|
||||||
|
|
||||||
pos = (int)p->engine.ps.psmargcur++;
|
|
||||||
p->engine.ps.psmarg[pos++] = c;
|
|
||||||
p->engine.ps.psmarg[pos] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static void
|
|
||||||
ps_end(struct termp *p)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At the end of the file, do one last showpage. This is the
|
|
||||||
* same behaviour as groff(1) and works for multiple pages as
|
|
||||||
* well as just one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert(0 == p->engine.ps.psstate);
|
|
||||||
assert('\0' == p->engine.ps.last);
|
|
||||||
assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]);
|
|
||||||
printf("%s", p->engine.ps.psmarg);
|
|
||||||
printf("showpage\n");
|
|
||||||
printf("%s\n", "%%EOF");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_begin(struct termp *p)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print margins into margin buffer. Nothing gets output to the
|
|
||||||
* screen yet, so we don't need to initialise the primary state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (p->engine.ps.psmarg) {
|
|
||||||
assert(p->engine.ps.psmargsz);
|
|
||||||
p->engine.ps.psmarg[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
p->engine.ps.psmargcur = 0;
|
|
||||||
p->engine.ps.psstate = PS_MARGINS;
|
|
||||||
p->engine.ps.pscol = PS_CHAR_LEFT;
|
|
||||||
p->engine.ps.psrow = PS_CHAR_TOPMARG;
|
|
||||||
|
|
||||||
ps_setfont(p, TERMFONT_NONE);
|
|
||||||
|
|
||||||
(*p->headf)(p, p->argf);
|
|
||||||
(*p->endline)(p);
|
|
||||||
|
|
||||||
p->engine.ps.pscol = PS_CHAR_LEFT;
|
|
||||||
p->engine.ps.psrow = PS_CHAR_BOTMARG;
|
|
||||||
|
|
||||||
(*p->footf)(p, p->argf);
|
|
||||||
(*p->endline)(p);
|
|
||||||
|
|
||||||
p->engine.ps.psstate &= ~PS_MARGINS;
|
|
||||||
|
|
||||||
assert(0 == p->engine.ps.psstate);
|
|
||||||
assert(p->engine.ps.psmarg);
|
|
||||||
assert('\0' != p->engine.ps.psmarg[0]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print header and initialise page state. Following this,
|
|
||||||
* stuff gets printed to the screen, so make sure we're sane.
|
|
||||||
*/
|
|
||||||
|
|
||||||
printf("%s\n", "%!PS");
|
|
||||||
ps_setfont(p, TERMFONT_NONE);
|
|
||||||
p->engine.ps.pscol = PS_CHAR_LEFT;
|
|
||||||
p->engine.ps.psrow = PS_CHAR_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_pletter(struct termp *p, char c)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're not in a PostScript "word" context, then open one
|
|
||||||
* now at the current cursor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! (PS_INLINE & p->engine.ps.psstate)) {
|
|
||||||
ps_printf(p, "%zu %zu moveto\n(",
|
|
||||||
p->engine.ps.pscol,
|
|
||||||
p->engine.ps.psrow);
|
|
||||||
p->engine.ps.psstate |= PS_INLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to escape these characters as per the PostScript
|
|
||||||
* specification. We would also escape non-graphable characters
|
|
||||||
* (like tabs), but none of them would get to this point and
|
|
||||||
* it's superfluous to abort() on them.
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case ('('):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case (')'):
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ('\\'):
|
|
||||||
ps_putchar(p, '\\');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the character and adjust where we are on the page. */
|
|
||||||
|
|
||||||
ps_putchar(p, c);
|
|
||||||
p->engine.ps.pscol += PS_CHAR_WIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_pclose(struct termp *p)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spit out that we're exiting a word context (this is a
|
|
||||||
* "partial close" because we don't check the last-char buffer
|
|
||||||
* or anything).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! (PS_INLINE & p->engine.ps.psstate))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ps_printf(p, ") show\n");
|
|
||||||
p->engine.ps.psstate &= ~PS_INLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_fclose(struct termp *p)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Strong closure: if we have a last-char, spit it out after
|
|
||||||
* checking that we're in the right font mode. This will of
|
|
||||||
* course open a new scope, if applicable.
|
|
||||||
*
|
|
||||||
* Following this, close out any scope that's open.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ('\0' != p->engine.ps.last) {
|
|
||||||
if (p->engine.ps.lastf != TERMFONT_NONE) {
|
|
||||||
ps_pclose(p);
|
|
||||||
ps_setfont(p, TERMFONT_NONE);
|
|
||||||
}
|
|
||||||
ps_pletter(p, p->engine.ps.last);
|
|
||||||
p->engine.ps.last = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! (PS_INLINE & p->engine.ps.psstate))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ps_pclose(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_letter(struct termp *p, char c)
|
|
||||||
{
|
|
||||||
char cc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* State machine dictates whether to buffer the last character
|
|
||||||
* or not. Basically, encoded words are detected by checking if
|
|
||||||
* we're an "8" and switching on the buffer. Then we put "8" in
|
|
||||||
* our buffer, and on the next charater, flush both character
|
|
||||||
* and buffer. Thus, "regular" words are detected by having a
|
|
||||||
* regular character and a regular buffer character.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ('\0' == p->engine.ps.last) {
|
|
||||||
assert(8 != c);
|
|
||||||
p->engine.ps.last = c;
|
|
||||||
return;
|
|
||||||
} else if (8 == p->engine.ps.last) {
|
|
||||||
assert(8 != c);
|
|
||||||
p->engine.ps.last = '\0';
|
|
||||||
} else if (8 == c) {
|
|
||||||
assert(8 != p->engine.ps.last);
|
|
||||||
if ('_' == p->engine.ps.last) {
|
|
||||||
if (p->engine.ps.lastf != TERMFONT_UNDER) {
|
|
||||||
ps_pclose(p);
|
|
||||||
ps_setfont(p, TERMFONT_UNDER);
|
|
||||||
}
|
|
||||||
} else if (p->engine.ps.lastf != TERMFONT_BOLD) {
|
|
||||||
ps_pclose(p);
|
|
||||||
ps_setfont(p, TERMFONT_BOLD);
|
|
||||||
}
|
|
||||||
p->engine.ps.last = c;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (p->engine.ps.lastf != TERMFONT_NONE) {
|
|
||||||
ps_pclose(p);
|
|
||||||
ps_setfont(p, TERMFONT_NONE);
|
|
||||||
}
|
|
||||||
cc = p->engine.ps.last;
|
|
||||||
p->engine.ps.last = c;
|
|
||||||
c = cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ps_pletter(p, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_advance(struct termp *p, size_t len)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Advance some spaces. This can probably be made smarter,
|
|
||||||
* i.e., to have multiple space-separated words in the same
|
|
||||||
* scope, but this is easier: just close out the current scope
|
|
||||||
* and readjust our column settings.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ps_fclose(p);
|
|
||||||
p->engine.ps.pscol += len ? len * PS_CHAR_WIDTH : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_endline(struct termp *p)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Close out any scopes we have open: we're at eoln. */
|
|
||||||
|
|
||||||
ps_fclose(p);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're in the margin, don't try to recalculate our current
|
|
||||||
* row. XXX: if the column tries to be fancy with multiple
|
|
||||||
* lines, we'll do nasty stuff.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (PS_MARGINS & p->engine.ps.psstate)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Put us down a line. If we're at the page bottom, spit out a
|
|
||||||
* showpage and restart our row.
|
|
||||||
*/
|
|
||||||
|
|
||||||
p->engine.ps.pscol = PS_CHAR_LEFT;
|
|
||||||
if (p->engine.ps.psrow >= PS_CHAR_HEIGHT + PS_CHAR_BOT) {
|
|
||||||
p->engine.ps.psrow -= PS_CHAR_HEIGHT;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]);
|
|
||||||
printf("%s", p->engine.ps.psmarg);
|
|
||||||
printf("showpage\n");
|
|
||||||
p->engine.ps.psrow = PS_CHAR_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ps_setfont(struct termp *p, enum termfont f)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (TERMFONT_BOLD == f)
|
|
||||||
ps_printf(p, "/Courier-Bold\n");
|
|
||||||
else if (TERMFONT_UNDER == f)
|
|
||||||
ps_printf(p, "/Courier-Oblique\n");
|
|
||||||
else
|
|
||||||
ps_printf(p, "/Courier\n");
|
|
||||||
|
|
||||||
ps_printf(p, "10 selectfont\n");
|
|
||||||
p->engine.ps.lastf = f;
|
|
||||||
}
|
|
||||||
|
|
3
common/lib/libutil/Makefile.inc
Normal file
3
common/lib/libutil/Makefile.inc
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# $NetBSD: Makefile.inc,v 1.1 2008/12/16 22:33:11 christos Exp $
|
||||||
|
.PATH.c: ${.PARSEDIR}
|
||||||
|
SRCS+= snprintb.c
|
282
common/lib/libutil/snprintb.c
Normal file
282
common/lib/libutil/snprintb.c
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
/* $NetBSD: snprintb.c,v 1.5 2009/05/13 02:50:31 pgoyette Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* snprintb: print an interpreted bitmask to a buffer
|
||||||
|
*
|
||||||
|
* => returns the length of the buffer that would be required to print the
|
||||||
|
* string minus the terminating NUL.
|
||||||
|
*/
|
||||||
|
#ifndef _STANDALONE
|
||||||
|
# ifndef _KERNEL
|
||||||
|
|
||||||
|
# if HAVE_NBTOOL_CONFIG_H
|
||||||
|
# include "nbtool_config.h"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# include <sys/cdefs.h>
|
||||||
|
# if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: snprintb.c,v 1.5 2009/05/13 02:50:31 pgoyette Exp $");
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/inttypes.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <util.h>
|
||||||
|
# include <errno.h>
|
||||||
|
# else
|
||||||
|
# include <sys/cdefs.h>
|
||||||
|
__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.5 2009/05/13 02:50:31 pgoyette Exp $");
|
||||||
|
# include <sys/param.h>
|
||||||
|
# include <sys/inttypes.h>
|
||||||
|
# include <sys/systm.h>
|
||||||
|
# include <lib/libkern/libkern.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
int
|
||||||
|
snprintb_m(char *buf, size_t buflen, const char *bitfmt, uint64_t val,
|
||||||
|
size_t l_max)
|
||||||
|
{
|
||||||
|
char *bp = buf, *s_bp = NULL;
|
||||||
|
const char *c_fmt, *s_fmt = NULL, *cur_fmt;
|
||||||
|
const char *sbase;
|
||||||
|
int bit, ch, t_len, s_len = 0, l_len, f_len, v_len, sep;
|
||||||
|
int restart = 0;
|
||||||
|
uint64_t field;
|
||||||
|
|
||||||
|
#ifdef _KERNEL
|
||||||
|
/*
|
||||||
|
* For safety; no other *s*printf() do this, but in the kernel
|
||||||
|
* we don't usually check the return value
|
||||||
|
*/
|
||||||
|
(void)memset(buf, 0, buflen);
|
||||||
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
|
ch = *bitfmt++;
|
||||||
|
switch (ch != '\177' ? ch : *bitfmt++) {
|
||||||
|
case 8:
|
||||||
|
sbase = "0%" PRIo64;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
sbase = "%" PRId64;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
sbase = "0x%" PRIx64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserve space for trailing blank line if needed */
|
||||||
|
if (l_max > 0)
|
||||||
|
buflen--;
|
||||||
|
|
||||||
|
t_len = snprintf(bp, buflen, sbase, val);
|
||||||
|
if (t_len < 0)
|
||||||
|
goto internal;
|
||||||
|
|
||||||
|
v_len = l_len = t_len;
|
||||||
|
|
||||||
|
if ((size_t)t_len < buflen)
|
||||||
|
bp += t_len;
|
||||||
|
else
|
||||||
|
bp += buflen - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the value we printed was 0 and we're using the old-style format,
|
||||||
|
* we're done.
|
||||||
|
*/
|
||||||
|
if ((val == 0) && (ch != '\177'))
|
||||||
|
goto terminate;
|
||||||
|
|
||||||
|
#define STORE(c) { l_len++; \
|
||||||
|
if ((size_t)(++t_len) < buflen) \
|
||||||
|
*bp++ = (c); \
|
||||||
|
} while ( /* CONSTCOND */ 0)
|
||||||
|
|
||||||
|
#define BACKUP { if (s_bp != NULL) { \
|
||||||
|
bp = s_bp; s_bp = NULL; \
|
||||||
|
t_len -= l_len - s_len; \
|
||||||
|
restart = 1; \
|
||||||
|
bitfmt = s_fmt; \
|
||||||
|
} \
|
||||||
|
STORE('>'); STORE('\0'); \
|
||||||
|
if ((size_t)t_len < buflen) \
|
||||||
|
snprintf(bp, buflen - t_len, sbase, val); \
|
||||||
|
t_len += v_len; l_len = v_len; bp += v_len; \
|
||||||
|
} while ( /* CONSTCOND */ 0)
|
||||||
|
|
||||||
|
#define PUTSEP \
|
||||||
|
if (l_max > 0 && (size_t)l_len >= l_max) { \
|
||||||
|
BACKUP; \
|
||||||
|
STORE('<'); \
|
||||||
|
} else { \
|
||||||
|
/* Remember separator location */ \
|
||||||
|
if ( l_max > 0 && sep != '<') { \
|
||||||
|
s_len = l_len; \
|
||||||
|
s_bp = bp; \
|
||||||
|
s_fmt = cur_fmt; \
|
||||||
|
} \
|
||||||
|
STORE(sep); \
|
||||||
|
restart = 0; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define PUTCHR(c) \
|
||||||
|
if (l_max > 0 && (size_t)l_len >= (l_max - 1)) { \
|
||||||
|
BACKUP; \
|
||||||
|
if (restart == 0) { \
|
||||||
|
STORE(c); \
|
||||||
|
} else \
|
||||||
|
sep = '<'; \
|
||||||
|
} else { \
|
||||||
|
STORE(c); \
|
||||||
|
restart = 0; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define PUTS(s) while ((ch = *(s)++) != 0) { \
|
||||||
|
PUTCHR(ch); \
|
||||||
|
if (restart) \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chris Torek's new bitmask format is identified by a leading \177
|
||||||
|
*/
|
||||||
|
sep = '<';
|
||||||
|
if (ch != '\177') {
|
||||||
|
/* old (standard) format. */
|
||||||
|
for (;(bit = *bitfmt) != 0;) {
|
||||||
|
cur_fmt = bitfmt++;
|
||||||
|
if (val & (1 << (bit - 1))) {
|
||||||
|
PUTSEP;
|
||||||
|
if (restart)
|
||||||
|
continue;
|
||||||
|
sep = ',';
|
||||||
|
for (; (ch = *bitfmt) > ' '; ++bitfmt) {
|
||||||
|
PUTCHR(ch);
|
||||||
|
if (restart)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
for (; *bitfmt > ' '; ++bitfmt)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* new quad-capable format; also does fields. */
|
||||||
|
field = val;
|
||||||
|
while (c_fmt = bitfmt, (ch = *bitfmt++) != '\0') {
|
||||||
|
bit = *bitfmt++; /* now 0-origin */
|
||||||
|
switch (ch) {
|
||||||
|
case 'b':
|
||||||
|
if (((u_int)(val >> bit) & 1) == 0)
|
||||||
|
goto skip;
|
||||||
|
cur_fmt = c_fmt;
|
||||||
|
PUTSEP;
|
||||||
|
if (restart)
|
||||||
|
break;
|
||||||
|
PUTS(bitfmt);
|
||||||
|
if (restart == 0)
|
||||||
|
sep = ',';
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
cur_fmt = c_fmt;
|
||||||
|
f_len = *bitfmt++; /* field length */
|
||||||
|
field = (val >> bit) &
|
||||||
|
(((uint64_t)1 << f_len) - 1);
|
||||||
|
if (ch == 'F') /* just extract */
|
||||||
|
break;
|
||||||
|
PUTSEP;
|
||||||
|
if (restart == 0) {
|
||||||
|
sep = ',';
|
||||||
|
PUTS(bitfmt);
|
||||||
|
}
|
||||||
|
if (restart == 0) {
|
||||||
|
PUTCHR('=');
|
||||||
|
}
|
||||||
|
if (restart == 0) {
|
||||||
|
f_len = snprintf(bp, buflen - t_len,
|
||||||
|
sbase, field);
|
||||||
|
if (f_len < 0)
|
||||||
|
goto internal;
|
||||||
|
t_len += f_len;
|
||||||
|
l_len += f_len;
|
||||||
|
if ((size_t)t_len < buflen)
|
||||||
|
bp += f_len;
|
||||||
|
if (l_max > 0 &&
|
||||||
|
(size_t)l_len > l_max) {
|
||||||
|
PUTCHR('#');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
case ':':
|
||||||
|
/*
|
||||||
|
* Here "bit" is actually a value instead,
|
||||||
|
* to be compared against the last field.
|
||||||
|
* This only works for values in [0..255],
|
||||||
|
* of course.
|
||||||
|
*/
|
||||||
|
if ((int)field != bit)
|
||||||
|
goto skip;
|
||||||
|
if (ch == '=') {
|
||||||
|
PUTCHR('=');
|
||||||
|
}
|
||||||
|
PUTS(bitfmt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
skip:
|
||||||
|
while (*bitfmt++ != '\0')
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l_len++;
|
||||||
|
if ((size_t)(++t_len) < buflen)
|
||||||
|
*bp++ = '>';
|
||||||
|
terminate:
|
||||||
|
*bp++ = '\0';
|
||||||
|
if (l_max != 0) {
|
||||||
|
t_len++;
|
||||||
|
*bp = '\0';
|
||||||
|
}
|
||||||
|
return t_len;
|
||||||
|
internal:
|
||||||
|
#ifndef _KERNEL
|
||||||
|
errno = EINVAL;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
snprintb(char *buf, size_t buflen, const char *bitfmt, uint64_t val)
|
||||||
|
{
|
||||||
|
return snprintb_m(buf, buflen, bitfmt, val, 0);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,3 +1,7 @@
|
||||||
|
20110928:
|
||||||
|
Update your /usr/etc/daily and /etc/man.conf if you
|
||||||
|
want to fully enjoy the manpage fixes.
|
||||||
|
|
||||||
20110817:
|
20110817:
|
||||||
To use the new asynchronous version of VFS do:
|
To use the new asynchronous version of VFS do:
|
||||||
# BUILDAVFS=yes make cleandepend world
|
# BUILDAVFS=yes make cleandepend world
|
||||||
|
|
|
@ -5,7 +5,7 @@ FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile \
|
||||||
protocols rc services termcap ttytab utmp rc.cd binary_sizes \
|
protocols rc services termcap ttytab utmp rc.cd binary_sizes \
|
||||||
binary_sizes.big binary_sizes.xxl syslog.conf rc.daemons.dist \
|
binary_sizes.big binary_sizes.xxl syslog.conf rc.daemons.dist \
|
||||||
rs.inet rs.single make.conf system.conf ttys resolv.conf rc.conf \
|
rs.inet rs.single make.conf system.conf ttys resolv.conf rc.conf \
|
||||||
rc.subr
|
rc.subr man.conf
|
||||||
|
|
||||||
FILES2=shadow
|
FILES2=shadow
|
||||||
FILES3=daily dhcptags.conf rc
|
FILES3=daily dhcptags.conf rc
|
||||||
|
|
16
etc/man.conf
Normal file
16
etc/man.conf
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
_version BSD.2
|
||||||
|
_subdir man{[1-9],1x}
|
||||||
|
_suffix .0
|
||||||
|
_build .[1-9] mandoc %s
|
||||||
|
_build .tbl tbl %s | mandoc
|
||||||
|
_default /usr/{,pkg/{,gcc44/}}man
|
||||||
|
_whatdb /usr/{,pkg/{,gcc44/}}man/whatis.db
|
||||||
|
1 man1
|
||||||
|
2 man2
|
||||||
|
3 man3
|
||||||
|
4 man4
|
||||||
|
5 man5
|
||||||
|
6 man6
|
||||||
|
7 man7
|
||||||
|
8 man8
|
||||||
|
9 man9
|
|
@ -66,6 +66,9 @@ do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Update manpage index
|
||||||
|
/usr/libexec/makewhatis
|
||||||
|
|
||||||
# Continue with a local script if present.
|
# Continue with a local script if present.
|
||||||
test -f /usr/local/etc/daily && sh /usr/local/etc/daily $caller
|
test -f /usr/local/etc/daily && sh /usr/local/etc/daily $caller
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
@ -21,7 +21,7 @@ SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libdriver libnetdriver \
|
||||||
libddekit libminixfs
|
libddekit libminixfs
|
||||||
|
|
||||||
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")
|
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")
|
||||||
SUBDIR+= libelf libminc libcrypt libterminfo libcurses libvassert
|
SUBDIR+= libelf libminc libcrypt libterminfo libcurses libvassert libutil
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${COMPILER_TYPE} == "ack"
|
.if ${COMPILER_TYPE} == "ack"
|
||||||
|
@ -31,7 +31,6 @@ SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
|
||||||
.if ${OBJECT_FMT} == "a.out"
|
.if ${OBJECT_FMT} == "a.out"
|
||||||
SUBDIR+= libend
|
SUBDIR+= libend
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.include <bsd.subdir.mk>
|
.include <bsd.subdir.mk>
|
||||||
|
|
||||||
build_ack:
|
build_ack:
|
||||||
|
|
92
lib/libutil/Makefile
Normal file
92
lib/libutil/Makefile
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
# $NetBSD: Makefile,v 1.63 2010/01/27 19:10:31 drochner Exp $
|
||||||
|
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||||
|
|
||||||
|
USE_SHLIBDIR= yes
|
||||||
|
|
||||||
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
|
.include "${NETBSDSRCDIR}/common/lib/libutil/Makefile.inc"
|
||||||
|
|
||||||
|
WARNS= 4
|
||||||
|
LIB= util
|
||||||
|
CPPFLAGS+=-DLIBC_SCCS -I${.CURDIR}
|
||||||
|
SRCS= efun.c getbootfile.c \
|
||||||
|
getmntopts.c \
|
||||||
|
login.c loginx.c login_tty.c logout.c logoutx.c \
|
||||||
|
logwtmp.c logwtmpx.c opendisk.c \
|
||||||
|
passwd.c pw_scan.c pidfile.c pidlock.c pty.c \
|
||||||
|
raise_default_signal.c \
|
||||||
|
secure_path.c snprintb.c \
|
||||||
|
ttyaction.c
|
||||||
|
#disklabel_dkcksum.c disklabel_scan.c \
|
||||||
|
#if_media.c \
|
||||||
|
#sockaddr_snprintf.c
|
||||||
|
#getlabelsector.c
|
||||||
|
#getmaxpartitions.c
|
||||||
|
#stat_flags.c
|
||||||
|
#getrawpartition.c
|
||||||
|
#login_cap.c
|
||||||
|
#ttymsg.c
|
||||||
|
#parsedate.y
|
||||||
|
|
||||||
|
MAN= efun.3 getbootfile.3 getlabelsector.3 getmaxpartitions.3 \
|
||||||
|
getmntopts.3 \
|
||||||
|
getrawpartition.3 \
|
||||||
|
login.3 login_cap.3 loginx.3 \
|
||||||
|
disklabel_dkcksum.3 disklabel_scan.3 \
|
||||||
|
opendisk.3 openpty.3 parsedate.3 pidfile.3 pidlock.3 \
|
||||||
|
pw_getconf.3 pw_init.3 pw_lock.3 secure_path.3 \
|
||||||
|
raise_default_signal.3 \
|
||||||
|
snprintb.3 sockaddr_snprintf.3 stat_flags.3 ttyaction.3 \
|
||||||
|
ttymsg.3 util.3
|
||||||
|
|
||||||
|
YPREFIX=__pd
|
||||||
|
#.PATH: ${NETBSDSRCDIR}/lib/libc/gen
|
||||||
|
.PATH: ${NETBSDSRCDIR}/lib/nbsd_libc/gen
|
||||||
|
|
||||||
|
#.include "compat/Makefile.inc"
|
||||||
|
|
||||||
|
MLINKS+=getlabelsector.3 getlabeloffset.3
|
||||||
|
MLINKS+=login.3 logout.3
|
||||||
|
MLINKS+=login.3 logwtmp.3
|
||||||
|
MLINKS+=login_cap.3 login_getclass.3
|
||||||
|
MLINKS+=login_cap.3 login_getcapbool.3
|
||||||
|
MLINKS+=login_cap.3 login_getcapnum.3
|
||||||
|
MLINKS+=login_cap.3 login_getcapsize.3
|
||||||
|
MLINKS+=login_cap.3 login_getcapstr.3
|
||||||
|
MLINKS+=login_cap.3 login_getcaptime.3
|
||||||
|
MLINKS+=login_cap.3 login_close.3
|
||||||
|
MLINKS+=login_cap.3 setclasscontext.3
|
||||||
|
MLINKS+=login_cap.3 setusercontext.3
|
||||||
|
MLINKS+=loginx.3 logoutx.3 loginx.3 logwtmpx.3
|
||||||
|
MLINKS+=openpty.3 login_tty.3
|
||||||
|
MLINKS+=openpty.3 forkpty.3
|
||||||
|
MLINKS+=pw_getconf.3 pw_getpwconf.3
|
||||||
|
MLINKS+=pw_init.3 pw_edit.3
|
||||||
|
MLINKS+=pw_init.3 pw_prompt.3
|
||||||
|
MLINKS+=pw_init.3 pw_copy.3
|
||||||
|
MLINKS+=pw_init.3 pw_copyx.3
|
||||||
|
MLINKS+=pw_init.3 pw_scan.3
|
||||||
|
MLINKS+=pw_init.3 pw_error.3
|
||||||
|
MLINKS+=pw_lock.3 pw_mkdb.3
|
||||||
|
MLINKS+=pw_lock.3 pw_abort.3
|
||||||
|
MLINKS+=pw_lock.3 pw_getprefix.3
|
||||||
|
MLINKS+=pw_lock.3 pw_setprefix.3
|
||||||
|
MLINKS+=pidlock.3 ttylock.3
|
||||||
|
MLINKS+=pidlock.3 ttyunlock.3
|
||||||
|
MLINKS+=efun.3 esetfunc.3
|
||||||
|
MLINKS+=efun.3 easprintf.3
|
||||||
|
MLINKS+=efun.3 estrlcpy.3
|
||||||
|
MLINKS+=efun.3 estrlcat.3
|
||||||
|
MLINKS+=efun.3 estrdup.3
|
||||||
|
MLINKS+=efun.3 estrndup.3
|
||||||
|
MLINKS+=efun.3 emalloc.3
|
||||||
|
MLINKS+=efun.3 ecalloc.3
|
||||||
|
MLINKS+=efun.3 erealloc.3
|
||||||
|
MLINKS+=efun.3 efopen.3
|
||||||
|
MLINKS+=efun.3 evasprintf.3
|
||||||
|
MLINKS+=stat_flags.3 string_to_flags.3
|
||||||
|
MLINKS+=stat_flags.3 flags_to_string.3
|
||||||
|
MLINKS+=snprintb.3 snprintb_m.3
|
||||||
|
|
||||||
|
.include <bsd.lib.mk>
|
7
lib/libutil/compat/Makefile.inc
Normal file
7
lib/libutil/compat/Makefile.inc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# $NetBSD: Makefile.inc,v 1.2 2009/01/11 02:57:18 christos Exp $
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR}/compat
|
||||||
|
|
||||||
|
CPPFLAGS+=-I${.CURDIR}/../libc -I${.CURDIR}/../../sys
|
||||||
|
SRCS+=compat_passwd.c compat_loginx.c compat_login.c compat_parsedate.c \
|
||||||
|
compat_login_cap.c
|
63
lib/libutil/compat/compat_gepwconf.c
Normal file
63
lib/libutil/compat/compat_gepwconf.c
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* $NetBSD: compat_gepwconf.c,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the NetBSD
|
||||||
|
* Foundation, Inc. and its contributors.
|
||||||
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: compat_gepwconf.c,v 1.2 2009/01/11 02:57:18 christos Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#define __LIBC12_SOURCE__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <compat/include/pwd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <compat/util.h>
|
||||||
|
|
||||||
|
__warn_references(pw_getpwconf,
|
||||||
|
"warning: reference to compatibility pw_getpwconf(); "
|
||||||
|
"include <pwd.h> to generate correct reference")
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_getpwconf(char *buf, size_t len, const struct passwd50 *p, const char *opt)
|
||||||
|
{
|
||||||
|
struct passwd px;
|
||||||
|
passwd50_to_passwd(p, &px);
|
||||||
|
__pw_getpwconf50(buf, len, &px, opt);
|
||||||
|
}
|
78
lib/libutil/compat/compat_login.c
Normal file
78
lib/libutil/compat/compat_login.c
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/* $NetBSD: compat_login.c,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)login.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: compat_login.c,v 1.2 2009/01/11 02:57:18 christos Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#define __LIBC12_SOURCE__
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <compat/util.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <compat/include/utmp.h>
|
||||||
|
|
||||||
|
__warn_references(login,
|
||||||
|
"warning: reference to compatibility login(); include <util.h> to generate correct reference")
|
||||||
|
|
||||||
|
void
|
||||||
|
login(const struct utmp50 *ut50)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int tty;
|
||||||
|
struct utmp ut;
|
||||||
|
|
||||||
|
utmp50_to_utmp(ut50, &ut);
|
||||||
|
|
||||||
|
tty = ttyslot();
|
||||||
|
if (tty > 0 && (fd = open(_PATH_UTMP, O_WRONLY|O_CREAT, 0644)) >= 0) {
|
||||||
|
(void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
|
||||||
|
(void)write(fd, &ut, sizeof(ut));
|
||||||
|
(void)close(fd);
|
||||||
|
}
|
||||||
|
if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) {
|
||||||
|
(void)write(fd, &ut, sizeof(ut));
|
||||||
|
(void)close(fd);
|
||||||
|
}
|
||||||
|
}
|
70
lib/libutil/compat/compat_login_cap.c
Normal file
70
lib/libutil/compat/compat_login_cap.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/* $NetBSD: compat_login_cap.c,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the NetBSD
|
||||||
|
* Foundation, Inc. and its contributors.
|
||||||
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#define __LIBC12_SOURCE__
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <login_cap.h>
|
||||||
|
#include <compat/login_cap.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <compat/include/pwd.h>
|
||||||
|
|
||||||
|
__warn_references(login_getpwclass,
|
||||||
|
"warning: reference to compatibility login_getpwclass();"
|
||||||
|
" include <login_cap.h> for correct reference")
|
||||||
|
__warn_references(setusercontext,
|
||||||
|
"warning: reference to compatibility setusercontext();"
|
||||||
|
" include <login_cap.h> for correct reference")
|
||||||
|
|
||||||
|
login_cap_t *
|
||||||
|
login_getpwclass(const struct passwd50 *pw50)
|
||||||
|
{
|
||||||
|
struct passwd pw;
|
||||||
|
|
||||||
|
passwd50_to_passwd(pw50, &pw);
|
||||||
|
return __login_getpwclass50(&pw);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
setusercontext(login_cap_t *lc, struct passwd50 *pw50, uid_t uid, u_int flags)
|
||||||
|
{
|
||||||
|
struct passwd pw;
|
||||||
|
|
||||||
|
passwd50_to_passwd(pw50, &pw);
|
||||||
|
return __setusercontext50(lc, &pw, uid, flags);
|
||||||
|
}
|
64
lib/libutil/compat/compat_loginx.c
Normal file
64
lib/libutil/compat/compat_loginx.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/* $NetBSD: compat_loginx.c,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: compat_loginx.c,v 1.2 2009/01/11 02:57:18 christos Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define __LIBC12_SOURCE__
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <compat/util.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <compat/include/utmp.h>
|
||||||
|
#include <utmpx.h>
|
||||||
|
#include <compat/include/utmpx.h>
|
||||||
|
|
||||||
|
__warn_references(loginx,
|
||||||
|
"warning: reference to compatibility loginx(); include <util.h> to generate correct reference")
|
||||||
|
|
||||||
|
void
|
||||||
|
loginx(const struct utmpx50 *ut50)
|
||||||
|
{
|
||||||
|
struct utmpx ut;
|
||||||
|
utmpx50_to_utmpx(ut50, &ut);
|
||||||
|
(void)__pututxline50(&ut);
|
||||||
|
(void)__updwtmpx50(_PATH_WTMPX, &ut);
|
||||||
|
}
|
73
lib/libutil/compat/compat_logoutx.c
Normal file
73
lib/libutil/compat/compat_logoutx.c
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/* $NetBSD: compat_logoutx.c,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)logout.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: compat_logoutx.c,v 1.2 2009/01/11 02:57:18 christos Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <utmpx.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
logoutx(const char *line, int status, int type)
|
||||||
|
{
|
||||||
|
struct utmpx *utp, ut;
|
||||||
|
(void)strlcpy(ut.ut_line, line, sizeof(ut.ut_line));
|
||||||
|
if ((utp = getutxline(&ut)) == NULL) {
|
||||||
|
endutxent();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
utp->ut_type = type;
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
utp->ut_exit.e_exit = (uint16_t)WEXITSTATUS(status);
|
||||||
|
if (WIFSIGNALED(status))
|
||||||
|
utp->ut_exit.e_termination = (uint16_t)WTERMSIG(status);
|
||||||
|
(void)gettimeofday(&utp->ut_tv, NULL);
|
||||||
|
(void)pututxline(utp);
|
||||||
|
endutxent();
|
||||||
|
return 1;
|
||||||
|
}
|
60
lib/libutil/compat/compat_parsedate.c
Normal file
60
lib/libutil/compat/compat_parsedate.c
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* $NetBSD: compat_parsedate.c,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the NetBSD
|
||||||
|
* Foundation, Inc. and its contributors.
|
||||||
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#define __LIBC12_SOURCE__
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <compat/include/time.h>
|
||||||
|
#include <compat/sys/time.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <compat/util.h>
|
||||||
|
|
||||||
|
__warn_references(parsedate,
|
||||||
|
"warning: reference to compatibility parsedate();"
|
||||||
|
" include <util.h> for correct reference")
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
parsedate(const char *str, const int32_t *t50, const int *tzoff)
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
if (t50)
|
||||||
|
t = *t50;
|
||||||
|
return (int32_t)__parsedate50(str, t50 ? &t : NULL, tzoff);
|
||||||
|
}
|
103
lib/libutil/compat/compat_passwd.c
Normal file
103
lib/libutil/compat/compat_passwd.c
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/* $NetBSD: compat_passwd.c,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the NetBSD
|
||||||
|
* Foundation, Inc. and its contributors.
|
||||||
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: compat_passwd.c,v 1.2 2009/01/11 02:57:18 christos Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#define __LIBC12_SOURCE__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <compat/include/pwd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <compat/util.h>
|
||||||
|
|
||||||
|
__warn_references(pw_scan,
|
||||||
|
"warning: reference to compatibility pw_scan(); "
|
||||||
|
"include <pwd.h> to generate correct reference")
|
||||||
|
__warn_references(pw_copy,
|
||||||
|
"warning: reference to compatibility pw_copy(); "
|
||||||
|
"include <util.h> to generate correct reference")
|
||||||
|
__warn_references(pw_copyx,
|
||||||
|
"warning: reference to compatibility pw_copyx(); "
|
||||||
|
"include <util.h> to generate correct reference")
|
||||||
|
__warn_references(pw_getpwconf,
|
||||||
|
"warning: reference to compatibility pw_getpwconf(); "
|
||||||
|
"include <pwd.h> to generate correct reference")
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_scan(char *buf, struct passwd50 *p, int *flags)
|
||||||
|
{
|
||||||
|
struct passwd px;
|
||||||
|
int rv = __pw_scan50(buf, &px, flags);
|
||||||
|
passwd_to_passwd50(&px, p);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_copy(int ffd, int tfd, struct passwd50 *pw50, struct passwd50 *opw50)
|
||||||
|
{
|
||||||
|
struct passwd pw, opw;
|
||||||
|
passwd50_to_passwd(pw50, &pw);
|
||||||
|
if (opw50)
|
||||||
|
passwd50_to_passwd(opw50, &opw);
|
||||||
|
__pw_copy50(ffd, tfd, &pw, opw50 ? &opw : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_copyx(int ffd, int tfd, struct passwd50 *pw50, struct passwd50 *opw50,
|
||||||
|
char *errbuf, size_t errbufsiz)
|
||||||
|
{
|
||||||
|
struct passwd pw, opw;
|
||||||
|
passwd50_to_passwd(pw50, &pw);
|
||||||
|
if (opw50)
|
||||||
|
passwd50_to_passwd(opw50, &opw);
|
||||||
|
return __pw_copyx50(ffd, tfd, &pw, opw50 ? &opw : NULL, errbuf,
|
||||||
|
errbufsiz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_getpwconf(char *buf, size_t len, const struct passwd50 *p, const char *opt)
|
||||||
|
{
|
||||||
|
struct passwd px;
|
||||||
|
passwd50_to_passwd(p, &px);
|
||||||
|
__pw_getpwconf50(buf, len, &px, opt);
|
||||||
|
}
|
51
lib/libutil/compat/login_cap.h
Normal file
51
lib/libutil/compat/login_cap.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/* $NetBSD: login_cap.h,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the NetBSD
|
||||||
|
* Foundation, Inc. and its contributors.
|
||||||
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#ifndef _COMPAT_LOGIN_CAP_H_
|
||||||
|
#define _COMPAT_LOGIN_CAP_H_
|
||||||
|
|
||||||
|
struct passwd;
|
||||||
|
struct passwd50;
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
login_cap_t *login_getpwclass(const struct passwd50 *);
|
||||||
|
login_cap_t *__login_getpwclass50(const struct passwd *);
|
||||||
|
int setusercontext(login_cap_t *, struct passwd50 *, uid_t, u_int);
|
||||||
|
int __setusercontext50(login_cap_t *, struct passwd *, uid_t, u_int);
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* !_COMPAT_LOGIN_CAP_H_ */
|
63
lib/libutil/compat/util.h
Normal file
63
lib/libutil/compat/util.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* $NetBSD: util.h,v 1.2 2009/01/11 02:57:18 christos Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1995
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _COMPAT_UTIL_H_
|
||||||
|
#define _COMPAT_UTIL_H_
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <compat/include/pwd.h>
|
||||||
|
#include <compat/include/utmp.h>
|
||||||
|
#include <compat/include/utmpx.h>
|
||||||
|
#include <machine/ansi.h>
|
||||||
|
|
||||||
|
void login(const struct utmp50 *);
|
||||||
|
void loginx(const struct utmpx50 *);
|
||||||
|
|
||||||
|
int32_t parsedate(const char *, const int32_t *, const int *);
|
||||||
|
|
||||||
|
void pw_copy(int, int, struct passwd50 *, struct passwd50 *);
|
||||||
|
int pw_copyx(int, int, struct passwd50 *, struct passwd50 *,
|
||||||
|
char *, size_t);
|
||||||
|
void pw_getpwconf(char *, size_t, const struct passwd50 *,
|
||||||
|
const char *);
|
||||||
|
|
||||||
|
void __login50(const struct utmp *);
|
||||||
|
void __loginx50(const struct utmpx *);
|
||||||
|
|
||||||
|
time_t __parsedate50(const char *, const time_t *, const int *);
|
||||||
|
|
||||||
|
void __pw_copy50(int, int, struct passwd *, struct passwd *);
|
||||||
|
int __pw_copyx50(int, int, struct passwd *, struct passwd *,
|
||||||
|
char *, size_t);
|
||||||
|
void __pw_getpwconf50(char *, size_t, const struct passwd *,
|
||||||
|
const char *);
|
||||||
|
#endif /* !_COMPAT_UTIL_H_ */
|
56
lib/libutil/disklabel_dkcksum.3
Normal file
56
lib/libutil/disklabel_dkcksum.3
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
.\" $NetBSD: disklabel_dkcksum.3,v 1.8 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Roland C. Dowdeswell.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt DISKLABEL_DKCKSUM 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm disklabel_dkcksum
|
||||||
|
.Nd compute the checksum for a disklabel
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft uint16_t
|
||||||
|
.Fo disklabel_dkcksum
|
||||||
|
.Fa "struct disklabel *lp"
|
||||||
|
.Fc
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn disklabel_dkcksum
|
||||||
|
computes the checksum for the disklabel passed in as
|
||||||
|
.Fa lp .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn disklabel_dkcksum
|
||||||
|
returns the computed checksum.
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn disklabel_dkcksum
|
||||||
|
function call appeared in
|
||||||
|
.Nx 2.0 .
|
58
lib/libutil/disklabel_dkcksum.c
Normal file
58
lib/libutil/disklabel_dkcksum.c
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* $NetBSD: disklabel_dkcksum.c,v 1.4 2005/05/15 21:01:34 thorpej Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)dkcksum.c 8.1 (Berkeley) 6/5/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: disklabel_dkcksum.c,v 1.4 2005/05/15 21:01:34 thorpej Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/disklabel.h>
|
||||||
|
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
disklabel_dkcksum(struct disklabel *lp)
|
||||||
|
{
|
||||||
|
uint16_t *start, *end;
|
||||||
|
uint16_t sum;
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
start = (uint16_t *)(void *)lp;
|
||||||
|
end = (uint16_t *)(void *)&lp->d_partitions[lp->d_npartitions];
|
||||||
|
while (start < end)
|
||||||
|
sum ^= *start++;
|
||||||
|
return (sum);
|
||||||
|
}
|
59
lib/libutil/disklabel_scan.3
Normal file
59
lib/libutil/disklabel_scan.3
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
.\" $NetBSD: disklabel_scan.3,v 1.6 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Roland C. Dowdeswell.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt DISKLABEL_SCAN 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm disklabel_scan
|
||||||
|
.Nd scan a buffer for a valid disklabel
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn disklabel_scan "struct disklabel *lp" "char *buf" "size_t buflen"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn disklabel_scan
|
||||||
|
scans the memory region specified by
|
||||||
|
.Fa buf
|
||||||
|
and
|
||||||
|
.Fa buflen
|
||||||
|
for a valid disklabel.
|
||||||
|
If such a label is found, it is copied into
|
||||||
|
.Fa lp .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn disklabel_scan
|
||||||
|
function returns 0 if a valid disklabel was found and 1 if not.
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn disklabel_scan
|
||||||
|
function call appeared in
|
||||||
|
.Nx 2.0 .
|
69
lib/libutil/disklabel_scan.c
Normal file
69
lib/libutil/disklabel_scan.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/* $NetBSD: disklabel_scan.c,v 1.3 2009/01/18 12:13:03 lukem Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Roland C. Dowdeswell.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
__COPYRIGHT(
|
||||||
|
"@(#) Copyright (c) 2002\
|
||||||
|
The NetBSD Foundation, Inc. All rights reserved.");
|
||||||
|
__RCSID("$NetBSD: disklabel_scan.c,v 1.3 2009/01/18 12:13:03 lukem Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
#include <sys/disklabel.h>
|
||||||
|
|
||||||
|
#define SCAN_INCR 4
|
||||||
|
|
||||||
|
int
|
||||||
|
disklabel_scan(struct disklabel *lp, char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* scan for the correct magic numbers. */
|
||||||
|
|
||||||
|
for (i=0; i <= buflen - sizeof(*lp); i += SCAN_INCR) {
|
||||||
|
memcpy(lp, buf + i, sizeof(*lp));
|
||||||
|
if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC)
|
||||||
|
goto sanity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sanity:
|
||||||
|
/* we've found something, let's sanity check it */
|
||||||
|
if (lp->d_npartitions > MAXPARTITIONS || disklabel_dkcksum(lp))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
117
lib/libutil/efun.3
Normal file
117
lib/libutil/efun.3
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
.\" $NetBSD: efun.3,v 1.10 2010/05/03 05:40:37 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Christos Zoulas.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 3, 2010
|
||||||
|
.Dt EFUN 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm esetfunc ,
|
||||||
|
.Nm easprintf ,
|
||||||
|
.Nm efopen ,
|
||||||
|
.Nm emalloc ,
|
||||||
|
.Nm ecalloc ,
|
||||||
|
.Nm erealloc ,
|
||||||
|
.Nm estrdup ,
|
||||||
|
.Nm estrndup ,
|
||||||
|
.Nm estrlcat ,
|
||||||
|
.Nm estrlcpy ,
|
||||||
|
.Nm evasprintf
|
||||||
|
.Nd error-checked utility functions
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft void (*)(int, const char *, ...)
|
||||||
|
.Fn esetfunc "void (*)(int, const char *, ...)"
|
||||||
|
.Ft int
|
||||||
|
.Fn easprintf "char ** restrict str" "const char * restrict fmt" "..."
|
||||||
|
.Ft FILE *
|
||||||
|
.Fn efopen "const char *p" "const char *m"
|
||||||
|
.Ft void *
|
||||||
|
.Fn ecalloc "size_t n" "size_t c"
|
||||||
|
.Ft void *
|
||||||
|
.Fn emalloc "size_t n"
|
||||||
|
.Ft void *
|
||||||
|
.Fn erealloc "void *p" "size_t n"
|
||||||
|
.Ft char *
|
||||||
|
.Fn estrdup "const char *s"
|
||||||
|
.Ft char *
|
||||||
|
.Fn estrndup "const char *s" "size_t len"
|
||||||
|
.Ft size_t
|
||||||
|
.Fn estrlcat "char *dst" "const char *src" "size_t len"
|
||||||
|
.Ft size_t
|
||||||
|
.Fn estrlcpy "char *dst" "const char *src" "size_t len"
|
||||||
|
.Ft int
|
||||||
|
.Fn evasprintf "char ** restrict str" "const char * restrict fmt" "..."
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn easprintf ,
|
||||||
|
.Fn efopen ,
|
||||||
|
.Fn ecalloc ,
|
||||||
|
.Fn emalloc ,
|
||||||
|
.Fn erealloc ,
|
||||||
|
.Fn estrdup ,
|
||||||
|
.Fn estrndup ,
|
||||||
|
.Fn estrlcat ,
|
||||||
|
.Fn estrlcpy ,
|
||||||
|
and
|
||||||
|
.Fn evasprintf
|
||||||
|
functions
|
||||||
|
operate exactly as the corresponding functions that do not start with an
|
||||||
|
.Sq e
|
||||||
|
except that in case of an error, they call
|
||||||
|
the installed error handler that can be configured with
|
||||||
|
.Fn esetfunc .
|
||||||
|
.Pp
|
||||||
|
For the string handling functions, it is an error when the destination
|
||||||
|
buffer is not large enough to hold the complete string.
|
||||||
|
For functions that allocate memory or open a file, it is an error when
|
||||||
|
they would return a null pointer.
|
||||||
|
The default error handler is
|
||||||
|
.Xr err 3 .
|
||||||
|
The function
|
||||||
|
.Fn esetfunc
|
||||||
|
returns the previous error handler function.
|
||||||
|
A
|
||||||
|
.Dv NULL
|
||||||
|
error handler will just call
|
||||||
|
.Xr exit 3 .
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr asprintf 3 ,
|
||||||
|
.Xr calloc 3 ,
|
||||||
|
.Xr err 3 ,
|
||||||
|
.Xr exit 3 ,
|
||||||
|
.Xr fopen 3 ,
|
||||||
|
.Xr malloc 3 ,
|
||||||
|
.Xr realloc 3 ,
|
||||||
|
.Xr strdup 3 ,
|
||||||
|
.Xr strlcat 3 ,
|
||||||
|
.Xr strlcpy 3 ,
|
||||||
|
.Xr strndup 3 ,
|
||||||
|
.Xr vasprintf 3
|
158
lib/libutil/efun.c
Normal file
158
lib/libutil/efun.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/* $NetBSD: efun.c,v 1.6 2008/04/28 20:23:02 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_NBTOOL_CONFIG_H
|
||||||
|
#include "nbtool_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifdef __RCSID
|
||||||
|
__RCSID("$NetBSD: efun.c,v 1.6 2008/04/28 20:23:02 martin Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
static void (*efunc)(int, const char *, ...) = err;
|
||||||
|
|
||||||
|
void (*
|
||||||
|
esetfunc(void (*ef)(int, const char *, ...)))(int, const char *, ...)
|
||||||
|
{
|
||||||
|
void (*of)(int, const char *, ...) = efunc;
|
||||||
|
efunc = ef == NULL ? (void (*)(int, const char *, ...))exit : ef;
|
||||||
|
return of;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
estrlcpy(char *dst, const char *src, size_t len)
|
||||||
|
{
|
||||||
|
size_t rv;
|
||||||
|
if ((rv = strlcpy(dst, src, len)) >= len) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
(*efunc)(1,
|
||||||
|
"Cannot copy string; %zu chars needed %zu provided",
|
||||||
|
rv, len);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
estrlcat(char *dst, const char *src, size_t len)
|
||||||
|
{
|
||||||
|
size_t rv;
|
||||||
|
if ((rv = strlcat(dst, src, len)) >= len) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
(*efunc)(1,
|
||||||
|
"Cannot append to string; %zu chars needed %zu provided",
|
||||||
|
rv, len);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
estrdup(const char *s)
|
||||||
|
{
|
||||||
|
char *d = strdup(s);
|
||||||
|
if (d == NULL)
|
||||||
|
(*efunc)(1, "Cannot copy string");
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
estrndup(const char *s, size_t len)
|
||||||
|
{
|
||||||
|
char *d = strndup(s, len);
|
||||||
|
if (d == NULL)
|
||||||
|
(*efunc)(1, "Cannot copy string");
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
emalloc(size_t n)
|
||||||
|
{
|
||||||
|
void *p = malloc(n);
|
||||||
|
if (p == NULL)
|
||||||
|
(*efunc)(1, "Cannot allocate %zu bytes", n);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
ecalloc(size_t n, size_t s)
|
||||||
|
{
|
||||||
|
void *p = calloc(n, s);
|
||||||
|
if (p == NULL)
|
||||||
|
(*efunc)(1, "Cannot allocate %zu bytes", n);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
erealloc(void *p, size_t n)
|
||||||
|
{
|
||||||
|
void *q = realloc(p, n);
|
||||||
|
if (q == NULL)
|
||||||
|
(*efunc)(1, "Cannot re-allocate %zu bytes", n);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *
|
||||||
|
efopen(const char *p, const char *m)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(p, m);
|
||||||
|
if (fp == NULL)
|
||||||
|
(*efunc)(1, "Cannot open `%s'", p);
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
easprintf(char ** __restrict ret, const char * __restrict format, ...)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
if ((rv = vasprintf(ret, format, ap)) == -1)
|
||||||
|
(*efunc)(1, "Cannot format string");
|
||||||
|
va_end(ap);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evasprintf(char ** __restrict ret, const char * __restrict format, va_list ap)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
if ((rv = vasprintf(ret, format, ap)) == -1)
|
||||||
|
(*efunc)(1, "Cannot format string");
|
||||||
|
return rv;
|
||||||
|
}
|
61
lib/libutil/getbootfile.3
Normal file
61
lib/libutil/getbootfile.3
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
.\" $NetBSD: getbootfile.3,v 1.9 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Thomas Klausner.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt GETBOOTFILE 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm getbootfile
|
||||||
|
.Nd get the name of the booted kernel file
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft const char *
|
||||||
|
.Fn getbootfile void
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn getbootfile
|
||||||
|
returns a static pointer to the full path name of the file from which
|
||||||
|
the current kernel was loaded.
|
||||||
|
If it can not be determined, or the file is not ``secure'' (see
|
||||||
|
.Xr secure_path 3 ) ,
|
||||||
|
.Dv _PATH_UNIX
|
||||||
|
from
|
||||||
|
.In paths.h
|
||||||
|
is returned instead.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr secure_path 3 ,
|
||||||
|
.Xr sysctl 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn getbootfile
|
||||||
|
function call appeared in
|
||||||
|
.Fx 2.0
|
||||||
|
and
|
||||||
|
.Nx 1.6 .
|
84
lib/libutil/getbootfile.c
Normal file
84
lib/libutil/getbootfile.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/* $NetBSD: getbootfile.c,v 1.5 2008/04/28 20:23:02 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Thomas Klausner.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: getbootfile.c,v 1.5 2008/04/28 20:23:02 martin Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
#ifdef CPU_BOOTED_KERNEL
|
||||||
|
static char name[MAXPATHLEN];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *
|
||||||
|
getbootfile(void)
|
||||||
|
{
|
||||||
|
#ifdef CPU_BOOTED_KERNEL
|
||||||
|
int mib[2];
|
||||||
|
size_t size;
|
||||||
|
#endif
|
||||||
|
const char *kernel;
|
||||||
|
|
||||||
|
kernel = _PATH_UNIX;
|
||||||
|
#ifdef CPU_BOOTED_KERNEL
|
||||||
|
/* find real boot-kernel name */
|
||||||
|
mib[0] = CTL_MACHDEP;
|
||||||
|
mib[1] = CPU_BOOTED_KERNEL;
|
||||||
|
size = sizeof(name) - 1;
|
||||||
|
if (sysctl(mib, 2, name + 1, &size, NULL, 0) == 0) {
|
||||||
|
/*
|
||||||
|
* traditionally, this sysctl returns the relative
|
||||||
|
* path of the kernel with the leading slash stripped
|
||||||
|
* -- could be empty, though (e.g. when netbooting).
|
||||||
|
*/
|
||||||
|
if (name[1] != '\0') {
|
||||||
|
name[0] = '/';
|
||||||
|
kernel = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we got a valid and 'secure' filename */
|
||||||
|
if (strcmp(kernel, _PATH_UNIX) != 0 &&
|
||||||
|
secure_path(kernel) != 0) {
|
||||||
|
/* doesn't seems so, fall back to default */
|
||||||
|
kernel = _PATH_UNIX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (kernel);
|
||||||
|
}
|
75
lib/libutil/getlabelsector.3
Normal file
75
lib/libutil/getlabelsector.3
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
.\" $NetBSD: getlabelsector.3,v 1.5 2009/06/24 22:31:58 zafer Exp $
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.\" Copyright 2002 Wasabi Systems, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Written by Steve C. Woodford for Wasabi Systems, Inc.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\" This product includes software developed for the NetBSD Project by
|
||||||
|
.\" Wasabi Systems, Inc.
|
||||||
|
.\" 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||||
|
.\" or promote products derived from this software without specific prior
|
||||||
|
.\" written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd December 11, 2002
|
||||||
|
.Dt GETLABELSECTOR 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm getlabelsector ,
|
||||||
|
.Nm getlabeloffset
|
||||||
|
.Nd get the sector number and offset of the disklabel
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft daddr_t
|
||||||
|
.Fn getlabelsector void
|
||||||
|
.Ft off_t
|
||||||
|
.Fn getlabeloffset void
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn getlabelsector
|
||||||
|
and
|
||||||
|
.Fn getlabeloffset
|
||||||
|
functions return values which describe the exact on-disk location of the
|
||||||
|
.Xr disklabel 5
|
||||||
|
on the current system, or \-1 on error.
|
||||||
|
These functions supersede the hardcoded
|
||||||
|
.Dv LABELSECTOR
|
||||||
|
and
|
||||||
|
.Dv LABELOFFSET
|
||||||
|
definitions previously used to derive the location of the
|
||||||
|
.Xr disklabel 5 .
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr sysctl 3 ,
|
||||||
|
.Xr disklabel 5
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn getlabelsector
|
||||||
|
and
|
||||||
|
.Fn getlabeloffset
|
||||||
|
functions appeared in
|
||||||
|
.Nx 2.0 .
|
75
lib/libutil/getlabelsector.c
Normal file
75
lib/libutil/getlabelsector.c
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* $NetBSD: getlabelsector.c,v 1.3 2005/09/17 01:51:21 elad Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2002 Wasabi Systems, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Written by Steve C. Woodford for Wasabi Systems, Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed for the NetBSD Project by
|
||||||
|
* Wasabi Systems, Inc.
|
||||||
|
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||||
|
* or promote products derived from this software without specific prior
|
||||||
|
* written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: getlabelsector.c,v 1.3 2005/09/17 01:51:21 elad Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
getlabelsector(void)
|
||||||
|
{
|
||||||
|
int sector, mib[2];
|
||||||
|
size_t varlen;
|
||||||
|
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_LABELSECTOR;
|
||||||
|
varlen = sizeof(sector);
|
||||||
|
if (sysctl(mib, 2, §or, &varlen, NULL, (size_t)0) < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t
|
||||||
|
getlabeloffset(void)
|
||||||
|
{
|
||||||
|
int offset, mib[2];
|
||||||
|
size_t varlen;
|
||||||
|
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_LABELOFFSET;
|
||||||
|
varlen = sizeof(offset);
|
||||||
|
if (sysctl(mib, 2, &offset, &varlen, NULL, (size_t)0) < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
return ((off_t)offset);
|
||||||
|
}
|
59
lib/libutil/getmaxpartitions.3
Normal file
59
lib/libutil/getmaxpartitions.3
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
.\" $NetBSD: getmaxpartitions.3,v 1.10 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Jason R. Thorpe.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt GETMAXPARTITIONS 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm getmaxpartitions
|
||||||
|
.Nd get the maximum number of partitions allowed per disk
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn getmaxpartitions void
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn getmaxpartitions
|
||||||
|
returns the number of partitions that are allowed per disk on the
|
||||||
|
system, or \-1 in case of an error, setting the global
|
||||||
|
.Va errno
|
||||||
|
variable.
|
||||||
|
The possible values for
|
||||||
|
.Va errno
|
||||||
|
are the same as in
|
||||||
|
.Xr sysctl 3 .
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr getrawpartition 3 ,
|
||||||
|
.Xr sysctl 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn getmaxpartitions
|
||||||
|
function call appeared in
|
||||||
|
.Nx 1.2 .
|
54
lib/libutil/getmaxpartitions.c
Normal file
54
lib/libutil/getmaxpartitions.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* $NetBSD: getmaxpartitions.c,v 1.6 2008/04/28 20:23:02 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Jason R. Thorpe.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: getmaxpartitions.c,v 1.6 2008/04/28 20:23:02 martin Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
getmaxpartitions(void)
|
||||||
|
{
|
||||||
|
int maxpart, mib[2];
|
||||||
|
size_t varlen;
|
||||||
|
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_MAXPARTITIONS;
|
||||||
|
varlen = sizeof(maxpart);
|
||||||
|
if (sysctl(mib, 2, &maxpart, &varlen, NULL, (size_t)0) < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
return (maxpart);
|
||||||
|
}
|
277
lib/libutil/getmntopts.3
Normal file
277
lib/libutil/getmntopts.3
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
.\" $NetBSD: getmntopts.3,v 1.12 2010/08/24 12:05:01 christos Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1994
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt GETMNTOPTS 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm getmntopts
|
||||||
|
.Nd scan mount options
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In mntopts.h
|
||||||
|
.Ft mntoptparse_t
|
||||||
|
.Fn getmntopts "const char *options" "const struct mntopt *mopts" "int *flagp" "int *altflagp"
|
||||||
|
.Ft const char *
|
||||||
|
.Fn getmntoptstr "mntoptparse_t mp" "const char *opt"
|
||||||
|
.Ft long
|
||||||
|
.Fn getmntoptnum "mntoptparse_t mp" "const char *opt"
|
||||||
|
.Ft void
|
||||||
|
.Fn freemntopts "mntoptparse_t mp"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn getmntopts
|
||||||
|
function takes a comma separated option list and a list
|
||||||
|
of valid option names, and computes the bitmasks
|
||||||
|
corresponding to the requested set of options.
|
||||||
|
.Pp
|
||||||
|
The string
|
||||||
|
.Ar options
|
||||||
|
is broken down into a sequence of comma separated tokens.
|
||||||
|
Each token is looked up in the table described by
|
||||||
|
.Ar mopts
|
||||||
|
and the bits in
|
||||||
|
the word referenced by either
|
||||||
|
.Ar flagp
|
||||||
|
or
|
||||||
|
.Ar altflagp
|
||||||
|
(depending on the
|
||||||
|
.Dv m_altloc
|
||||||
|
field of the option's table entry)
|
||||||
|
are updated.
|
||||||
|
The flag words are not initialized by
|
||||||
|
.Fn getmntopts .
|
||||||
|
The table,
|
||||||
|
.Ar mopts ,
|
||||||
|
has the following format:
|
||||||
|
.Bd -literal
|
||||||
|
struct mntopt {
|
||||||
|
const char *m_option; /* option name */
|
||||||
|
int m_inverse; /* negative option, e.g., "dev" */
|
||||||
|
int m_flag; /* bit to set, e.g., MNT_RDONLY */
|
||||||
|
int m_altloc; /* use altflagp rather than flagp */
|
||||||
|
};
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The members of this structure are:
|
||||||
|
.Bl -tag -width m_inverse
|
||||||
|
.It Fa m_option
|
||||||
|
the option name,
|
||||||
|
for example
|
||||||
|
.Dq suid .
|
||||||
|
.It Fa m_inverse
|
||||||
|
tells
|
||||||
|
.Fn getmntopts
|
||||||
|
that the name has the inverse meaning of the bit.
|
||||||
|
For example,
|
||||||
|
.Dq suid
|
||||||
|
is the string, whereas the mount flag is
|
||||||
|
.Dv MNT_NOSUID .
|
||||||
|
In this case, the sense of the string and the flag
|
||||||
|
are inverted, so the
|
||||||
|
.Fa m_inverse
|
||||||
|
flag should be set.
|
||||||
|
.It Fa m_flag
|
||||||
|
the value of the bit to be set or cleared in
|
||||||
|
the flag word when the option is recognized.
|
||||||
|
The bit is set when the option is discovered,
|
||||||
|
but cleared if the option name was preceded
|
||||||
|
by the letters
|
||||||
|
.Dq no .
|
||||||
|
The
|
||||||
|
.Fa m_inverse
|
||||||
|
flag causes these two operations to be reversed.
|
||||||
|
.It Fa m_altloc
|
||||||
|
the bit should be set or cleared in
|
||||||
|
.Ar altflagp
|
||||||
|
rather than
|
||||||
|
.Ar flagp .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Each of the user visible
|
||||||
|
.Dv MNT_
|
||||||
|
flags has a corresponding
|
||||||
|
.Dv MOPT_
|
||||||
|
macro which defines an appropriate
|
||||||
|
.Li "struct mntopt"
|
||||||
|
entry.
|
||||||
|
To simplify the program interface and ensure consistency across all
|
||||||
|
programs, a general purpose macro,
|
||||||
|
.Dv MOPT_STDOPTS ,
|
||||||
|
is defined which contains an entry for all the generic VFS options.
|
||||||
|
In addition, the macros
|
||||||
|
.Dv MOPT_FORCE
|
||||||
|
and
|
||||||
|
.Dv MOPT_UPDATE
|
||||||
|
exist to enable the
|
||||||
|
.Dv MNT_FORCE
|
||||||
|
and
|
||||||
|
.Dv MNT_UPDATE
|
||||||
|
flags to be set.
|
||||||
|
Finally, the table must be terminated by an entry with a
|
||||||
|
.Dv NULL
|
||||||
|
first element.
|
||||||
|
.Pp
|
||||||
|
.Fn getmntopts
|
||||||
|
returns a
|
||||||
|
.Li "mntoptparse_t"
|
||||||
|
handle that can be used in subsequent
|
||||||
|
.Fn getmntoptstr
|
||||||
|
and
|
||||||
|
.Fn getmntoptnum
|
||||||
|
calls to fetch a value for an option and that must be freed with a call
|
||||||
|
to
|
||||||
|
.Fn freemntopts .
|
||||||
|
If an error occurred, then if the external integer value
|
||||||
|
.Va getmnt_silent
|
||||||
|
is zero then
|
||||||
|
.Fn getmntopts
|
||||||
|
prints an error message and exits;
|
||||||
|
if
|
||||||
|
.Va getmnt_silent
|
||||||
|
is non-zero then
|
||||||
|
.Fn getmntopts
|
||||||
|
returns
|
||||||
|
.Dv NULL .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn getmntoptstr
|
||||||
|
function returns the string value of the named option, if such a value
|
||||||
|
was set in the option string.
|
||||||
|
If the value was not set, then if the external integer value
|
||||||
|
.Va getmnt_silent
|
||||||
|
is zero then
|
||||||
|
.Fn getmntoptstr
|
||||||
|
prints an error message and exits;
|
||||||
|
if
|
||||||
|
.Va getmnt_silent
|
||||||
|
is non-zero then
|
||||||
|
.Fn getmntoptstr
|
||||||
|
returns
|
||||||
|
.Dv NULL .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn getmntoptnum
|
||||||
|
returns the long value of the named option, if such a value was set in the
|
||||||
|
option string.
|
||||||
|
If the value was not set, or could not be converted from a string to a
|
||||||
|
long, then if the external integer value
|
||||||
|
.Va getmnt_silent
|
||||||
|
is zero then
|
||||||
|
.Fn getmntoptnum
|
||||||
|
prints an error message and exits;
|
||||||
|
if
|
||||||
|
.Va getmnt_silent
|
||||||
|
is non-zero then
|
||||||
|
.Fn getmntoptnum
|
||||||
|
returns \-1.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn freemntopts
|
||||||
|
frees the storage used by
|
||||||
|
.Fn getmntopts .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn getmntopts
|
||||||
|
returns
|
||||||
|
.Dv NULL
|
||||||
|
if an error occurred.
|
||||||
|
Note that some bits may already have been set in
|
||||||
|
.Va flagp
|
||||||
|
and
|
||||||
|
.Va altflagp
|
||||||
|
even if
|
||||||
|
.Dv NULL
|
||||||
|
is returned.
|
||||||
|
.Fn getmntoptstr
|
||||||
|
returns
|
||||||
|
.Dv NULL
|
||||||
|
if an error occurred.
|
||||||
|
.Fn getmntoptnum
|
||||||
|
returns \-1 if an error occurred.
|
||||||
|
.Sh EXAMPLES
|
||||||
|
Most commands will use the standard option set.
|
||||||
|
Local filesystems which support the
|
||||||
|
.Dv MNT_UPDATE
|
||||||
|
flag, would also have an
|
||||||
|
.Dv MOPT_UPDATE
|
||||||
|
entry.
|
||||||
|
This can be declared and used as follows:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
#include \*[Lt]mntopts.h\*[Gt]
|
||||||
|
|
||||||
|
static const struct mntopt mopts[] = {
|
||||||
|
MOPT_STDOPTS,
|
||||||
|
MOPT_UPDATE,
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
\&...
|
||||||
|
|
||||||
|
long val;
|
||||||
|
mntoptparse_t mp;
|
||||||
|
mntflags = mntaltflags = 0;
|
||||||
|
|
||||||
|
\&...
|
||||||
|
|
||||||
|
mp = getmntopts(options, mopts, \*[Am]mntflags, \*[Am]mntaltflags);
|
||||||
|
|
||||||
|
if (mp == NULL)
|
||||||
|
err(EXIT_FAILURE, "getmntopts");
|
||||||
|
|
||||||
|
\&...
|
||||||
|
|
||||||
|
val = getmntoptnum(mp, "rsize");
|
||||||
|
freemntopts(mp);
|
||||||
|
.Ed
|
||||||
|
.Sh DIAGNOSTICS
|
||||||
|
If the external integer variable
|
||||||
|
.Va getmnt_silent
|
||||||
|
is zero then the
|
||||||
|
.Fn getmntopts ,
|
||||||
|
.Fn getmntoptstr ,
|
||||||
|
and
|
||||||
|
.Fn getmntoptnum
|
||||||
|
functions display an error message and exit if an error occurred.
|
||||||
|
By default
|
||||||
|
.Va getmnt_silent
|
||||||
|
is zero.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr err 3 ,
|
||||||
|
.Xr mount 8
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn getmntopts
|
||||||
|
function appeared in
|
||||||
|
.Bx 4.4 .
|
||||||
|
It was moved to the utilities library and enhanced to retrieve option
|
||||||
|
values in
|
||||||
|
.Nx 2.0 .
|
194
lib/libutil/getmntopts.c
Normal file
194
lib/libutil/getmntopts.c
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/* $NetBSD: getmntopts.c,v 1.4 2007/08/26 22:46:15 pooka Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: getmntopts.c,v 1.4 2007/08/26 22:46:15 pooka Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fstab.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <mntopts.h>
|
||||||
|
|
||||||
|
int getmnt_silent = 0;
|
||||||
|
|
||||||
|
static const char errmsg[] = "-o %s: option not supported";
|
||||||
|
|
||||||
|
struct mntoptparse {
|
||||||
|
const char *options;
|
||||||
|
const struct mntopt *mopts;
|
||||||
|
char *optbuf;
|
||||||
|
char **optarg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
getmntoptstr(mntoptparse_t mp, const char *opt)
|
||||||
|
{
|
||||||
|
const struct mntopt *m;
|
||||||
|
|
||||||
|
for (m = mp->mopts; m->m_option != NULL; m++)
|
||||||
|
if (strcasecmp(opt, m->m_option) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (m->m_option == NULL) {
|
||||||
|
if (getmnt_silent == 0)
|
||||||
|
errx(1, errmsg, opt);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mp->optarg[m - mp->mopts];
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
getmntoptnum(mntoptparse_t mp, const char *opt)
|
||||||
|
{
|
||||||
|
char *ep;
|
||||||
|
long rv;
|
||||||
|
void (*fun)(int, const char *, ...) = NULL;
|
||||||
|
const char *val = getmntoptstr(mp, opt);
|
||||||
|
|
||||||
|
if (val == NULL) {
|
||||||
|
if (getmnt_silent == 0)
|
||||||
|
errx(1, "Missing %s argument", opt);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
rv = strtol(val, &ep, 0);
|
||||||
|
|
||||||
|
if (*ep)
|
||||||
|
fun = errx;
|
||||||
|
|
||||||
|
if (errno == ERANGE && (rv == LONG_MAX || rv == LONG_MIN))
|
||||||
|
fun = err;
|
||||||
|
|
||||||
|
if (fun) {
|
||||||
|
if (getmnt_silent != 0)
|
||||||
|
return -1;
|
||||||
|
(*fun)(1, "Invalid %s argument `%s'", opt, val);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
freemntopts(mntoptparse_t mp)
|
||||||
|
{
|
||||||
|
free(mp->optbuf);
|
||||||
|
free(mp->optarg);
|
||||||
|
free(mp);
|
||||||
|
}
|
||||||
|
|
||||||
|
mntoptparse_t
|
||||||
|
getmntopts(const char *options, const struct mntopt *m0, int *flagp,
|
||||||
|
int *altflagp)
|
||||||
|
{
|
||||||
|
const struct mntopt *m;
|
||||||
|
int negative;
|
||||||
|
char *opt, *p;
|
||||||
|
int *thisflagp;
|
||||||
|
size_t nopts;
|
||||||
|
mntoptparse_t mp;
|
||||||
|
|
||||||
|
for (nopts = 0, m = m0; m->m_option != NULL; ++m, nopts++)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((mp = malloc(sizeof(struct mntoptparse))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Copy option string, since it is about to be torn asunder... */
|
||||||
|
if ((mp->optbuf = strdup(options)) == NULL) {
|
||||||
|
free(mp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mp->optarg = calloc(nopts, sizeof(char *))) == NULL) {
|
||||||
|
free(mp->optbuf);
|
||||||
|
free(mp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp->mopts = m0;
|
||||||
|
mp->options = options;
|
||||||
|
|
||||||
|
for (opt = mp->optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
|
||||||
|
/* Check for "no" prefix. */
|
||||||
|
if (opt[0] == 'n' && opt[1] == 'o') {
|
||||||
|
negative = 1;
|
||||||
|
opt += 2;
|
||||||
|
} else
|
||||||
|
negative = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* for options with assignments in them (ie. quotas)
|
||||||
|
* ignore the assignment as it's handled elsewhere
|
||||||
|
*/
|
||||||
|
p = strchr(opt, '=');
|
||||||
|
if (p) {
|
||||||
|
*p++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan option table. */
|
||||||
|
for (m = m0; m->m_option != NULL; ++m)
|
||||||
|
if (strcasecmp(opt, m->m_option) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Save flag, or fail if option is not recognised. */
|
||||||
|
if (m->m_option) {
|
||||||
|
mp->optarg[m - m0] = p;
|
||||||
|
thisflagp = m->m_altloc ? altflagp : flagp;
|
||||||
|
if (negative == m->m_inverse)
|
||||||
|
*thisflagp |= m->m_flag;
|
||||||
|
else
|
||||||
|
*thisflagp &= ~m->m_flag;
|
||||||
|
} else if (!getmnt_silent) {
|
||||||
|
errx(1, errmsg, opt);
|
||||||
|
} else {
|
||||||
|
free(mp->optbuf);
|
||||||
|
free(mp);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mp;
|
||||||
|
}
|
71
lib/libutil/getrawpartition.3
Normal file
71
lib/libutil/getrawpartition.3
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
.\" $NetBSD: getrawpartition.3,v 1.11 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Jason R. Thorpe.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt GETRAWPARTITION 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm getrawpartition
|
||||||
|
.Nd get the system
|
||||||
|
.Dq raw
|
||||||
|
partition
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn getrawpartition void
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn getrawpartition
|
||||||
|
returns the partition number (
|
||||||
|
.Sq a
|
||||||
|
== 0,
|
||||||
|
.Sq b
|
||||||
|
== 1, ...) of the
|
||||||
|
.Dq raw
|
||||||
|
partition of the system's disks,
|
||||||
|
or \-1 in case of an error, setting the global
|
||||||
|
.Va errno
|
||||||
|
variable.
|
||||||
|
The possible values for
|
||||||
|
.Va errno
|
||||||
|
are the same as in
|
||||||
|
.Xr sysctl 3 .
|
||||||
|
The
|
||||||
|
.Dq raw
|
||||||
|
partition is defined as the partition which provides access to the entire
|
||||||
|
disk, regardless of the disk's partition map.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr getmaxpartitions 3 ,
|
||||||
|
.Xr sysctl 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn getrawpartition
|
||||||
|
function call appeared in
|
||||||
|
.Nx 1.2 .
|
54
lib/libutil/getrawpartition.c
Normal file
54
lib/libutil/getrawpartition.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* $NetBSD: getrawpartition.c,v 1.6 2008/04/28 20:23:03 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Jason R. Thorpe.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: getrawpartition.c,v 1.6 2008/04/28 20:23:03 martin Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
getrawpartition()
|
||||||
|
{
|
||||||
|
int rawpart, mib[2];
|
||||||
|
size_t varlen;
|
||||||
|
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_RAWPARTITION;
|
||||||
|
varlen = sizeof(rawpart);
|
||||||
|
if (sysctl(mib, 2, &rawpart, &varlen, NULL, (size_t)0) < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
return (rawpart);
|
||||||
|
}
|
180
lib/libutil/if_media.c
Normal file
180
lib/libutil/if_media.c
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/* $NetBSD: if_media.c,v 1.2 2008/04/28 20:23:03 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||||
|
* NASA Ames Research Center.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: if_media.c,v 1.2 2008/04/28 20:23:03 martin Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <net/if_media.h>
|
||||||
|
|
||||||
|
struct ifmedia_description ifm_mode_descriptions[] =
|
||||||
|
IFM_MODE_DESCRIPTIONS;
|
||||||
|
|
||||||
|
struct ifmedia_description ifm_type_descriptions[] =
|
||||||
|
IFM_TYPE_DESCRIPTIONS;
|
||||||
|
|
||||||
|
struct ifmedia_description ifm_subtype_descriptions[] =
|
||||||
|
IFM_SUBTYPE_DESCRIPTIONS;
|
||||||
|
|
||||||
|
struct ifmedia_description ifm_option_descriptions[] =
|
||||||
|
IFM_OPTION_DESCRIPTIONS;
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_media_type_string(int mword)
|
||||||
|
{
|
||||||
|
struct ifmedia_description *desc;
|
||||||
|
|
||||||
|
for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) {
|
||||||
|
if (IFM_TYPE(mword) == desc->ifmt_word)
|
||||||
|
return (desc->ifmt_string);
|
||||||
|
}
|
||||||
|
return "<unknown type>";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_media_subtype_string(int mword)
|
||||||
|
{
|
||||||
|
struct ifmedia_description *desc;
|
||||||
|
|
||||||
|
for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL;
|
||||||
|
desc++) {
|
||||||
|
if (IFM_TYPE_MATCH(desc->ifmt_word, mword) &&
|
||||||
|
IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword))
|
||||||
|
return desc->ifmt_string;
|
||||||
|
}
|
||||||
|
return "<unknown subtype>";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_media_mode_string(int mword)
|
||||||
|
{
|
||||||
|
struct ifmedia_description *desc;
|
||||||
|
|
||||||
|
for (desc = ifm_mode_descriptions; desc->ifmt_string != NULL; desc++) {
|
||||||
|
if (IFM_TYPE_MATCH(desc->ifmt_word, mword) &&
|
||||||
|
IFM_MODE(mword) == IFM_MODE(desc->ifmt_word))
|
||||||
|
return desc->ifmt_string;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_media_option_string(int *mwordp)
|
||||||
|
{
|
||||||
|
struct ifmedia_description *desc;
|
||||||
|
int mword = *mwordp;
|
||||||
|
|
||||||
|
for (desc = ifm_option_descriptions; desc->ifmt_string != NULL;
|
||||||
|
desc++) {
|
||||||
|
if (!IFM_TYPE_MATCH(desc->ifmt_word, mword))
|
||||||
|
continue;
|
||||||
|
if (mword & IFM_OPTIONS(desc->ifmt_word)) {
|
||||||
|
*mwordp = mword & ~IFM_OPTIONS(desc->ifmt_word);
|
||||||
|
return desc->ifmt_string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Historical behaviour is to ignore unknown option bits! */
|
||||||
|
*mwordp = mword & ~IFM_OPTIONS(~0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lookup_media_word(struct ifmedia_description *desc, int type, const char *val)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (; desc->ifmt_string != NULL; desc++) {
|
||||||
|
if (IFM_TYPE_MATCH(desc->ifmt_word, type) &&
|
||||||
|
strcasecmp(desc->ifmt_string, val) == 0)
|
||||||
|
return (desc->ifmt_word);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_media_mode(int type, const char *val)
|
||||||
|
{
|
||||||
|
|
||||||
|
return lookup_media_word(ifm_mode_descriptions, type, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_media_subtype(int type, const char *val)
|
||||||
|
{
|
||||||
|
|
||||||
|
return lookup_media_word(ifm_subtype_descriptions, type, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_media_options(int type, const char *val, char **invalid)
|
||||||
|
{
|
||||||
|
char *optlist, *str;
|
||||||
|
int option, rval = 0;
|
||||||
|
|
||||||
|
/* We muck with the string, so copy it. */
|
||||||
|
optlist = strdup(val);
|
||||||
|
if (optlist == NULL) {
|
||||||
|
if (invalid != NULL)
|
||||||
|
*invalid = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
str = optlist;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the options in the user-provided comma-separated list.
|
||||||
|
*/
|
||||||
|
type = IFM_TYPE(type);
|
||||||
|
for (; (str = strtok(str, ",")) != NULL; str = NULL) {
|
||||||
|
option = lookup_media_word(ifm_option_descriptions, type, str);
|
||||||
|
if (option != -1) {
|
||||||
|
rval |= IFM_OPTIONS(option);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rval = -1;
|
||||||
|
if (invalid == NULL)
|
||||||
|
break;
|
||||||
|
/* Pass invalid option at start of malloced buffer */
|
||||||
|
if (str != optlist)
|
||||||
|
memmove(optlist, str, strlen(str) + 1);
|
||||||
|
/* Caller should free() or exit() */
|
||||||
|
*invalid = optlist;
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(optlist);
|
||||||
|
return (rval);
|
||||||
|
}
|
107
lib/libutil/login.3
Normal file
107
lib/libutil/login.3
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
.\" $NetBSD: login.3,v 1.6 2003/08/07 16:44:58 agc Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1995
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software developed by the Computer Systems
|
||||||
|
.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract
|
||||||
|
.\" BG 91-66 and contributed to Berkeley.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd December 14, 1995
|
||||||
|
.Dt LOGIN 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm login ,
|
||||||
|
.Nm logout ,
|
||||||
|
.Nm logwtmp
|
||||||
|
.Nd login utility functions
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft void
|
||||||
|
.Fn login "struct utmp *ut"
|
||||||
|
.Ft int
|
||||||
|
.Fn logout "const char *line"
|
||||||
|
.Ft void
|
||||||
|
.Fn logwtmp "const char *line" "const char *name" "const char *host"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn login ,
|
||||||
|
.Fn logout ,
|
||||||
|
and
|
||||||
|
.Fn logwtmp
|
||||||
|
functions operate on the database of current users in
|
||||||
|
.Pa /var/run/utmp
|
||||||
|
and on the logfile
|
||||||
|
.Pa /var/log/wtmp
|
||||||
|
of logins and logouts.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn login
|
||||||
|
function updates the
|
||||||
|
.Pa /var/run/utmp
|
||||||
|
and
|
||||||
|
.Pa /var/log/wtmp
|
||||||
|
files with user information contained in
|
||||||
|
.Fa ut .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn logout
|
||||||
|
function removes the entry from
|
||||||
|
.Pa /var/run/utmp
|
||||||
|
corresponding to the device
|
||||||
|
.Fa line .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn logwtmp
|
||||||
|
function adds an entry to
|
||||||
|
.Pa /var/log/wtmp .
|
||||||
|
Since
|
||||||
|
.Fn login
|
||||||
|
will add the appropriate entry for
|
||||||
|
.Pa /var/log/wtmp
|
||||||
|
during a login,
|
||||||
|
.Fn logwtmp
|
||||||
|
is usually used for logouts.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn logout
|
||||||
|
returns non-zero if it was able to find and delete an entry for
|
||||||
|
.Fa line ,
|
||||||
|
and zero if there is no entry for
|
||||||
|
.Fa line
|
||||||
|
in
|
||||||
|
.Pa /var/run/utmp .
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /var/run/wtmp -compact
|
||||||
|
.It Pa /dev/\(**
|
||||||
|
.It Pa /etc/ttys
|
||||||
|
.It Pa /var/run/utmp
|
||||||
|
.It Pa /var/log/wtmp
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr utmp 5
|
70
lib/libutil/login.c
Normal file
70
lib/libutil/login.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/* $NetBSD: login.c,v 1.16 2003/08/07 16:44:58 agc Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)login.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: login.c,v 1.16 2003/08/07 16:44:58 agc Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
login(const struct utmp *ut)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int tty;
|
||||||
|
|
||||||
|
_DIAGASSERT(ut != NULL);
|
||||||
|
|
||||||
|
tty = ttyslot();
|
||||||
|
if (tty > 0 && (fd = open(_PATH_UTMP, O_WRONLY|O_CREAT, 0644)) >= 0) {
|
||||||
|
(void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
|
||||||
|
(void)write(fd, ut, sizeof(struct utmp));
|
||||||
|
(void)close(fd);
|
||||||
|
}
|
||||||
|
if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) {
|
||||||
|
(void)write(fd, ut, sizeof(struct utmp));
|
||||||
|
(void)close(fd);
|
||||||
|
}
|
||||||
|
}
|
289
lib/libutil/login_cap.3
Normal file
289
lib/libutil/login_cap.3
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
.\" $NetBSD: login_cap.3,v 1.18 2010/05/05 22:05:31 wiz Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1996,1997 Berkeley Software Design, Inc. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\" This product includes software developed by Berkeley Software Design,
|
||||||
|
.\" Inc.
|
||||||
|
.\" 4. The name of Berkeley Software Design, Inc. may not be used to endorse
|
||||||
|
.\" or promote products derived from this software without specific prior
|
||||||
|
.\" written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" BSDI login_cap.3,v 1.4 1997/11/07 16:22:27 jch Exp
|
||||||
|
.\"
|
||||||
|
.Dd October 6, 2007
|
||||||
|
.Dt LOGIN_CAP 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm login_getclass ,
|
||||||
|
.Nm login_getcapbool ,
|
||||||
|
.Nm login_getcapnum ,
|
||||||
|
.Nm login_getcapsize ,
|
||||||
|
.Nm login_getcapstr ,
|
||||||
|
.Nm login_getcaptime ,
|
||||||
|
.Nm login_close ,
|
||||||
|
.Nm setclasscontext ,
|
||||||
|
.Nm setusercontext
|
||||||
|
.Nd query login.conf database about a user class
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/types.h
|
||||||
|
.In login_cap.h
|
||||||
|
.Ft login_cap_t *
|
||||||
|
.Fn login_getclass "char *class"
|
||||||
|
.Ft int
|
||||||
|
.Fn login_getcapbool "login_cap_t *lc" "const char *cap" "u_int def"
|
||||||
|
.Ft quad_t
|
||||||
|
.Fn login_getcapnum "login_cap_t *lc" "const char *cap" "quad_t def" "quad_t err"
|
||||||
|
.Ft quad_t
|
||||||
|
.Fn login_getcapsize "login_cap_t *lc" "const char *cap" "quad_t def" "quad_t err"
|
||||||
|
.Ft char *
|
||||||
|
.Fn login_getcapstr "login_cap_t *lc" "const char *cap" "char *def" "char *err"
|
||||||
|
.Ft quad_t
|
||||||
|
.Fn login_getcaptime "login_cap_t *lc" "const char *cap" "quad_t def" "quad_t err"
|
||||||
|
.Ft void
|
||||||
|
.Fn login_close "login_cap_t *lc"
|
||||||
|
.Ft int
|
||||||
|
.Fn setclasscontext "const char *class" "u_int flags"
|
||||||
|
.Ft int
|
||||||
|
.Fn setusercontext "login_cap_t *lc" "const struct passwd *pwd" "uid_t uid" "u_int flags"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn login_getclass
|
||||||
|
function extracts the entry specified by
|
||||||
|
.Ar class
|
||||||
|
(or
|
||||||
|
.Li default
|
||||||
|
if
|
||||||
|
.Ar class
|
||||||
|
is
|
||||||
|
.Dv NULL
|
||||||
|
or the empty string)
|
||||||
|
from
|
||||||
|
.Pa /etc/login.conf
|
||||||
|
(see
|
||||||
|
.Xr login.conf 5 ) .
|
||||||
|
If the entry is found, a
|
||||||
|
.Li login_cap_t
|
||||||
|
pointer is returned.
|
||||||
|
.Dv NULL
|
||||||
|
is returned if the user class is not found.
|
||||||
|
When the
|
||||||
|
.Li login_cap_t
|
||||||
|
structure is no longer needed, it should be freed by the
|
||||||
|
.Fn login_close
|
||||||
|
function.
|
||||||
|
.Pp
|
||||||
|
Once
|
||||||
|
.Ar lc
|
||||||
|
has been returned by
|
||||||
|
.Fn login_getclass ,
|
||||||
|
any of the other
|
||||||
|
.Fn login_*
|
||||||
|
functions may be called.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn login_getcapnum ,
|
||||||
|
.Fn login_getcapsize ,
|
||||||
|
.Fn login_getcapstr ,
|
||||||
|
and
|
||||||
|
.Fn login_getcaptime
|
||||||
|
functions all query the database entry for a field named
|
||||||
|
.Ar cap .
|
||||||
|
If the field is found, its value is returned.
|
||||||
|
If the field is not found, the value specified by
|
||||||
|
.Ar def
|
||||||
|
is returned.
|
||||||
|
If an error is encountered while trying to find the field,
|
||||||
|
.Ar err
|
||||||
|
is returned.
|
||||||
|
See
|
||||||
|
.Xr login.conf 5
|
||||||
|
for a discussion of the various textual forms the value may take.
|
||||||
|
The
|
||||||
|
.Fn login_getcapbool
|
||||||
|
function is slightly different.
|
||||||
|
It returns
|
||||||
|
.Ar def
|
||||||
|
if no capabilities were found for this class (typically meaning that
|
||||||
|
the default class was used and the
|
||||||
|
.Li /etc/login.conf
|
||||||
|
file is missing).
|
||||||
|
It returns a non-zero value if
|
||||||
|
.Ar cap ,
|
||||||
|
with no value, was found,
|
||||||
|
zero otherwise.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn setclasscontext
|
||||||
|
function takes
|
||||||
|
.Ar class ,
|
||||||
|
the name of a user class,
|
||||||
|
and sets the resources defined by that class according to
|
||||||
|
.Ar flags .
|
||||||
|
Only the
|
||||||
|
.Dv LOGIN_SETPATH ,
|
||||||
|
.Dv LOGIN_SETPRIORITY ,
|
||||||
|
.Dv LOGIN_SETRESOURCES ,
|
||||||
|
and
|
||||||
|
.Dv LOGIN_SETUMASK
|
||||||
|
bits are used.
|
||||||
|
(See
|
||||||
|
.Fn setusercontext
|
||||||
|
below).
|
||||||
|
It returns 0 on success and -1 on failure.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn setusercontext
|
||||||
|
function
|
||||||
|
sets the resources according to
|
||||||
|
.Ar flags .
|
||||||
|
The
|
||||||
|
.Ar lc
|
||||||
|
argument, if not
|
||||||
|
.Dv NULL ,
|
||||||
|
contains the class information that should
|
||||||
|
be used.
|
||||||
|
The
|
||||||
|
.Ar pwd
|
||||||
|
argument, if not
|
||||||
|
.Dv NULL ,
|
||||||
|
provides information about the user.
|
||||||
|
Both
|
||||||
|
.Ar lc
|
||||||
|
and
|
||||||
|
.Ar pwd
|
||||||
|
cannot be
|
||||||
|
.Dv NULL .
|
||||||
|
The
|
||||||
|
.Ar uid
|
||||||
|
argument is used in place of the user id contained in the
|
||||||
|
.Ar pwd
|
||||||
|
structure when calling
|
||||||
|
.Xr setuid 2 .
|
||||||
|
The various bits available to be or-ed together to make up
|
||||||
|
.Ar flags
|
||||||
|
are:
|
||||||
|
.Bl -tag -width LOGIN_SETRESOURCESXX
|
||||||
|
.It LOGIN_SETGID
|
||||||
|
Set the group id.
|
||||||
|
Requires the
|
||||||
|
.Ar pwd
|
||||||
|
field be specified.
|
||||||
|
.It LOGIN_SETGROUPS
|
||||||
|
Set the group membership list by calling
|
||||||
|
.Xr initgroups 3 .
|
||||||
|
Requires the
|
||||||
|
.Ar pwd
|
||||||
|
field be specified.
|
||||||
|
.It LOGIN_SETGROUP
|
||||||
|
Set the group id and call
|
||||||
|
.Xr initgroups 3 .
|
||||||
|
Requires the
|
||||||
|
.Ar pwd
|
||||||
|
field be specified.
|
||||||
|
.It LOGIN_SETLOGIN
|
||||||
|
Sets the login name by
|
||||||
|
.Xr setlogin 2 .
|
||||||
|
Requires the
|
||||||
|
.Ar pwd
|
||||||
|
field be specified.
|
||||||
|
.It LOGIN_SETPATH
|
||||||
|
Sets the
|
||||||
|
.Ev PATH
|
||||||
|
environment variable.
|
||||||
|
.It LOGIN_SETPRIORITY
|
||||||
|
Sets the priority by
|
||||||
|
.Xr setpriority 2 .
|
||||||
|
.It LOGIN_SETRESOURCES
|
||||||
|
Sets the various system resources by
|
||||||
|
.Xr setrlimit 2 .
|
||||||
|
.It LOGIN_SETUMASK
|
||||||
|
Sets the umask by
|
||||||
|
.Xr umask 2 .
|
||||||
|
.It LOGIN_SETUSER
|
||||||
|
Sets the user id to
|
||||||
|
.Ar uid
|
||||||
|
by
|
||||||
|
.Xr setuid 2 .
|
||||||
|
.It LOGIN_SETENV
|
||||||
|
Sets the environment variables as defined by the setenv keyword, by
|
||||||
|
.Xr setenv 3 .
|
||||||
|
.It LOGIN_SETALL
|
||||||
|
Sets all of the above.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr setlogin 2 ,
|
||||||
|
.Xr setpriority 2 ,
|
||||||
|
.Xr setrlimit 2 ,
|
||||||
|
.Xr setuid 2 ,
|
||||||
|
.Xr umask 2 ,
|
||||||
|
.Xr initgroups 3 ,
|
||||||
|
.Xr secure_path 3 ,
|
||||||
|
.Xr login.conf 5
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
family of functions are largely based on the
|
||||||
|
.Bsx
|
||||||
|
implementation of same, and appeared in
|
||||||
|
.Nx 1.5
|
||||||
|
by kind permission.
|
||||||
|
.Sh CAVEATS
|
||||||
|
The string returned by
|
||||||
|
.Fn login_getcapstr
|
||||||
|
is allocated via
|
||||||
|
.Xr malloc 3
|
||||||
|
when the specified capability is present and thus it is the responsibility
|
||||||
|
of the caller to
|
||||||
|
.Fn free
|
||||||
|
this space.
|
||||||
|
However, if the capability was not found or an error occurred and
|
||||||
|
.Fa def
|
||||||
|
or
|
||||||
|
.Fa err
|
||||||
|
(whichever is relevant) are
|
||||||
|
.Pf non- Dv NULL
|
||||||
|
the returned value is simply what was passed in to
|
||||||
|
.Fn login_getcapstr .
|
||||||
|
Therefore it is not possible to blindly
|
||||||
|
.Fn free
|
||||||
|
the return value without first checking it against
|
||||||
|
.Fa def
|
||||||
|
and
|
||||||
|
.Fa err .
|
||||||
|
.Pp
|
||||||
|
The same warnings set forth in
|
||||||
|
.Xr setlogin 2
|
||||||
|
apply to
|
||||||
|
.Fn setusercontext
|
||||||
|
when the
|
||||||
|
.Dv LOGIN_SETLOGIN
|
||||||
|
flag is used.
|
||||||
|
Specifically, changing the login name affects all processes in the current
|
||||||
|
session, not just the current process.
|
||||||
|
See
|
||||||
|
.Xr setlogin 2
|
||||||
|
for more information.
|
987
lib/libutil/login_cap.c
Normal file
987
lib/libutil/login_cap.c
Normal file
|
@ -0,0 +1,987 @@
|
||||||
|
/* $NetBSD: login_cap.c,v 1.29 2007/12/04 22:09:02 mjf Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1995,1997 Berkeley Software Design, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Berkeley Software Design,
|
||||||
|
* Inc.
|
||||||
|
* 4. The name of Berkeley Software Design, Inc. may not be used to endorse
|
||||||
|
* or promote products derived from this software without specific prior
|
||||||
|
* written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* BSDI login_cap.c,v 2.13 1998/02/07 03:17:05 prb Exp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: login_cap.c,v 1.29 2007/12/04 22:09:02 mjf Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <login_cap.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
static u_quad_t multiply(u_quad_t, u_quad_t);
|
||||||
|
static u_quad_t strtolimit(const char *, char **, int);
|
||||||
|
static u_quad_t strtosize(const char *, char **, int);
|
||||||
|
static int gsetrl(login_cap_t *, int, const char *, int type);
|
||||||
|
static int isinfinite(const char *);
|
||||||
|
static int envset(void *, const char *, const char *, int);
|
||||||
|
|
||||||
|
login_cap_t *
|
||||||
|
login_getclass(const char *class)
|
||||||
|
{
|
||||||
|
const char *classfiles[2];
|
||||||
|
login_cap_t *lc;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* class may be NULL */
|
||||||
|
|
||||||
|
if (secure_path(_PATH_LOGIN_CONF) == 0) {
|
||||||
|
classfiles[0] = _PATH_LOGIN_CONF;
|
||||||
|
classfiles[1] = NULL;
|
||||||
|
} else {
|
||||||
|
classfiles[0] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lc = malloc(sizeof(login_cap_t))) == NULL) {
|
||||||
|
syslog(LOG_ERR, "%s:%d malloc: %m", __FILE__, __LINE__);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lc->lc_cap = 0;
|
||||||
|
lc->lc_style = 0;
|
||||||
|
|
||||||
|
if (class == NULL || class[0] == '\0')
|
||||||
|
class = LOGIN_DEFCLASS;
|
||||||
|
|
||||||
|
if ((lc->lc_class = strdup(class)) == NULL) {
|
||||||
|
syslog(LOG_ERR, "%s:%d strdup: %m", __FILE__, __LINE__);
|
||||||
|
free(lc);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not having a login.conf file is not an error condition.
|
||||||
|
* The individual routines deal reasonably with missing
|
||||||
|
* capabilities and use default values.
|
||||||
|
*/
|
||||||
|
if (classfiles[0] == NULL)
|
||||||
|
return(lc);
|
||||||
|
|
||||||
|
if ((res = cgetent(&lc->lc_cap, classfiles, lc->lc_class)) != 0) {
|
||||||
|
lc->lc_cap = 0;
|
||||||
|
switch (res) {
|
||||||
|
case 1:
|
||||||
|
syslog(LOG_ERR, "%s: couldn't resolve 'tc'",
|
||||||
|
lc->lc_class);
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
if (strcmp(lc->lc_class, LOGIN_DEFCLASS) == 0)
|
||||||
|
return (lc);
|
||||||
|
syslog(LOG_ERR, "%s: unknown class", lc->lc_class);
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
syslog(LOG_ERR, "%s: getting class information: %m",
|
||||||
|
lc->lc_class);
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
syslog(LOG_ERR, "%s: 'tc' reference loop",
|
||||||
|
lc->lc_class);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
syslog(LOG_ERR, "%s: unexpected cgetent error",
|
||||||
|
lc->lc_class);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(lc->lc_class);
|
||||||
|
free(lc);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (lc);
|
||||||
|
}
|
||||||
|
|
||||||
|
login_cap_t *
|
||||||
|
login_getpwclass(const struct passwd *pwd)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* pwd may be NULL */
|
||||||
|
|
||||||
|
return login_getclass(pwd ? pwd->pw_class : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *e)
|
||||||
|
{
|
||||||
|
char *res = NULL;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
_DIAGASSERT(cap != NULL);
|
||||||
|
|
||||||
|
if (!lc || !lc->lc_cap)
|
||||||
|
return (def);
|
||||||
|
|
||||||
|
switch (status = cgetstr(lc->lc_cap, cap, &res)) {
|
||||||
|
case -1:
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (def);
|
||||||
|
case -2:
|
||||||
|
syslog(LOG_ERR, "%s: getting capability %s: %m",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
default:
|
||||||
|
if (status >= 0)
|
||||||
|
return (res);
|
||||||
|
syslog(LOG_ERR, "%s: unexpected error with capability %s",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quad_t
|
||||||
|
login_getcaptime(login_cap_t *lc, const char *cap, quad_t def, quad_t e)
|
||||||
|
{
|
||||||
|
char *ep;
|
||||||
|
char *res = NULL, *sres;
|
||||||
|
int status;
|
||||||
|
quad_t q, r;
|
||||||
|
|
||||||
|
_DIAGASSERT(cap != NULL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (!lc || !lc->lc_cap)
|
||||||
|
return (def);
|
||||||
|
|
||||||
|
switch (status = cgetstr(lc->lc_cap, cap, &res)) {
|
||||||
|
case -1:
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (def);
|
||||||
|
case -2:
|
||||||
|
syslog(LOG_ERR, "%s: getting capability %s: %m",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
errno = ERANGE;
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
default:
|
||||||
|
if (status >= 0)
|
||||||
|
break;
|
||||||
|
syslog(LOG_ERR, "%s: unexpected error with capability %s",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
errno = ERANGE;
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isinfinite(res))
|
||||||
|
return (RLIM_INFINITY);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
q = 0;
|
||||||
|
sres = res;
|
||||||
|
while (*res) {
|
||||||
|
r = strtoq(res, &ep, 0);
|
||||||
|
if (!ep || ep == res ||
|
||||||
|
((r == QUAD_MIN || r == QUAD_MAX) && errno == ERANGE)) {
|
||||||
|
invalid:
|
||||||
|
syslog(LOG_ERR, "%s:%s=%s: invalid time",
|
||||||
|
lc->lc_class, cap, sres);
|
||||||
|
errno = ERANGE;
|
||||||
|
free(sres);
|
||||||
|
return (e);
|
||||||
|
}
|
||||||
|
switch (*ep++) {
|
||||||
|
case '\0':
|
||||||
|
--ep;
|
||||||
|
break;
|
||||||
|
case 's': case 'S':
|
||||||
|
break;
|
||||||
|
case 'm': case 'M':
|
||||||
|
r *= 60;
|
||||||
|
break;
|
||||||
|
case 'h': case 'H':
|
||||||
|
r *= 60 * 60;
|
||||||
|
break;
|
||||||
|
case 'd': case 'D':
|
||||||
|
r *= 60 * 60 * 24;
|
||||||
|
break;
|
||||||
|
case 'w': case 'W':
|
||||||
|
r *= 60 * 60 * 24 * 7;
|
||||||
|
break;
|
||||||
|
case 'y': case 'Y': /* Pretty absurd */
|
||||||
|
r *= 60 * 60 * 24 * 365;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
res = ep;
|
||||||
|
q += r;
|
||||||
|
}
|
||||||
|
free(sres);
|
||||||
|
return (q);
|
||||||
|
}
|
||||||
|
|
||||||
|
quad_t
|
||||||
|
login_getcapnum(login_cap_t *lc, const char *cap, quad_t def, quad_t e)
|
||||||
|
{
|
||||||
|
char *ep;
|
||||||
|
char *res = NULL;
|
||||||
|
int status;
|
||||||
|
quad_t q;
|
||||||
|
|
||||||
|
_DIAGASSERT(cap != NULL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (!lc || !lc->lc_cap)
|
||||||
|
return (def);
|
||||||
|
|
||||||
|
switch (status = cgetstr(lc->lc_cap, cap, &res)) {
|
||||||
|
case -1:
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (def);
|
||||||
|
case -2:
|
||||||
|
syslog(LOG_ERR, "%s: getting capability %s: %m",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
errno = ERANGE;
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
default:
|
||||||
|
if (status >= 0)
|
||||||
|
break;
|
||||||
|
syslog(LOG_ERR, "%s: unexpected error with capability %s",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
errno = ERANGE;
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isinfinite(res))
|
||||||
|
return (RLIM_INFINITY);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
q = strtoq(res, &ep, 0);
|
||||||
|
if (!ep || ep == res || ep[0] ||
|
||||||
|
((q == QUAD_MIN || q == QUAD_MAX) && errno == ERANGE)) {
|
||||||
|
syslog(LOG_ERR, "%s:%s=%s: invalid number",
|
||||||
|
lc->lc_class, cap, res);
|
||||||
|
errno = ERANGE;
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
}
|
||||||
|
free(res);
|
||||||
|
return (q);
|
||||||
|
}
|
||||||
|
|
||||||
|
quad_t
|
||||||
|
login_getcapsize(login_cap_t *lc, const char *cap, quad_t def, quad_t e)
|
||||||
|
{
|
||||||
|
char *ep;
|
||||||
|
char *res = NULL;
|
||||||
|
int status;
|
||||||
|
quad_t q;
|
||||||
|
|
||||||
|
_DIAGASSERT(cap != NULL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
if (!lc || !lc->lc_cap)
|
||||||
|
return (def);
|
||||||
|
|
||||||
|
switch (status = cgetstr(lc->lc_cap, cap, &res)) {
|
||||||
|
case -1:
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (def);
|
||||||
|
case -2:
|
||||||
|
syslog(LOG_ERR, "%s: getting capability %s: %m",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
errno = ERANGE;
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
default:
|
||||||
|
if (status >= 0)
|
||||||
|
break;
|
||||||
|
syslog(LOG_ERR, "%s: unexpected error with capability %s",
|
||||||
|
lc->lc_class, cap);
|
||||||
|
errno = ERANGE;
|
||||||
|
if (res)
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
q = strtolimit(res, &ep, 0);
|
||||||
|
if (!ep || ep == res || (ep[0] && ep[1]) ||
|
||||||
|
((q == QUAD_MIN || q == QUAD_MAX) && errno == ERANGE)) {
|
||||||
|
syslog(LOG_ERR, "%s:%s=%s: invalid size",
|
||||||
|
lc->lc_class, cap, res);
|
||||||
|
errno = ERANGE;
|
||||||
|
free(res);
|
||||||
|
return (e);
|
||||||
|
}
|
||||||
|
free(res);
|
||||||
|
return (q);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
login_getcapbool(login_cap_t *lc, const char *cap, u_int def)
|
||||||
|
{
|
||||||
|
|
||||||
|
_DIAGASSERT(cap != NULL);
|
||||||
|
|
||||||
|
if (!lc || !lc->lc_cap)
|
||||||
|
return (def);
|
||||||
|
|
||||||
|
return (cgetcap(lc->lc_cap, cap, ':') != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
login_close(login_cap_t *lc)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (lc) {
|
||||||
|
if (lc->lc_class)
|
||||||
|
free(lc->lc_class);
|
||||||
|
if (lc->lc_cap)
|
||||||
|
free(lc->lc_cap);
|
||||||
|
if (lc->lc_style)
|
||||||
|
free(lc->lc_style);
|
||||||
|
free(lc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define R_CTIME 1
|
||||||
|
#define R_CSIZE 2
|
||||||
|
#define R_CNUMB 3
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int what;
|
||||||
|
int type;
|
||||||
|
const char *name;
|
||||||
|
} r_list[] = {
|
||||||
|
{ RLIMIT_CPU, R_CTIME, "cputime", },
|
||||||
|
{ RLIMIT_FSIZE, R_CSIZE, "filesize", },
|
||||||
|
{ RLIMIT_DATA, R_CSIZE, "datasize", },
|
||||||
|
{ RLIMIT_STACK, R_CSIZE, "stacksize", },
|
||||||
|
{ RLIMIT_RSS, R_CSIZE, "memoryuse", },
|
||||||
|
{ RLIMIT_MEMLOCK, R_CSIZE, "memorylocked", },
|
||||||
|
{ RLIMIT_NPROC, R_CNUMB, "maxproc", },
|
||||||
|
{ RLIMIT_NOFILE, R_CNUMB, "openfiles", },
|
||||||
|
{ RLIMIT_CORE, R_CSIZE, "coredumpsize", },
|
||||||
|
{ RLIMIT_SBSIZE, R_CSIZE, "sbsize", },
|
||||||
|
{ -1, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
gsetrl(login_cap_t *lc, int what, const char *name, int type)
|
||||||
|
{
|
||||||
|
struct rlimit rl;
|
||||||
|
struct rlimit r;
|
||||||
|
char name_cur[32];
|
||||||
|
char name_max[32];
|
||||||
|
|
||||||
|
_DIAGASSERT(name != NULL);
|
||||||
|
|
||||||
|
(void)snprintf(name_cur, sizeof(name_cur), "%s-cur", name);
|
||||||
|
(void)snprintf(name_max, sizeof(name_max), "%s-max", name);
|
||||||
|
|
||||||
|
if (getrlimit(what, &r)) {
|
||||||
|
syslog(LOG_ERR, "getting resource limit: %m");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RCUR r.rlim_cur
|
||||||
|
#define RMAX r.rlim_max
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case R_CTIME:
|
||||||
|
RCUR = login_getcaptime(lc, name, RCUR, RCUR);
|
||||||
|
RMAX = login_getcaptime(lc, name, RMAX, RMAX);
|
||||||
|
rl.rlim_cur = login_getcaptime(lc, name_cur, RCUR, RCUR);
|
||||||
|
rl.rlim_max = login_getcaptime(lc, name_max, RMAX, RMAX);
|
||||||
|
break;
|
||||||
|
case R_CSIZE:
|
||||||
|
RCUR = login_getcapsize(lc, name, RCUR, RCUR);
|
||||||
|
RMAX = login_getcapsize(lc, name, RMAX, RMAX);
|
||||||
|
rl.rlim_cur = login_getcapsize(lc, name_cur, RCUR, RCUR);
|
||||||
|
rl.rlim_max = login_getcapsize(lc, name_max, RMAX, RMAX);
|
||||||
|
break;
|
||||||
|
case R_CNUMB:
|
||||||
|
RCUR = login_getcapnum(lc, name, RCUR, RCUR);
|
||||||
|
RMAX = login_getcapnum(lc, name, RMAX, RMAX);
|
||||||
|
rl.rlim_cur = login_getcapnum(lc, name_cur, RCUR, RCUR);
|
||||||
|
rl.rlim_max = login_getcapnum(lc, name_max, RMAX, RMAX);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
syslog(LOG_ERR, "%s: invalid type %d setting resource limit %s",
|
||||||
|
lc->lc_class, type, name);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setrlimit(what, &rl)) {
|
||||||
|
syslog(LOG_ERR, "%s: setting resource limit %s: %m",
|
||||||
|
lc->lc_class, name);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
#undef RCUR
|
||||||
|
#undef RMAX
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
/*ARGSUSED*/
|
||||||
|
envset(void *envp __unused, const char *name, const char *value, int overwrite)
|
||||||
|
{
|
||||||
|
return setenv(name, value, overwrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
setuserenv(login_cap_t *lc, envfunc_t senv, void *envp)
|
||||||
|
{
|
||||||
|
const char *stop = ", \t";
|
||||||
|
size_t i, count;
|
||||||
|
char *ptr;
|
||||||
|
char **res;
|
||||||
|
char *str = login_getcapstr(lc, "setenv", NULL, NULL);
|
||||||
|
|
||||||
|
if (str == NULL || *str == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* count the sub-strings, this may over-count since we don't
|
||||||
|
* account for escaped delimiters.
|
||||||
|
*/
|
||||||
|
for (i = 1, ptr = str; *ptr; i++) {
|
||||||
|
ptr += strcspn(ptr, stop);
|
||||||
|
if (*ptr)
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate ptr array and string */
|
||||||
|
count = i;
|
||||||
|
res = malloc(count * sizeof(char *) + strlen(str) + 1);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ptr = (char *)(void *)&res[count];
|
||||||
|
(void)strcpy(ptr, str);
|
||||||
|
|
||||||
|
/* split string */
|
||||||
|
for (i = 0; (res[i] = stresep(&ptr, stop, '\\')) != NULL; )
|
||||||
|
if (*res[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
count = i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if ((ptr = strchr(res[i], '=')) != NULL)
|
||||||
|
*ptr++ = '\0';
|
||||||
|
else
|
||||||
|
ptr = NULL;
|
||||||
|
(void)(*senv)(envp, res[i], ptr ? ptr : "", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(res);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
setclasscontext(const char *class, u_int flags)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
login_cap_t *lc;
|
||||||
|
|
||||||
|
flags &= LOGIN_SETRESOURCES | LOGIN_SETPRIORITY | LOGIN_SETUMASK |
|
||||||
|
LOGIN_SETPATH;
|
||||||
|
|
||||||
|
lc = login_getclass(class);
|
||||||
|
ret = lc ? setusercontext(lc, NULL, 0, flags) : -1;
|
||||||
|
login_close(lc);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, u_int flags)
|
||||||
|
{
|
||||||
|
char per_user_tmp[MAXPATHLEN + 1];
|
||||||
|
const char *component_name;
|
||||||
|
login_cap_t *flc;
|
||||||
|
quad_t p;
|
||||||
|
int i;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
flc = NULL;
|
||||||
|
|
||||||
|
if (!lc)
|
||||||
|
flc = lc = login_getclass(pwd ? pwd->pw_class : NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Without the pwd entry being passed we cannot set either
|
||||||
|
* the group or the login. We could complain about it.
|
||||||
|
*/
|
||||||
|
if (pwd == NULL)
|
||||||
|
flags &= ~(LOGIN_SETGROUP|LOGIN_SETLOGIN);
|
||||||
|
|
||||||
|
#ifdef LOGIN_OSETGROUP
|
||||||
|
if (pwd == NULL)
|
||||||
|
flags &= ~LOGIN_OSETGROUP;
|
||||||
|
if (flags & LOGIN_OSETGROUP)
|
||||||
|
flags = (flags & ~LOGIN_OSETGROUP) | LOGIN_SETGROUP;
|
||||||
|
#endif
|
||||||
|
if (flags & LOGIN_SETRESOURCES)
|
||||||
|
for (i = 0; r_list[i].name; ++i)
|
||||||
|
(void)gsetrl(lc, r_list[i].what, r_list[i].name,
|
||||||
|
r_list[i].type);
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETPRIORITY) {
|
||||||
|
p = login_getcapnum(lc, "priority", (quad_t)0, (quad_t)0);
|
||||||
|
|
||||||
|
if (setpriority(PRIO_PROCESS, 0, (int)p) == -1)
|
||||||
|
syslog(LOG_ERR, "%s: setpriority: %m", lc->lc_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETUMASK) {
|
||||||
|
p = login_getcapnum(lc, "umask", (quad_t) LOGIN_DEFUMASK,
|
||||||
|
(quad_t)LOGIN_DEFUMASK);
|
||||||
|
umask((mode_t)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETGID) {
|
||||||
|
if (setgid(pwd->pw_gid) == -1) {
|
||||||
|
syslog(LOG_ERR, "setgid(%d): %m", pwd->pw_gid);
|
||||||
|
login_close(flc);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETGROUPS) {
|
||||||
|
if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
|
||||||
|
syslog(LOG_ERR, "initgroups(%s,%d): %m",
|
||||||
|
pwd->pw_name, pwd->pw_gid);
|
||||||
|
login_close(flc);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create per-user temporary directories if needed. */
|
||||||
|
if ((len = readlink("/tmp", per_user_tmp,
|
||||||
|
sizeof(per_user_tmp) - 6)) != -1) {
|
||||||
|
|
||||||
|
static const char atuid[] = "/@ruid";
|
||||||
|
char *lp;
|
||||||
|
|
||||||
|
/* readlink does not nul-terminate the string */
|
||||||
|
per_user_tmp[len] = '\0';
|
||||||
|
|
||||||
|
/* Check if it's magic symlink. */
|
||||||
|
lp = strstr(per_user_tmp, atuid);
|
||||||
|
if (lp != NULL && *(lp + (sizeof(atuid) - 1)) == '\0') {
|
||||||
|
lp++;
|
||||||
|
|
||||||
|
if (snprintf(lp, 11, "/%u", pwd->pw_uid) > 10) {
|
||||||
|
syslog(LOG_ERR, "real temporary path too long");
|
||||||
|
login_close(flc);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (mkdir(per_user_tmp, S_IRWXU) != -1) {
|
||||||
|
if (chown(per_user_tmp, pwd->pw_uid,
|
||||||
|
pwd->pw_gid)) {
|
||||||
|
component_name = "chown";
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must set sticky bit for tmp directory, some
|
||||||
|
* programs rely on this.
|
||||||
|
*/
|
||||||
|
if(chmod(per_user_tmp, S_IRWXU | S_ISVTX)) {
|
||||||
|
component_name = "chmod";
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (errno != EEXIST) {
|
||||||
|
component_name = "mkdir";
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* We must ensure that we own the
|
||||||
|
* directory and that is has the correct
|
||||||
|
* permissions, otherwise a DOS attack
|
||||||
|
* is possible.
|
||||||
|
*/
|
||||||
|
struct stat sb;
|
||||||
|
if (stat(per_user_tmp, &sb) == -1) {
|
||||||
|
component_name = "stat";
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.st_uid != pwd->pw_uid) {
|
||||||
|
if (chown(per_user_tmp,
|
||||||
|
pwd->pw_uid, pwd->pw_gid)) {
|
||||||
|
component_name = "chown";
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.st_mode != (S_IRWXU | S_ISVTX)) {
|
||||||
|
if (chmod(per_user_tmp,
|
||||||
|
S_IRWXU | S_ISVTX)) {
|
||||||
|
component_name = "chmod";
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETLOGIN)
|
||||||
|
if (setlogin(pwd->pw_name) == -1) {
|
||||||
|
syslog(LOG_ERR, "setlogin(%s) failure: %m",
|
||||||
|
pwd->pw_name);
|
||||||
|
login_close(flc);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETUSER)
|
||||||
|
if (setuid(uid) == -1) {
|
||||||
|
syslog(LOG_ERR, "setuid(%d): %m", uid);
|
||||||
|
login_close(flc);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETENV)
|
||||||
|
setuserenv(lc, envset, NULL);
|
||||||
|
|
||||||
|
if (flags & LOGIN_SETPATH)
|
||||||
|
setuserpath(lc, pwd ? pwd->pw_dir : "", envset, NULL);
|
||||||
|
|
||||||
|
login_close(flc);
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (component_name != NULL) {
|
||||||
|
syslog(LOG_ERR, "%s %s: %m", component_name, per_user_tmp);
|
||||||
|
login_close(flc);
|
||||||
|
return (-1);
|
||||||
|
} else {
|
||||||
|
syslog(LOG_ERR, "%s: %m", per_user_tmp);
|
||||||
|
login_close(flc);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setuserpath(login_cap_t *lc, const char *home, envfunc_t senv, void *envp)
|
||||||
|
{
|
||||||
|
size_t hlen, plen;
|
||||||
|
int cnt = 0;
|
||||||
|
char *path;
|
||||||
|
const char *cpath;
|
||||||
|
char *p, *q;
|
||||||
|
|
||||||
|
_DIAGASSERT(home != NULL);
|
||||||
|
|
||||||
|
hlen = strlen(home);
|
||||||
|
|
||||||
|
p = path = login_getcapstr(lc, "path", NULL, NULL);
|
||||||
|
if (p) {
|
||||||
|
while (*p)
|
||||||
|
if (*p++ == '~')
|
||||||
|
++cnt;
|
||||||
|
plen = (p - path) + cnt * (hlen + 1) + 1;
|
||||||
|
p = path;
|
||||||
|
q = path = malloc(plen);
|
||||||
|
if (q) {
|
||||||
|
while (*p) {
|
||||||
|
p += strspn(p, " \t");
|
||||||
|
if (*p == '\0')
|
||||||
|
break;
|
||||||
|
plen = strcspn(p, " \t");
|
||||||
|
if (hlen == 0 && *p == '~') {
|
||||||
|
p += plen;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (q != path)
|
||||||
|
*q++ = ':';
|
||||||
|
if (*p == '~') {
|
||||||
|
strcpy(q, home);
|
||||||
|
q += hlen;
|
||||||
|
++p;
|
||||||
|
--plen;
|
||||||
|
}
|
||||||
|
memcpy(q, p, plen);
|
||||||
|
p += plen;
|
||||||
|
q += plen;
|
||||||
|
}
|
||||||
|
*q = '\0';
|
||||||
|
cpath = path;
|
||||||
|
} else
|
||||||
|
cpath = _PATH_DEFPATH;
|
||||||
|
} else
|
||||||
|
cpath = _PATH_DEFPATH;
|
||||||
|
if ((*senv)(envp, "PATH", cpath, 1))
|
||||||
|
warn("could not set PATH");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert an expression of the following forms
|
||||||
|
* 1) A number.
|
||||||
|
* 2) A number followed by a b (mult by 512).
|
||||||
|
* 3) A number followed by a k (mult by 1024).
|
||||||
|
* 5) A number followed by a m (mult by 1024 * 1024).
|
||||||
|
* 6) A number followed by a g (mult by 1024 * 1024 * 1024).
|
||||||
|
* 7) A number followed by a t (mult by 1024 * 1024 * 1024 * 1024).
|
||||||
|
* 8) Two or more numbers (with/without k,b,m,g, or t).
|
||||||
|
* separated by x (also * for backwards compatibility), specifying
|
||||||
|
* the product of the indicated values.
|
||||||
|
*/
|
||||||
|
static u_quad_t
|
||||||
|
strtosize(const char *str, char **endptr, int radix)
|
||||||
|
{
|
||||||
|
u_quad_t num, num2;
|
||||||
|
char *expr, *expr2;
|
||||||
|
|
||||||
|
_DIAGASSERT(str != NULL);
|
||||||
|
/* endptr may be NULL */
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
num = strtouq(str, &expr, radix);
|
||||||
|
if (errno || expr == str) {
|
||||||
|
if (endptr)
|
||||||
|
*endptr = expr;
|
||||||
|
return (num);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(*expr) {
|
||||||
|
case 'b': case 'B':
|
||||||
|
num = multiply(num, (u_quad_t)512);
|
||||||
|
++expr;
|
||||||
|
break;
|
||||||
|
case 'k': case 'K':
|
||||||
|
num = multiply(num, (u_quad_t)1024);
|
||||||
|
++expr;
|
||||||
|
break;
|
||||||
|
case 'm': case 'M':
|
||||||
|
num = multiply(num, (u_quad_t)1024 * 1024);
|
||||||
|
++expr;
|
||||||
|
break;
|
||||||
|
case 'g': case 'G':
|
||||||
|
num = multiply(num, (u_quad_t)1024 * 1024 * 1024);
|
||||||
|
++expr;
|
||||||
|
break;
|
||||||
|
case 't': case 'T':
|
||||||
|
num = multiply(num, (u_quad_t)1024 * 1024);
|
||||||
|
num = multiply(num, (u_quad_t)1024 * 1024);
|
||||||
|
++expr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno)
|
||||||
|
goto erange;
|
||||||
|
|
||||||
|
switch(*expr) {
|
||||||
|
case '*': /* Backward compatible. */
|
||||||
|
case 'x':
|
||||||
|
num2 = strtosize(expr+1, &expr2, radix);
|
||||||
|
if (errno) {
|
||||||
|
expr = expr2;
|
||||||
|
goto erange;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expr2 == expr + 1) {
|
||||||
|
if (endptr)
|
||||||
|
*endptr = expr;
|
||||||
|
return (num);
|
||||||
|
}
|
||||||
|
expr = expr2;
|
||||||
|
num = multiply(num, num2);
|
||||||
|
if (errno)
|
||||||
|
goto erange;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (endptr)
|
||||||
|
*endptr = expr;
|
||||||
|
return (num);
|
||||||
|
erange:
|
||||||
|
if (endptr)
|
||||||
|
*endptr = expr;
|
||||||
|
errno = ERANGE;
|
||||||
|
return (UQUAD_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u_quad_t
|
||||||
|
strtolimit(const char *str, char **endptr, int radix)
|
||||||
|
{
|
||||||
|
|
||||||
|
_DIAGASSERT(str != NULL);
|
||||||
|
/* endptr may be NULL */
|
||||||
|
|
||||||
|
if (isinfinite(str)) {
|
||||||
|
if (endptr)
|
||||||
|
*endptr = (char *)__UNCONST(str) + strlen(str);
|
||||||
|
return ((u_quad_t)RLIM_INFINITY);
|
||||||
|
}
|
||||||
|
return (strtosize(str, endptr, radix));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isinfinite(const char *s)
|
||||||
|
{
|
||||||
|
static const char *infs[] = {
|
||||||
|
"infinity",
|
||||||
|
"inf",
|
||||||
|
"unlimited",
|
||||||
|
"unlimit",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
const char **i;
|
||||||
|
|
||||||
|
_DIAGASSERT(s != NULL);
|
||||||
|
|
||||||
|
for (i = infs; *i; i++) {
|
||||||
|
if (!strcasecmp(s, *i))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u_quad_t
|
||||||
|
multiply(u_quad_t n1, u_quad_t n2)
|
||||||
|
{
|
||||||
|
static int bpw = 0;
|
||||||
|
u_quad_t m;
|
||||||
|
u_quad_t r;
|
||||||
|
int b1, b2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get rid of the simple cases
|
||||||
|
*/
|
||||||
|
if (n1 == 0 || n2 == 0)
|
||||||
|
return (0);
|
||||||
|
if (n1 == 1)
|
||||||
|
return (n2);
|
||||||
|
if (n2 == 1)
|
||||||
|
return (n1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sizeof() returns number of bytes needed for storage.
|
||||||
|
* This may be different from the actual number of useful bits.
|
||||||
|
*/
|
||||||
|
if (!bpw) {
|
||||||
|
bpw = sizeof(u_quad_t) * 8;
|
||||||
|
while (((u_quad_t)1 << (bpw-1)) == 0)
|
||||||
|
--bpw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First check the magnitude of each number. If the sum of the
|
||||||
|
* magnatude is way to high, reject the number. (If this test
|
||||||
|
* is not done then the first multiply below may overflow.)
|
||||||
|
*/
|
||||||
|
for (b1 = bpw; (((u_quad_t)1 << (b1-1)) & n1) == 0; --b1)
|
||||||
|
;
|
||||||
|
for (b2 = bpw; (((u_quad_t)1 << (b2-1)) & n2) == 0; --b2)
|
||||||
|
;
|
||||||
|
if (b1 + b2 - 2 > bpw) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return (UQUAD_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decompose the multiplication to be:
|
||||||
|
* h1 = n1 & ~1
|
||||||
|
* h2 = n2 & ~1
|
||||||
|
* l1 = n1 & 1
|
||||||
|
* l2 = n2 & 1
|
||||||
|
* (h1 + l1) * (h2 + l2)
|
||||||
|
* (h1 * h2) + (h1 * l2) + (l1 * h2) + (l1 * l2)
|
||||||
|
*
|
||||||
|
* Since h1 && h2 do not have the low bit set, we can then say:
|
||||||
|
*
|
||||||
|
* (h1>>1 * h2>>1 * 4) + ...
|
||||||
|
*
|
||||||
|
* So if (h1>>1 * h2>>1) > (1<<(bpw - 2)) then the result will
|
||||||
|
* overflow.
|
||||||
|
*
|
||||||
|
* Finally, if MAX - ((h1 * l2) + (l1 * h2) + (l1 * l2)) < (h1*h2)
|
||||||
|
* then adding in residual amout will cause an overflow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
m = (n1 >> 1) * (n2 >> 1);
|
||||||
|
|
||||||
|
if (m >= ((u_quad_t)1 << (bpw-2))) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return (UQUAD_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
m *= 4;
|
||||||
|
|
||||||
|
r = (n1 & n2 & 1)
|
||||||
|
+ (n2 & 1) * (n1 & ~(u_quad_t)1)
|
||||||
|
+ (n1 & 1) * (n2 & ~(u_quad_t)1);
|
||||||
|
|
||||||
|
if ((u_quad_t)(m + r) < m) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return (UQUAD_MAX);
|
||||||
|
}
|
||||||
|
m += r;
|
||||||
|
|
||||||
|
return (m);
|
||||||
|
}
|
66
lib/libutil/login_tty.c
Normal file
66
lib/libutil/login_tty.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* $NetBSD: login_tty.c,v 1.12 2008/02/09 05:07:26 dholland Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)login_tty.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: login_tty.c,v 1.12 2008/02/09 05:07:26 dholland Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
login_tty(int fd)
|
||||||
|
{
|
||||||
|
|
||||||
|
_DIAGASSERT(fd != -1);
|
||||||
|
|
||||||
|
(void) setsid();
|
||||||
|
#ifdef TIOCSCTTY
|
||||||
|
if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1)
|
||||||
|
return (-1);
|
||||||
|
#endif
|
||||||
|
(void) dup2(fd, STDIN_FILENO);
|
||||||
|
(void) dup2(fd, STDOUT_FILENO);
|
||||||
|
(void) dup2(fd, STDERR_FILENO);
|
||||||
|
if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
|
||||||
|
(void) close(fd);
|
||||||
|
return (0);
|
||||||
|
}
|
93
lib/libutil/loginx.3
Normal file
93
lib/libutil/loginx.3
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
.\" $NetBSD: loginx.3,v 1.3 2008/04/30 13:10:52 martin Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Thomas Klausner.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd September 26, 2002
|
||||||
|
.Dt LOGINX 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm loginx ,
|
||||||
|
.Nm logoutx ,
|
||||||
|
.Nm logwtmpx
|
||||||
|
.Nd login utility functions
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft void
|
||||||
|
.Fn loginx "const struct utmpx *ut"
|
||||||
|
.Ft int
|
||||||
|
.Fn logoutx "const char *line" "int status" "int type"
|
||||||
|
.Ft void
|
||||||
|
.Fn logwtmpx "const char *line" "const char *name" "const char *host" "int status" "int type"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn loginx ,
|
||||||
|
.Fn logoutx ,
|
||||||
|
and
|
||||||
|
.Fn logwtmpx
|
||||||
|
operate on the
|
||||||
|
.Xr utmpx 5
|
||||||
|
database of currently logged in users, and the
|
||||||
|
.Xr wtmpx 5
|
||||||
|
database of logins and logouts.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn loginx
|
||||||
|
function updates the
|
||||||
|
.Pa /var/run/utmpx
|
||||||
|
and
|
||||||
|
.Pa /var/log/wtmpx
|
||||||
|
databases with the information from
|
||||||
|
.Fa ut .
|
||||||
|
.Pp
|
||||||
|
.Fn logoutx
|
||||||
|
updates the entry corresponding to
|
||||||
|
.Fa line
|
||||||
|
with the type and status from
|
||||||
|
.Fa type
|
||||||
|
and
|
||||||
|
.Fa status .
|
||||||
|
.Pp
|
||||||
|
.Fn logwtmpx
|
||||||
|
writes an entry filled with data from
|
||||||
|
.Fa line ,
|
||||||
|
.Fa name ,
|
||||||
|
.Fa host ,
|
||||||
|
.Fa status ,
|
||||||
|
and
|
||||||
|
.Fa type
|
||||||
|
to the
|
||||||
|
.Xr wtmpx 5
|
||||||
|
database.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn logoutx
|
||||||
|
returns 1 on success, and 0 if no corresponding entry was found.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr endutxent 3 ,
|
||||||
|
.Xr utmpx 5
|
54
lib/libutil/loginx.c
Normal file
54
lib/libutil/loginx.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* $NetBSD: loginx.c,v 1.2 2003/08/07 16:44:59 agc Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: loginx.c,v 1.2 2003/08/07 16:44:59 agc Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <utmpx.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
loginx(const struct utmpx *ut)
|
||||||
|
{
|
||||||
|
(void)pututxline(ut);
|
||||||
|
(void)updwtmpx(_PATH_WTMPX, ut);
|
||||||
|
}
|
77
lib/libutil/logout.c
Normal file
77
lib/libutil/logout.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* $NetBSD: logout.c,v 1.16 2005/08/27 17:07:17 elad Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)logout.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: logout.c,v 1.16 2005/08/27 17:07:17 elad Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
logout(const char *line)
|
||||||
|
{
|
||||||
|
int fd, rval;
|
||||||
|
struct utmp ut;
|
||||||
|
|
||||||
|
_DIAGASSERT(line != NULL);
|
||||||
|
|
||||||
|
if ((fd = open(_PATH_UTMP, O_RDWR, 0)) < 0)
|
||||||
|
return(0);
|
||||||
|
rval = 0;
|
||||||
|
while (read(fd, &ut, sizeof(ut)) == sizeof(ut)) {
|
||||||
|
if (!ut.ut_name[0] || strncmp(ut.ut_line, line,
|
||||||
|
(size_t)UT_LINESIZE))
|
||||||
|
continue;
|
||||||
|
memset(ut.ut_name, 0, (size_t)UT_NAMESIZE);
|
||||||
|
memset(ut.ut_host, 0, (size_t)UT_HOSTSIZE);
|
||||||
|
(void)time(&ut.ut_time);
|
||||||
|
(void)lseek(fd, -(off_t)sizeof(ut), SEEK_CUR);
|
||||||
|
(void)write(fd, &ut, sizeof(ut));
|
||||||
|
rval = 1;
|
||||||
|
}
|
||||||
|
(void)close(fd);
|
||||||
|
return(rval);
|
||||||
|
}
|
73
lib/libutil/logoutx.c
Normal file
73
lib/libutil/logoutx.c
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/* $NetBSD: logoutx.c,v 1.2 2003/08/07 16:44:59 agc Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)logout.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: logoutx.c,v 1.2 2003/08/07 16:44:59 agc Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <utmpx.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
logoutx(const char *line, int status, int type)
|
||||||
|
{
|
||||||
|
struct utmpx *utp, ut;
|
||||||
|
(void)strlcpy(ut.ut_line, line, sizeof(ut.ut_line));
|
||||||
|
if ((utp = getutxline(&ut)) == NULL) {
|
||||||
|
endutxent();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
utp->ut_type = type;
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
utp->ut_exit.e_exit = (uint16_t)WEXITSTATUS(status);
|
||||||
|
if (WIFSIGNALED(status))
|
||||||
|
utp->ut_exit.e_termination = (uint16_t)WTERMSIG(status);
|
||||||
|
(void)gettimeofday(&utp->ut_tv, NULL);
|
||||||
|
(void)pututxline(utp);
|
||||||
|
endutxent();
|
||||||
|
return 1;
|
||||||
|
}
|
75
lib/libutil/logwtmp.c
Normal file
75
lib/libutil/logwtmp.c
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* $NetBSD: logwtmp.c,v 1.14 2003/08/07 16:44:59 agc Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: logwtmp.c,v 1.14 2003/08/07 16:44:59 agc Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
logwtmp(const char *line, const char *name, const char *host)
|
||||||
|
{
|
||||||
|
struct utmp ut;
|
||||||
|
struct stat buf;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
_DIAGASSERT(line != NULL);
|
||||||
|
_DIAGASSERT(name != NULL);
|
||||||
|
_DIAGASSERT(host != NULL);
|
||||||
|
|
||||||
|
if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
|
||||||
|
return;
|
||||||
|
if (fstat(fd, &buf) == 0) {
|
||||||
|
(void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
|
||||||
|
(void) strncpy(ut.ut_name, name, sizeof(ut.ut_name));
|
||||||
|
(void) strncpy(ut.ut_host, host, sizeof(ut.ut_host));
|
||||||
|
(void) time(&ut.ut_time);
|
||||||
|
if (write(fd, &ut, sizeof(struct utmp)) != sizeof(struct utmp))
|
||||||
|
(void) ftruncate(fd, buf.st_size);
|
||||||
|
}
|
||||||
|
(void) close(fd);
|
||||||
|
}
|
76
lib/libutil/logwtmpx.c
Normal file
76
lib/libutil/logwtmpx.c
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/* $NetBSD: logwtmpx.c,v 1.2 2003/08/07 16:44:59 agc Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: logwtmpx.c,v 1.2 2003/08/07 16:44:59 agc Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <utmpx.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
logwtmpx(const char *line, const char *name, const char *host, int status,
|
||||||
|
int type)
|
||||||
|
{
|
||||||
|
struct utmpx ut;
|
||||||
|
|
||||||
|
_DIAGASSERT(line != NULL);
|
||||||
|
_DIAGASSERT(name != NULL);
|
||||||
|
_DIAGASSERT(host != NULL);
|
||||||
|
|
||||||
|
(void)memset(&ut, 0, sizeof(ut));
|
||||||
|
(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
|
||||||
|
(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
|
||||||
|
(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
|
||||||
|
ut.ut_type = type;
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
ut.ut_exit.e_exit = (uint16_t)WEXITSTATUS(status);
|
||||||
|
if (WIFSIGNALED(status))
|
||||||
|
ut.ut_exit.e_termination = (uint16_t)WTERMSIG(status);
|
||||||
|
(void)gettimeofday(&ut.ut_tv, NULL);
|
||||||
|
(void)updwtmpx(_PATH_WTMPX, &ut);
|
||||||
|
}
|
172
lib/libutil/opendisk.3
Normal file
172
lib/libutil/opendisk.3
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
.\" $NetBSD: opendisk.3,v 1.11 2008/04/30 13:10:52 martin Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1997, 2001 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Luke Mewburn.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd December 11, 2001
|
||||||
|
.Dt OPENDISK 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm opendisk
|
||||||
|
.Nd open a disk partition
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fo opendisk
|
||||||
|
.Fa "const char *path"
|
||||||
|
.Fa "int flags"
|
||||||
|
.Fa "char *buf"
|
||||||
|
.Fa "size_t buflen"
|
||||||
|
.Fa "int iscooked"
|
||||||
|
.Fc
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn opendisk
|
||||||
|
opens
|
||||||
|
.Fa path ,
|
||||||
|
for reading and/or writing as specified by the argument
|
||||||
|
.Fa flags
|
||||||
|
using
|
||||||
|
.Xr open 2 ,
|
||||||
|
and the file descriptor is returned to the caller.
|
||||||
|
.Fa buf
|
||||||
|
is used to store the resultant filename.
|
||||||
|
.Fa buflen
|
||||||
|
is the size, in bytes, of the array referenced by
|
||||||
|
.Fa buf
|
||||||
|
(usually
|
||||||
|
.Dv MAXPATHLEN
|
||||||
|
bytes).
|
||||||
|
.Fa iscooked
|
||||||
|
controls which paths in
|
||||||
|
.Pa /dev
|
||||||
|
are tried.
|
||||||
|
.Pp
|
||||||
|
.Fn opendisk
|
||||||
|
attempts to open the following variations of
|
||||||
|
.Fa path ,
|
||||||
|
in order:
|
||||||
|
.Bl -tag -width "/dev/rpathX"
|
||||||
|
.It Pa path
|
||||||
|
The pathname as given.
|
||||||
|
.It Pa path Ns Em X
|
||||||
|
.Fa path
|
||||||
|
with a suffix of
|
||||||
|
.Sq Em X ,
|
||||||
|
where
|
||||||
|
.Sq Em X
|
||||||
|
represents the raw partition of the device, as determined by
|
||||||
|
.Xr getrawpartition 3 ,
|
||||||
|
usually
|
||||||
|
.Dq c .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Fa path
|
||||||
|
does not contain a
|
||||||
|
slash
|
||||||
|
.Pq Dq / ,
|
||||||
|
the following variations are attempted:
|
||||||
|
.Pp
|
||||||
|
.Bl -dash -offset indent
|
||||||
|
.It
|
||||||
|
If
|
||||||
|
.Fa iscooked
|
||||||
|
is zero:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width "/dev/rpathX"
|
||||||
|
.It Pa /dev/rpath
|
||||||
|
.Fa path
|
||||||
|
with a prefix of
|
||||||
|
.Dq Pa /dev/r .
|
||||||
|
.It Pa /dev/rpath Ns Em X
|
||||||
|
.Fa path
|
||||||
|
with a prefix of
|
||||||
|
.Dq Pa /dev/r
|
||||||
|
and a suffix of
|
||||||
|
.Sq Em X
|
||||||
|
(q.v.).
|
||||||
|
.El
|
||||||
|
.It
|
||||||
|
If
|
||||||
|
.Fa iscooked
|
||||||
|
is non-zero:
|
||||||
|
.Bl -tag -width "/dev/rpathX"
|
||||||
|
.It Pa /dev/path
|
||||||
|
.Fa path
|
||||||
|
with a prefix of
|
||||||
|
.Dq Pa /dev/ .
|
||||||
|
.It Pa /dev/path Ns Em X
|
||||||
|
.Fa path
|
||||||
|
with a prefix of
|
||||||
|
.Dq Pa /dev/
|
||||||
|
and a suffix of
|
||||||
|
.Sq Em X
|
||||||
|
(q.v.).
|
||||||
|
.El
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
An open file descriptor, or -1 if the
|
||||||
|
.Xr open 2
|
||||||
|
failed.
|
||||||
|
.Sh ERRORS
|
||||||
|
.Fn opendisk
|
||||||
|
may set
|
||||||
|
.Va errno
|
||||||
|
to one of the following values:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EINVAL
|
||||||
|
.Dv O_CREAT
|
||||||
|
was set in
|
||||||
|
.Fa flags ,
|
||||||
|
or
|
||||||
|
.Xr getrawpartition 3
|
||||||
|
didn't return a valid partition.
|
||||||
|
.It Bq Er EFAULT
|
||||||
|
.Fa buf
|
||||||
|
was the
|
||||||
|
.Dv NULL
|
||||||
|
pointer.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn opendisk
|
||||||
|
function
|
||||||
|
may also set
|
||||||
|
.Va errno
|
||||||
|
to any value specified by the
|
||||||
|
.Xr open 2
|
||||||
|
function.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr open 2 ,
|
||||||
|
.Xr getrawpartition 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn opendisk
|
||||||
|
function first appeared in
|
||||||
|
.Nx 1.3 .
|
104
lib/libutil/opendisk.c
Normal file
104
lib/libutil/opendisk.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/* $NetBSD: opendisk.c,v 1.12 2009/10/13 22:00:31 pooka Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Luke Mewburn.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: opendisk.c,v 1.12 2009/10/13 22:00:31 pooka Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
__opendisk(const char *path, int flags, char *buf, size_t buflen, int iscooked,
|
||||||
|
int (*ofn)(const char *, int, ...))
|
||||||
|
{
|
||||||
|
int f, rawpart;
|
||||||
|
|
||||||
|
if (buf == NULL) {
|
||||||
|
errno = EFAULT;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
snprintf(buf, buflen, "%s", path);
|
||||||
|
|
||||||
|
if ((flags & O_CREAT) != 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rawpart = getrawpartition();
|
||||||
|
if (rawpart < 0)
|
||||||
|
return (-1); /* sysctl(3) in getrawpartition sets errno */
|
||||||
|
|
||||||
|
f = ofn(buf, flags, 0);
|
||||||
|
if (f != -1 || errno != ENOENT)
|
||||||
|
return (f);
|
||||||
|
|
||||||
|
snprintf(buf, buflen, "%s%c", path, 'a' + rawpart);
|
||||||
|
f = ofn(buf, flags, 0);
|
||||||
|
if (f != -1 || errno != ENOENT)
|
||||||
|
return (f);
|
||||||
|
|
||||||
|
if (strchr(path, '/') != NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
snprintf(buf, buflen, "%s%s%s", _PATH_DEV, iscooked ? "" : "r", path);
|
||||||
|
f = ofn(buf, flags, 0);
|
||||||
|
if (f != -1 || errno != ENOENT)
|
||||||
|
return (f);
|
||||||
|
|
||||||
|
snprintf(buf, buflen, "%s%s%s%c", _PATH_DEV, iscooked ? "" : "r", path,
|
||||||
|
'a' + rawpart);
|
||||||
|
f = ofn(buf, flags, 0);
|
||||||
|
return (f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
opendisk(const char *path, int flags, char *buf, size_t buflen, int iscooked)
|
||||||
|
{
|
||||||
|
|
||||||
|
return __opendisk(path, flags, buf, buflen, iscooked, open);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
opendisk1(const char *path, int flags, char *buf, size_t buflen, int iscooked,
|
||||||
|
int (*ofn)(const char *, int, ...))
|
||||||
|
{
|
||||||
|
|
||||||
|
return __opendisk(path, flags, buf, buflen, iscooked, ofn);
|
||||||
|
}
|
165
lib/libutil/openpty.3
Normal file
165
lib/libutil/openpty.3
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
.\" $NetBSD: openpty.3,v 1.14 2008/11/28 07:17:17 dholland Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1995
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software developed by the Computer Systems
|
||||||
|
.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract
|
||||||
|
.\" BG 91-66 and contributed to Berkeley.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd November 28, 2008
|
||||||
|
.Dt OPENPTY 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm openpty ,
|
||||||
|
.Nm login_tty ,
|
||||||
|
.Nm forkpty
|
||||||
|
.Nd tty utility functions
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn openpty "int *amaster" "int *aslave" "char *name" "struct termios *termp" "struct winsize *winp"
|
||||||
|
.Ft int
|
||||||
|
.Fn login_tty "int fd"
|
||||||
|
.Ft pid_t
|
||||||
|
.Fn forkpty "int *amaster" "char *name" "struct termios *termp" "struct winsize *winp"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn openpty ,
|
||||||
|
.Fn login_tty ,
|
||||||
|
and
|
||||||
|
.Fn forkpty
|
||||||
|
functions perform manipulations on ttys and pseudo-ttys.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn openpty
|
||||||
|
function finds an available pseudo-tty and returns file descriptors
|
||||||
|
for the master and slave in
|
||||||
|
.Fa amaster
|
||||||
|
and
|
||||||
|
.Fa aslave .
|
||||||
|
If
|
||||||
|
.Fa name
|
||||||
|
is non-null, the filename of the slave is returned in
|
||||||
|
.Fa name .
|
||||||
|
If
|
||||||
|
.Fa termp
|
||||||
|
is non-null, the terminal parameters of the slave will be set to the
|
||||||
|
values in
|
||||||
|
.Fa termp .
|
||||||
|
If
|
||||||
|
.Fa winp
|
||||||
|
is non-null, the window size of the slave will be set to the values in
|
||||||
|
.Fa winp .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn login_tty
|
||||||
|
function prepares for a login on the tty
|
||||||
|
.Fa fd
|
||||||
|
(which may be a real tty device, or the slave of a pseudo-tty as
|
||||||
|
returned by
|
||||||
|
.Fn openpty )
|
||||||
|
by creating a new session, making
|
||||||
|
.Fa fd
|
||||||
|
the controlling terminal for the current process, setting
|
||||||
|
.Fa fd
|
||||||
|
to be the standard input, output, and error streams of the current
|
||||||
|
process, and closing
|
||||||
|
.Fa fd .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn forkpty
|
||||||
|
function combines
|
||||||
|
.Fn openpty ,
|
||||||
|
.Fn fork ,
|
||||||
|
and
|
||||||
|
.Fn login_tty
|
||||||
|
to create a new process operating in a pseudo-tty.
|
||||||
|
The file descriptor of the master side of the pseudo-tty is returned
|
||||||
|
(to the parent process only) in
|
||||||
|
.Fa amaster .
|
||||||
|
The filename of the slave is returned (to both the parent and child
|
||||||
|
processes) in
|
||||||
|
.Fa name
|
||||||
|
if
|
||||||
|
.Fa name
|
||||||
|
is non-null.
|
||||||
|
The
|
||||||
|
.Fa termp
|
||||||
|
and
|
||||||
|
.Fa winp
|
||||||
|
parameters, if non-null, will determine the terminal attributes and
|
||||||
|
window size of the slave side of the pseudo-tty.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
If a call to
|
||||||
|
.Fn openpty ,
|
||||||
|
.Fn login_tty ,
|
||||||
|
or
|
||||||
|
.Fn forkpty
|
||||||
|
is not successful, -1 is returned and
|
||||||
|
.Va errno
|
||||||
|
is set to indicate the error.
|
||||||
|
Otherwise,
|
||||||
|
.Fn openpty ,
|
||||||
|
.Fn login_tty ,
|
||||||
|
and the child process of
|
||||||
|
.Fn forkpty
|
||||||
|
return 0, and the parent process of
|
||||||
|
.Fn forkpty
|
||||||
|
returns the process ID of the child process.
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /dev/[pt]ty[p-zP-T][0-9a-zA-Z] -compact
|
||||||
|
.It Pa /dev/[pt]ty[p-zP-T][0-9a-zA-Z]
|
||||||
|
.El
|
||||||
|
.Sh ERRORS
|
||||||
|
.Fn openpty
|
||||||
|
will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er ENOENT
|
||||||
|
There are no available ttys.
|
||||||
|
.It Bq Er EPERM
|
||||||
|
The caller was not the superuser and the
|
||||||
|
.Xr ptm 4
|
||||||
|
device is missing or not configured.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
.Fn login_tty
|
||||||
|
will fail if
|
||||||
|
.Fn ioctl
|
||||||
|
fails to set
|
||||||
|
.Fa fd
|
||||||
|
to the controlling terminal of the current process.
|
||||||
|
.Fn forkpty
|
||||||
|
will fail if either
|
||||||
|
.Fn openpty
|
||||||
|
or
|
||||||
|
.Fn fork
|
||||||
|
fails.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr fork 2
|
278
lib/libutil/parsedate.3
Normal file
278
lib/libutil/parsedate.3
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
.\" $NetBSD: parsedate.3,v 1.10 2010/12/22 09:12:28 wiz Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Christos Zoulas.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd December 20, 2010
|
||||||
|
.Dt PARSEDATE 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm parsedate
|
||||||
|
.Nd date parsing function
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft time_t
|
||||||
|
.Fn parsedate "const char *datestr" "const time_t *time" "const int *tzoff"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn parsedate
|
||||||
|
function parses a datetime from
|
||||||
|
.Ar datestr
|
||||||
|
described in english relative to an optional
|
||||||
|
.Ar time
|
||||||
|
point and an optional timezone offset in seconds specified in
|
||||||
|
.Ar tzoff .
|
||||||
|
If either
|
||||||
|
.Ar time
|
||||||
|
or
|
||||||
|
.Ar tzoff
|
||||||
|
are
|
||||||
|
.Dv NULL ,
|
||||||
|
then the current time and timezone offset are used.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ar datestr
|
||||||
|
is a sequence of white-space separated items.
|
||||||
|
The white-space is optional the concatenated items are not ambiguous.
|
||||||
|
An empty
|
||||||
|
.Ar datestr
|
||||||
|
is equivalent to midnight today (the beginning of this day).
|
||||||
|
.Pp
|
||||||
|
The following words have the indicated numeric meanings:
|
||||||
|
.Dv last =
|
||||||
|
\-1,
|
||||||
|
.Dv this =
|
||||||
|
0,
|
||||||
|
.Dv first, next, or one =
|
||||||
|
1,
|
||||||
|
.Dv second
|
||||||
|
is unused so that it is not confused with
|
||||||
|
.Dq seconds ,
|
||||||
|
.Dv two =
|
||||||
|
2,
|
||||||
|
.Dv third or three =
|
||||||
|
3,
|
||||||
|
.Dv fourth or four =
|
||||||
|
4,
|
||||||
|
.Dv fifth or five =
|
||||||
|
5,
|
||||||
|
.Dv sixth or six =
|
||||||
|
6,
|
||||||
|
.Dv seventh or seven =
|
||||||
|
7,
|
||||||
|
.Dv eighth or eight =
|
||||||
|
8,
|
||||||
|
.Dv ninth or nine =
|
||||||
|
9,
|
||||||
|
.Dv tenth or ten =
|
||||||
|
10,
|
||||||
|
.Dv eleventh or eleven =
|
||||||
|
11,
|
||||||
|
.Dv twelfth or twoelve =
|
||||||
|
12.
|
||||||
|
.Pp
|
||||||
|
The following words are recognized in English only:
|
||||||
|
.Dv AM ,
|
||||||
|
.Dv PM ,
|
||||||
|
.Dv a.m. ,
|
||||||
|
.Dv p.m.
|
||||||
|
.Pp
|
||||||
|
The months:
|
||||||
|
.Dv january ,
|
||||||
|
.Dv february ,
|
||||||
|
.Dv march ,
|
||||||
|
.Dv april ,
|
||||||
|
.Dv may ,
|
||||||
|
.Dv june ,
|
||||||
|
.Dv july ,
|
||||||
|
.Dv august ,
|
||||||
|
.Dv september ,
|
||||||
|
.Dv sept ,
|
||||||
|
.Dv october ,
|
||||||
|
.Dv november ,
|
||||||
|
.Dv december ,
|
||||||
|
.Pp
|
||||||
|
The days of the week:
|
||||||
|
.Dv sunday ,
|
||||||
|
.Dv monday ,
|
||||||
|
.Dv tuesday ,
|
||||||
|
.Dv tues ,
|
||||||
|
.Dv wednesday ,
|
||||||
|
.Dv wednes ,
|
||||||
|
.Dv thursday ,
|
||||||
|
.Dv thur ,
|
||||||
|
.Dv thurs ,
|
||||||
|
.Dv friday ,
|
||||||
|
.Dv saturday .
|
||||||
|
.Pp
|
||||||
|
Time units:
|
||||||
|
.Dv year ,
|
||||||
|
.Dv month ,
|
||||||
|
.Dv fortnight ,
|
||||||
|
.Dv week ,
|
||||||
|
.Dv day ,
|
||||||
|
.Dv hour ,
|
||||||
|
.Dv minute ,
|
||||||
|
.Dv min ,
|
||||||
|
.Dv second ,
|
||||||
|
.Dv sec ,
|
||||||
|
.Dv tomorrow ,
|
||||||
|
.Dv yesterday .
|
||||||
|
.Pp
|
||||||
|
Timezone names:
|
||||||
|
.Dv gmt ,
|
||||||
|
.Dv ut ,
|
||||||
|
.Dv utc ,
|
||||||
|
.Dv wet ,
|
||||||
|
.Dv bst ,
|
||||||
|
.Dv wat ,
|
||||||
|
.Dv at ,
|
||||||
|
.Dv ast ,
|
||||||
|
.Dv adt ,
|
||||||
|
.Dv est ,
|
||||||
|
.Dv edt ,
|
||||||
|
.Dv cst ,
|
||||||
|
.Dv cdt ,
|
||||||
|
.Dv mst ,
|
||||||
|
.Dv mdt ,
|
||||||
|
.Dv pst ,
|
||||||
|
.Dv pdt ,
|
||||||
|
.Dv yst ,
|
||||||
|
.Dv ydt ,
|
||||||
|
.Dv hst ,
|
||||||
|
.Dv hdt ,
|
||||||
|
.Dv cat ,
|
||||||
|
.Dv ahst ,
|
||||||
|
.Dv nt ,
|
||||||
|
.Dv idlw ,
|
||||||
|
.Dv cet ,
|
||||||
|
.Dv met ,
|
||||||
|
.Dv mewt ,
|
||||||
|
.Dv mest ,
|
||||||
|
.Dv swt ,
|
||||||
|
.Dv sst ,
|
||||||
|
.Dv fwt ,
|
||||||
|
.Dv fst ,
|
||||||
|
.Dv eet ,
|
||||||
|
.Dv bt ,
|
||||||
|
.Dv zp4 ,
|
||||||
|
.Dv zp5 ,
|
||||||
|
.Dv zp6 ,
|
||||||
|
.Dv wast ,
|
||||||
|
.Dv wadt ,
|
||||||
|
.Dv cct ,
|
||||||
|
.Dv jst ,
|
||||||
|
.Dv east ,
|
||||||
|
.Dv eadt ,
|
||||||
|
.Dv gst ,
|
||||||
|
.Dv nzt ,
|
||||||
|
.Dv nzst ,
|
||||||
|
.Dv nzdt ,
|
||||||
|
.Dv idle .
|
||||||
|
.Pp
|
||||||
|
A variety of unambiguous dates are recognized:
|
||||||
|
.Bl -tag -compact -width "20 Jun 1994"
|
||||||
|
.It 69-09-10
|
||||||
|
For years between 69-99 we assume 1900+ and for years between 0-68
|
||||||
|
we assume 2000+.
|
||||||
|
.It 2006-11-17
|
||||||
|
An ISO-8601 date.
|
||||||
|
.It 10/1/2000
|
||||||
|
October 10, 2000; the common US format.
|
||||||
|
.It 20 Jun 1994
|
||||||
|
.It 23jun2001
|
||||||
|
.It 1-sep-06
|
||||||
|
Other common abbreviations.
|
||||||
|
.It 1/11
|
||||||
|
the year can be omitted
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
As well as times:
|
||||||
|
.Bl -tag -compact -width 12:11:01.000012
|
||||||
|
.It 10:01
|
||||||
|
.It 10:12pm
|
||||||
|
.It 12:11:01.000012
|
||||||
|
.It 12:21-0500
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Relative items are also supported:
|
||||||
|
.Bl -tag -compact -width "this thursday"
|
||||||
|
.It -1 month
|
||||||
|
.It last friday
|
||||||
|
.It one week ago
|
||||||
|
.It this thursday
|
||||||
|
.It next sunday
|
||||||
|
.It +2 years
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Seconds since epoch (also known as UNIX time) are also supported:
|
||||||
|
.Bl -tag -compact -width "@735275209"
|
||||||
|
.It @735275209
|
||||||
|
Tue Apr 20 03:06:49 UTC 1993
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn parsedate
|
||||||
|
returns the number of seconds passed since the Epoch, or
|
||||||
|
.Dv \-1
|
||||||
|
if the date could not be parsed properly.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr date 1 ,
|
||||||
|
.Xr eeprom 8
|
||||||
|
.Sh HISTORY
|
||||||
|
The parser used in
|
||||||
|
.Fn parsedate
|
||||||
|
was originally written by Steven M. Bellovin while at the University
|
||||||
|
of North Carolina at Chapel Hill.
|
||||||
|
It was later tweaked by a couple of people on Usenet.
|
||||||
|
Completely overhauled by Rich $alz and Jim Berets in August, 1990.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn parsedate
|
||||||
|
function first appeared in
|
||||||
|
.Nx 4.0 .
|
||||||
|
.Sh BUGS
|
||||||
|
.Bl -tag -compact -width 1
|
||||||
|
.It 1
|
||||||
|
The
|
||||||
|
.Fn parsedate
|
||||||
|
function is not re-entrant or thread-safe.
|
||||||
|
.It 2
|
||||||
|
The
|
||||||
|
.Fn parsedate
|
||||||
|
function cannot compute days before the unix epoch (19700101).
|
||||||
|
.It 3
|
||||||
|
The
|
||||||
|
.Fn parsedate
|
||||||
|
function assumes years less than 0 mean -
|
||||||
|
.Fa year ,
|
||||||
|
years less than 70 mean 2000 +
|
||||||
|
.Fa year ,
|
||||||
|
years less than 100 mean 1900 +
|
||||||
|
.Fa year .
|
||||||
|
.El
|
1060
lib/libutil/parsedate.y
Normal file
1060
lib/libutil/parsedate.y
Normal file
File diff suppressed because it is too large
Load diff
665
lib/libutil/passwd.c
Normal file
665
lib/libutil/passwd.c
Normal file
|
@ -0,0 +1,665 @@
|
||||||
|
/* $NetBSD: passwd.c,v 1.50 2010/08/18 08:32:02 christos Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1987, 1993, 1994, 1995
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: passwd.c,v 1.50 2010/08/18 08:32:02 christos Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
static const char *pw_filename(const char *filename);
|
||||||
|
static void pw_cont(int sig);
|
||||||
|
static const char * pw_equal(char *buf, struct passwd *old_pw);
|
||||||
|
static const char *pw_default(const char *option);
|
||||||
|
static int read_line(FILE *fp, char *line, int max);
|
||||||
|
static void trim_whitespace(char *line);
|
||||||
|
|
||||||
|
static char pw_prefix[MAXPATHLEN];
|
||||||
|
|
||||||
|
const char *
|
||||||
|
pw_getprefix(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return(pw_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_setprefix(const char *new_prefix)
|
||||||
|
{
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
_DIAGASSERT(new_prefix != NULL);
|
||||||
|
|
||||||
|
length = strlen(new_prefix);
|
||||||
|
if (length < sizeof(pw_prefix)) {
|
||||||
|
(void)strcpy(pw_prefix, new_prefix);
|
||||||
|
while (length > 0 && pw_prefix[length - 1] == '/')
|
||||||
|
pw_prefix[--length] = '\0';
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
pw_filename(const char *filename)
|
||||||
|
{
|
||||||
|
static char newfilename[MAXPATHLEN];
|
||||||
|
|
||||||
|
_DIAGASSERT(filename != NULL);
|
||||||
|
|
||||||
|
if (pw_prefix[0] == '\0')
|
||||||
|
return filename;
|
||||||
|
|
||||||
|
if (strlen(pw_prefix) + strlen(filename) < sizeof(newfilename))
|
||||||
|
return strcat(strcpy(newfilename, pw_prefix), filename);
|
||||||
|
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_lock(int retries)
|
||||||
|
{
|
||||||
|
const char *filename;
|
||||||
|
int i, fd;
|
||||||
|
mode_t old_mode;
|
||||||
|
int oerrno;
|
||||||
|
|
||||||
|
/* Acquire the lock file. */
|
||||||
|
filename = pw_filename(_PATH_MASTERPASSWD_LOCK);
|
||||||
|
if (filename == NULL)
|
||||||
|
return(-1);
|
||||||
|
old_mode = umask(0);
|
||||||
|
fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, 0600);
|
||||||
|
for (i = 0; i < retries && fd < 0 && errno == EEXIST; i++) {
|
||||||
|
sleep(1);
|
||||||
|
fd = open(filename, O_WRONLY|O_CREAT|O_EXCL,
|
||||||
|
0600);
|
||||||
|
}
|
||||||
|
oerrno = errno;
|
||||||
|
(void)umask(old_mode);
|
||||||
|
errno = oerrno;
|
||||||
|
return(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_mkdb(username, secureonly)
|
||||||
|
const char *username;
|
||||||
|
int secureonly;
|
||||||
|
{
|
||||||
|
const char *args[9];
|
||||||
|
int pstat, i;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = vfork();
|
||||||
|
if (pid == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
args[0] = "pwd_mkdb";
|
||||||
|
args[1] = "-d";
|
||||||
|
args[2] = pw_prefix;
|
||||||
|
args[3] = "-pl";
|
||||||
|
i = 4;
|
||||||
|
|
||||||
|
if (secureonly)
|
||||||
|
args[i++] = "-s";
|
||||||
|
if (username != NULL) {
|
||||||
|
args[i++] = "-u";
|
||||||
|
args[i++] = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
args[i++] = pw_filename(_PATH_MASTERPASSWD_LOCK);
|
||||||
|
args[i] = NULL;
|
||||||
|
execv(_PATH_PWD_MKDB, (char * const *)__UNCONST(args));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
pid = waitpid(pid, &pstat, 0);
|
||||||
|
if (pid == -1) {
|
||||||
|
warn("error waiting for pid %lu", (unsigned long)pid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (WIFEXITED(pstat)) {
|
||||||
|
if (WEXITSTATUS(pstat) != 0) {
|
||||||
|
warnx("pwd_mkdb exited with static %d",
|
||||||
|
WEXITSTATUS(pstat));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (WIFSIGNALED(pstat)) {
|
||||||
|
warnx("pwd_mkdb exited with signal %d", WTERMSIG(pstat));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_abort(void)
|
||||||
|
{
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
filename = pw_filename(_PATH_MASTERPASSWD_LOCK);
|
||||||
|
return((filename == NULL) ? -1 : unlink(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Everything below this point is intended for the convenience of programs
|
||||||
|
* which allow a user to interactively edit the passwd file. Errors in the
|
||||||
|
* routines below will cause the process to abort. */
|
||||||
|
|
||||||
|
static pid_t editpid = -1;
|
||||||
|
|
||||||
|
static void
|
||||||
|
pw_cont(int sig)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (editpid != -1)
|
||||||
|
kill(editpid, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_init(void)
|
||||||
|
{
|
||||||
|
struct rlimit rlim;
|
||||||
|
|
||||||
|
#ifndef __minix
|
||||||
|
/* Unlimited resource limits. */
|
||||||
|
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
|
||||||
|
(void)setrlimit(RLIMIT_CPU, &rlim);
|
||||||
|
(void)setrlimit(RLIMIT_FSIZE, &rlim);
|
||||||
|
(void)setrlimit(RLIMIT_STACK, &rlim);
|
||||||
|
(void)setrlimit(RLIMIT_DATA, &rlim);
|
||||||
|
(void)setrlimit(RLIMIT_RSS, &rlim);
|
||||||
|
|
||||||
|
/* Don't drop core (not really necessary, but GP's). */
|
||||||
|
rlim.rlim_cur = rlim.rlim_max = 0;
|
||||||
|
(void)setrlimit(RLIMIT_CORE, &rlim);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Turn off signals. */
|
||||||
|
(void)signal(SIGALRM, SIG_IGN);
|
||||||
|
(void)signal(SIGHUP, SIG_IGN);
|
||||||
|
(void)signal(SIGINT, SIG_IGN);
|
||||||
|
(void)signal(SIGPIPE, SIG_IGN);
|
||||||
|
(void)signal(SIGQUIT, SIG_IGN);
|
||||||
|
(void)signal(SIGTERM, SIG_IGN);
|
||||||
|
(void)signal(SIGCONT, pw_cont);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_edit(int notsetuid, const char *filename)
|
||||||
|
{
|
||||||
|
int pstat;
|
||||||
|
char *p;
|
||||||
|
const char * volatile editor;
|
||||||
|
const char *argp[] = { "sh", "-c", NULL, NULL };
|
||||||
|
|
||||||
|
if (filename == NULL)
|
||||||
|
filename = _PATH_MASTERPASSWD_LOCK;
|
||||||
|
|
||||||
|
filename = pw_filename(filename);
|
||||||
|
if (filename == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((editor = getenv("EDITOR")) == NULL)
|
||||||
|
editor = _PATH_VI;
|
||||||
|
|
||||||
|
p = malloc(strlen(editor) + 1 + strlen(filename) + 1);
|
||||||
|
if (p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sprintf(p, "%s %s", editor, filename);
|
||||||
|
argp[2] = p;
|
||||||
|
|
||||||
|
switch(editpid = vfork()) {
|
||||||
|
case -1:
|
||||||
|
free(p);
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
if (notsetuid) {
|
||||||
|
setgid(getgid());
|
||||||
|
setuid(getuid());
|
||||||
|
}
|
||||||
|
execvp(_PATH_BSHELL, (char *const *)__UNCONST(argp));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
|
||||||
|
if (editpid == -1)
|
||||||
|
pw_error(editor, 1, 1);
|
||||||
|
else if (WIFSTOPPED(pstat))
|
||||||
|
raise(WSTOPSIG(pstat));
|
||||||
|
else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
pw_error(editor, 1, 1);
|
||||||
|
}
|
||||||
|
editpid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_prompt(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
(void)printf("re-edit the password file? [y]: ");
|
||||||
|
(void)fflush(stdout);
|
||||||
|
c = getchar();
|
||||||
|
if (c != EOF && c != '\n')
|
||||||
|
while (getchar() != '\n');
|
||||||
|
if (c == 'n')
|
||||||
|
pw_error(NULL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for use in pw_copy(). Compare a pw entry to a pw struct. */
|
||||||
|
/* returns a character string labelling the miscompared field or 0 */
|
||||||
|
static const char *
|
||||||
|
pw_equal(char *buf, struct passwd *pw)
|
||||||
|
{
|
||||||
|
struct passwd buf_pw;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
_DIAGASSERT(buf != NULL);
|
||||||
|
_DIAGASSERT(pw != NULL);
|
||||||
|
|
||||||
|
len = strlen (buf);
|
||||||
|
if (buf[len-1] == '\n')
|
||||||
|
buf[len-1] = '\0';
|
||||||
|
if (!pw_scan(buf, &buf_pw, NULL))
|
||||||
|
return "corrupt line";
|
||||||
|
if (strcmp(pw->pw_name, buf_pw.pw_name) != 0)
|
||||||
|
return "name";
|
||||||
|
if (pw->pw_uid != buf_pw.pw_uid)
|
||||||
|
return "uid";
|
||||||
|
if (pw->pw_gid != buf_pw.pw_gid)
|
||||||
|
return "gid";
|
||||||
|
if (strcmp( pw->pw_class, buf_pw.pw_class) != 0)
|
||||||
|
return "class";
|
||||||
|
if (pw->pw_change != buf_pw.pw_change)
|
||||||
|
return "change";
|
||||||
|
if (pw->pw_expire != buf_pw.pw_expire)
|
||||||
|
return "expire";
|
||||||
|
if (strcmp( pw->pw_gecos, buf_pw.pw_gecos) != 0)
|
||||||
|
return "gecos";
|
||||||
|
if (strcmp( pw->pw_dir, buf_pw.pw_dir) != 0)
|
||||||
|
return "dir";
|
||||||
|
if (strcmp( pw->pw_shell, buf_pw.pw_shell) != 0)
|
||||||
|
return "shell";
|
||||||
|
return (char *)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_copy(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw)
|
||||||
|
{
|
||||||
|
char errbuf[200];
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = pw_copyx(ffd, tfd, pw, old_pw, errbuf, sizeof(errbuf));
|
||||||
|
if (rv == 0) {
|
||||||
|
warnx("%s", errbuf);
|
||||||
|
pw_error(NULL, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pw_print(FILE *to, const struct passwd *pw)
|
||||||
|
{
|
||||||
|
(void)fprintf(to, "%s:%s:%d:%d:%s:%lld:%lld:%s:%s:%s\n",
|
||||||
|
pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
|
||||||
|
pw->pw_class, (long long)pw->pw_change,
|
||||||
|
(long long)pw->pw_expire,
|
||||||
|
pw->pw_gecos, pw->pw_dir, pw->pw_shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pw_copyx(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw,
|
||||||
|
char *errbuf, size_t errbufsz)
|
||||||
|
{
|
||||||
|
const char *filename;
|
||||||
|
char mpwd[MAXPATHLEN], mpwdl[MAXPATHLEN], *p, buf[8192];
|
||||||
|
FILE *from, *to;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
_DIAGASSERT(pw != NULL);
|
||||||
|
_DIAGASSERT(errbuf != NULL);
|
||||||
|
/* old_pw may be NULL */
|
||||||
|
|
||||||
|
if ((filename = pw_filename(_PATH_MASTERPASSWD)) == NULL) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s: %s", pw_prefix,
|
||||||
|
strerror(errno));
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
(void)strcpy(mpwd, filename);
|
||||||
|
if ((filename = pw_filename(_PATH_MASTERPASSWD_LOCK)) == NULL) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s: %s", pw_prefix,
|
||||||
|
strerror(errno));
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
(void)strcpy(mpwdl, filename);
|
||||||
|
|
||||||
|
if (!(from = fdopen(ffd, "r"))) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s: %s", mpwd, strerror(errno));
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (!(to = fdopen(tfd, "w"))) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s: %s", mpwdl, strerror(errno));
|
||||||
|
(void)fclose(from);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (done = 0; fgets(buf, (int)sizeof(buf), from);) {
|
||||||
|
const char *neq;
|
||||||
|
if (!strchr(buf, '\n')) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s: line too long", mpwd);
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
(void)fprintf(to, "%s", buf);
|
||||||
|
if (ferror(to)) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s",
|
||||||
|
strerror(errno));
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(p = strchr(buf, ':'))) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s: corrupted entry", mpwd);
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
if (strcmp(buf, pw->pw_name)) {
|
||||||
|
*p = ':';
|
||||||
|
(void)fprintf(to, "%s", buf);
|
||||||
|
if (ferror(to)) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s",
|
||||||
|
strerror(errno));
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*p = ':';
|
||||||
|
if (old_pw && (neq = pw_equal(buf, old_pw)) != NULL) {
|
||||||
|
if (strcmp(neq, "corrupt line") == 0)
|
||||||
|
(void)snprintf(errbuf, errbufsz,
|
||||||
|
"%s: entry %s corrupted", mpwd,
|
||||||
|
pw->pw_name);
|
||||||
|
else
|
||||||
|
(void)snprintf(errbuf, errbufsz,
|
||||||
|
"%s: entry %s inconsistent %s",
|
||||||
|
mpwd, pw->pw_name, neq);
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
pw_print(to, pw);
|
||||||
|
done = 1;
|
||||||
|
if (ferror(to)) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s", strerror(errno));
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Only append a new entry if real uid is root! */
|
||||||
|
if (!done) {
|
||||||
|
if (getuid() == 0) {
|
||||||
|
pw_print(to, pw);
|
||||||
|
done = 1;
|
||||||
|
} else {
|
||||||
|
snprintf(errbuf, errbufsz,
|
||||||
|
"%s: changes not made, no such entry", mpwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ferror(to)) {
|
||||||
|
snprintf(errbuf, errbufsz, "%s", strerror(errno));
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
(void)fclose(from);
|
||||||
|
(void)fclose(to);
|
||||||
|
|
||||||
|
return (done);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_error(const char *name, int error, int eval)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (name)
|
||||||
|
warn("%s", name);
|
||||||
|
else
|
||||||
|
warn(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
warnx("%s%s: unchanged", pw_prefix, _PATH_MASTERPASSWD);
|
||||||
|
pw_abort();
|
||||||
|
exit(eval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Removes head and/or tail spaces. */
|
||||||
|
static void
|
||||||
|
trim_whitespace(char *line)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
_DIAGASSERT(line != NULL);
|
||||||
|
|
||||||
|
/* Remove leading spaces */
|
||||||
|
p = line;
|
||||||
|
while (isspace((unsigned char) *p))
|
||||||
|
p++;
|
||||||
|
memmove(line, p, strlen(p) + 1);
|
||||||
|
|
||||||
|
/* Remove trailing spaces */
|
||||||
|
p = line + strlen(line) - 1;
|
||||||
|
while (isspace((unsigned char) *p))
|
||||||
|
p--;
|
||||||
|
*(p + 1) = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get one line, remove spaces from front and tail */
|
||||||
|
static int
|
||||||
|
read_line(FILE *fp, char *line, int max)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
_DIAGASSERT(fp != NULL);
|
||||||
|
_DIAGASSERT(line != NULL);
|
||||||
|
|
||||||
|
/* Read one line of config */
|
||||||
|
if (fgets(line, max, fp) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if ((p = strchr(line, '\n')) == NULL) {
|
||||||
|
warnx("line too long");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
/* Remove comments */
|
||||||
|
if ((p = strchr(line, '#')) != NULL)
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
trim_whitespace(line);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
pw_default(const char *option)
|
||||||
|
{
|
||||||
|
static const char *options[][2] = {
|
||||||
|
{ "localcipher", "old" },
|
||||||
|
{ "ypcipher", "old" },
|
||||||
|
};
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
_DIAGASSERT(option != NULL);
|
||||||
|
for (i = 0; i < sizeof(options) / sizeof(options[0]); i++)
|
||||||
|
if (strcmp(options[i][0], option) == 0)
|
||||||
|
return (options[i][1]);
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve password information from the /etc/passwd.conf file, at the
|
||||||
|
* moment this is only for choosing the cipher to use. It could easily be
|
||||||
|
* used for other authentication methods as well.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
pw_getconf(char *data, size_t max, const char *key, const char *option)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char line[LINE_MAX], *p, *p2;
|
||||||
|
static char result[LINE_MAX];
|
||||||
|
int got, found;
|
||||||
|
const char *cp;
|
||||||
|
|
||||||
|
_DIAGASSERT(data != NULL);
|
||||||
|
_DIAGASSERT(key != NULL);
|
||||||
|
_DIAGASSERT(option != NULL);
|
||||||
|
|
||||||
|
got = 0;
|
||||||
|
found = 0;
|
||||||
|
result[0] = '\0';
|
||||||
|
|
||||||
|
if ((fp = fopen(_PATH_PASSWD_CONF, "r")) == NULL) {
|
||||||
|
if ((cp = pw_default(option)) != NULL)
|
||||||
|
strlcpy(data, cp, max);
|
||||||
|
else
|
||||||
|
data[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!found && (got || read_line(fp, line, LINE_MAX))) {
|
||||||
|
got = 0;
|
||||||
|
|
||||||
|
if (strncmp(key, line, strlen(key)) != 0 ||
|
||||||
|
line[strlen(key)] != ':')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Now we found our specified key */
|
||||||
|
while (read_line(fp, line, LINE_MAX)) {
|
||||||
|
/* Leaving key field */
|
||||||
|
if (line[0] != '\0' && strchr(line + 1, ':') != NULL) {
|
||||||
|
got = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p2 = line;
|
||||||
|
if ((p = strsep(&p2, "=")) == NULL || p2 == NULL)
|
||||||
|
continue;
|
||||||
|
trim_whitespace(p);
|
||||||
|
|
||||||
|
if (!strncmp(p, option, strlen(option))) {
|
||||||
|
trim_whitespace(p2);
|
||||||
|
strcpy(result, p2);
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
errno = ENOENT;
|
||||||
|
if (!got)
|
||||||
|
errno = ENOTDIR;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we got no result and were looking for a default
|
||||||
|
* value, try hard coded defaults.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (strlen(result) == 0 && strcmp(key, "default") == 0 &&
|
||||||
|
(cp = pw_default(option)) != NULL)
|
||||||
|
strlcpy(data, cp, max);
|
||||||
|
else
|
||||||
|
strlcpy(data, result, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_getpwconf(char *data, size_t max, const struct passwd *pwd,
|
||||||
|
const char *option)
|
||||||
|
{
|
||||||
|
char grpkey[LINE_MAX];
|
||||||
|
struct group grs, *grp;
|
||||||
|
char grbuf[1024];
|
||||||
|
|
||||||
|
pw_getconf(data, max, pwd->pw_name, option);
|
||||||
|
|
||||||
|
/* Try to find an entry for the group */
|
||||||
|
if (*data == '\0') {
|
||||||
|
(void)getgrgid_r(pwd->pw_gid, &grs, grbuf, sizeof(grbuf), &grp);
|
||||||
|
if (grp != NULL) {
|
||||||
|
(void)snprintf(grpkey, sizeof(grpkey), ":%s",
|
||||||
|
grp->gr_name);
|
||||||
|
pw_getconf(data, max, grpkey, option);
|
||||||
|
}
|
||||||
|
if (*data == '\0')
|
||||||
|
pw_getconf(data, max, "default", option);
|
||||||
|
}
|
||||||
|
}
|
89
lib/libutil/pidfile.3
Normal file
89
lib/libutil/pidfile.3
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
.\" $NetBSD: pidfile.3,v 1.12 2010/05/05 22:05:31 wiz Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Jason R. Thorpe.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt PIDFILE 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pidfile
|
||||||
|
.Nd write a daemon pid file
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile "const char *basename"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Fn pidfile
|
||||||
|
writes a file containing the process ID of the program to the
|
||||||
|
.Pa /var/run
|
||||||
|
directory.
|
||||||
|
The file name has the form
|
||||||
|
.Pa /var/run/basename.pid .
|
||||||
|
If the
|
||||||
|
.Ar basename
|
||||||
|
argument is
|
||||||
|
.Dv NULL ,
|
||||||
|
.Fn pidfile
|
||||||
|
will determine the program name and use that instead.
|
||||||
|
.Pp
|
||||||
|
The pid file can be used as a quick reference if
|
||||||
|
the process needs to be sent a signal.
|
||||||
|
When the program exits, the pid file will be removed automatically, unless
|
||||||
|
the program receives a fatal signal.
|
||||||
|
.Pp
|
||||||
|
Note that only the first invocation of
|
||||||
|
.Fn pidfile
|
||||||
|
causes a pid file to be written; subsequent invocations have no effect
|
||||||
|
unless a new
|
||||||
|
.Ar basename
|
||||||
|
is supplied.
|
||||||
|
If called with a new
|
||||||
|
.Ar basename ,
|
||||||
|
.Fn pidfile
|
||||||
|
will remove the old pid file and write the new one.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn pidfile
|
||||||
|
returns 0 on success and -1 on failure.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr atexit 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn pidfile
|
||||||
|
function call appeared in
|
||||||
|
.Nx 1.5 .
|
||||||
|
.Sh BUGS
|
||||||
|
.Fn pidfile
|
||||||
|
uses
|
||||||
|
.Xr atexit 3
|
||||||
|
to ensure the pidfile is unlinked at program exit.
|
||||||
|
However, programs that use the
|
||||||
|
.Xr _exit 2
|
||||||
|
function (for example, in signal handlers)
|
||||||
|
will not trigger this behaviour.
|
120
lib/libutil/pidfile.c
Normal file
120
lib/libutil/pidfile.c
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/* $NetBSD: pidfile.c,v 1.8 2008/04/28 20:23:03 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Jason R. Thorpe and Matthias Scheler.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: pidfile.c,v 1.8 2008/04/28 20:23:03 martin Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
static int pidfile_atexit_done;
|
||||||
|
static pid_t pidfile_pid;
|
||||||
|
static char *pidfile_basename;
|
||||||
|
static char *pidfile_path;
|
||||||
|
|
||||||
|
static void pidfile_cleanup(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
pidfile(const char *basename)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register handler which will remove the pidfile later.
|
||||||
|
*/
|
||||||
|
if (!pidfile_atexit_done) {
|
||||||
|
if (atexit(pidfile_cleanup) < 0)
|
||||||
|
return -1;
|
||||||
|
pidfile_atexit_done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basename == NULL)
|
||||||
|
basename = getprogname();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If pidfile has already been created for the supplied basename
|
||||||
|
* we don't need to create a pidfile again.
|
||||||
|
*/
|
||||||
|
if (pidfile_path != NULL) {
|
||||||
|
if (strcmp(pidfile_basename, basename) == 0)
|
||||||
|
return 0;
|
||||||
|
/*
|
||||||
|
* Remove existing pidfile if it was created by this process.
|
||||||
|
*/
|
||||||
|
pidfile_cleanup();
|
||||||
|
|
||||||
|
free(pidfile_path);
|
||||||
|
pidfile_path = NULL;
|
||||||
|
free(pidfile_basename);
|
||||||
|
pidfile_basename = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pidfile_pid = getpid();
|
||||||
|
|
||||||
|
pidfile_basename = strdup(basename);
|
||||||
|
if (pidfile_basename == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* _PATH_VARRUN includes trailing / */
|
||||||
|
(void) asprintf(&pidfile_path, "%s%s.pid", _PATH_VARRUN, basename);
|
||||||
|
if (pidfile_path == NULL) {
|
||||||
|
free(pidfile_basename);
|
||||||
|
pidfile_basename = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((f = fopen(pidfile_path, "w")) == NULL) {
|
||||||
|
free(pidfile_path);
|
||||||
|
pidfile_path = NULL;
|
||||||
|
free(pidfile_basename);
|
||||||
|
pidfile_basename = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) fprintf(f, "%d\n", pidfile_pid);
|
||||||
|
(void) fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pidfile_cleanup(void)
|
||||||
|
{
|
||||||
|
/* Only remove the pidfile if it was created by this process. */
|
||||||
|
if ((pidfile_path != NULL) && (pidfile_pid == getpid()))
|
||||||
|
(void) unlink(pidfile_path);
|
||||||
|
}
|
184
lib/libutil/pidlock.3
Normal file
184
lib/libutil/pidlock.3
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
.\" $NetBSD: pidlock.3,v 1.12 2009/03/09 19:24:27 joerg Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright 1996, 1997 by Curt Sampson <cjs@NetBSD.org>
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd March 19, 2006
|
||||||
|
.Dt PIDLOCK 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pidlock ,
|
||||||
|
.Nm ttylock ,
|
||||||
|
.Nm ttyunlock
|
||||||
|
.Nd locks based on files containing PIDs
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn pidlock "const char *lockfile" "int flags" "pid_t *locker" "const char *info"
|
||||||
|
.Ft int
|
||||||
|
.Fn ttylock "const char *tty" "int flags" "pid_t *locker"
|
||||||
|
.Ft int
|
||||||
|
.Fn ttyunlock "const char *tty"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn pidlock
|
||||||
|
.Fn ttylock ,
|
||||||
|
and
|
||||||
|
.Fn ttyunlock
|
||||||
|
functions attempt to create a lockfile for an arbitrary resource that
|
||||||
|
only one program may hold at a time.
|
||||||
|
(In the case of
|
||||||
|
.Fn ttylock ,
|
||||||
|
this is access to a tty device.)
|
||||||
|
If the
|
||||||
|
function succeeds in creating the lockfile, it will succeed for
|
||||||
|
no other program calling it with the same lockfile until the original
|
||||||
|
calling program has removed the lockfile or exited.
|
||||||
|
The
|
||||||
|
.Fn ttyunlock
|
||||||
|
function will remove the lockfile created by
|
||||||
|
.Fn ttylock .
|
||||||
|
.Pp
|
||||||
|
These functions use the method of creating a lockfile traditionally
|
||||||
|
used by UUCP software.
|
||||||
|
This is described as follows in the documentation for Taylor UUCP:
|
||||||
|
.Bd -filled -offset indent
|
||||||
|
The lock file normally contains the process ID of the locking process.
|
||||||
|
This makes it easy to determine whether a lock is still valid.
|
||||||
|
The algorithm is to create a temporary file and then link
|
||||||
|
it to the name that must be locked.
|
||||||
|
If the link fails because a file with that name already exists,
|
||||||
|
the existing file is read to get the process ID.
|
||||||
|
If the process still exists, the lock attempt fails.
|
||||||
|
Otherwise the lock file is deleted and the locking algorithm
|
||||||
|
is retried.
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The PID is stored in ASCII format, with leading spaces to pad it
|
||||||
|
out to ten characters, and a terminating newline.
|
||||||
|
This implementation has been extended to put the hostname
|
||||||
|
on the second line of the file, terminated with a newline, and
|
||||||
|
optionally an arbitrary comment on the third line of the file, also
|
||||||
|
terminated with a newline.
|
||||||
|
If a comment is given, but
|
||||||
|
.Dv PIDLOCK_NONBLOCK
|
||||||
|
is not, a blank line will be written as the second line of the file.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidlock
|
||||||
|
function will attempt to create the file
|
||||||
|
.Fa lockfile
|
||||||
|
and put the current process's pid in it.
|
||||||
|
The
|
||||||
|
.Fn ttylock
|
||||||
|
function will do the same, but should be passed only the base name
|
||||||
|
(with no leading directory prefix) of the
|
||||||
|
.Fa tty
|
||||||
|
to be locked; it will test that the tty exists in
|
||||||
|
.Pa /dev
|
||||||
|
and is a character device, and then create
|
||||||
|
the file in the
|
||||||
|
.Pa /var/spool/lock
|
||||||
|
directory and prefix the filename with
|
||||||
|
.Pa LCK.. .
|
||||||
|
Use the
|
||||||
|
.Fn ttyunlock
|
||||||
|
function to remove this lock.
|
||||||
|
.Pp
|
||||||
|
The following flags may be passed in
|
||||||
|
.Pa flags :
|
||||||
|
.Bl -tag -width Dv -offset indent
|
||||||
|
.It Dv PIDLOCK_NONBLOCK
|
||||||
|
The function should return immediately when a lock is held by another
|
||||||
|
active process.
|
||||||
|
Otherwise the function will wait (forever, if necessary)
|
||||||
|
for the lock to be freed.
|
||||||
|
.It Dv PIDLOCK_USEHOSTNAME
|
||||||
|
The hostname should be compared against the hostname in the second
|
||||||
|
line of the file (if present), and if they differ, no attempt at
|
||||||
|
checking for a living process holding the lock will be made, and
|
||||||
|
the lockfile will never be deleted.
|
||||||
|
(The process is assumed to be alive.)
|
||||||
|
This is used for locking on NFS or other remote filesystems.
|
||||||
|
(The function will never create a lock if
|
||||||
|
.Dv PIDLOCK_USEHOSTNAME
|
||||||
|
is specified and no hostname is present.)
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Pa locker
|
||||||
|
is non-null, it will contain the PID of the locking process, if there
|
||||||
|
is one, on return.
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Pa info
|
||||||
|
is non-null and the lock succeeds, the string it points to will be
|
||||||
|
written as the third line of the lock file.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
Zero is returned if the operation was successful; on an error a -1
|
||||||
|
is returned and a standard error code is left in the global location
|
||||||
|
.Va errno .
|
||||||
|
.Sh ERRORS
|
||||||
|
In addition to the errors that are returned from
|
||||||
|
.Xr stat 2 ,
|
||||||
|
.Xr open 2 ,
|
||||||
|
.Xr read 2 ,
|
||||||
|
.Xr write 2 ,
|
||||||
|
and
|
||||||
|
.Xr link 2 ,
|
||||||
|
.Fn pidlock
|
||||||
|
or
|
||||||
|
.Fn ttylock
|
||||||
|
can set
|
||||||
|
.Va errno
|
||||||
|
to the following values on failure:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EWOULDBLOCK
|
||||||
|
Another running process has a lock and the
|
||||||
|
.Dv PIDLOCK_NONBLOCK
|
||||||
|
flag was specified.
|
||||||
|
.It Bq Er EFTYPE
|
||||||
|
The
|
||||||
|
.Fa tty
|
||||||
|
specified in
|
||||||
|
.Fn ttylock
|
||||||
|
is not a character special device.
|
||||||
|
.El
|
||||||
|
.\" .Sh SEE ALSO
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn pidlock
|
||||||
|
and
|
||||||
|
.Fn ttylock
|
||||||
|
functions appeared in
|
||||||
|
.Nx 1.3 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An Curt Sampson
|
||||||
|
.Aq cjs@NetBSD.org .
|
||||||
|
.Sh BUGS
|
||||||
|
The lockfile format breaks if a pid is longer than ten digits when
|
||||||
|
printed in decimal form.
|
||||||
|
.Pp
|
||||||
|
The PID returned will be the pid of the locker on the remote machine if
|
||||||
|
.Dv PIDLOCK_USEHOSTNAME
|
||||||
|
is specified, but there is no indication that this is not on the local
|
||||||
|
machine.
|
232
lib/libutil/pidlock.c
Normal file
232
lib/libutil/pidlock.c
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
/* $NetBSD: pidlock.c,v 1.15 2009/01/18 12:13:04 lukem Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 1996, 1997 by Curt Sampson <cjs@NetBSD.org>.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: pidlock.c,v 1.15 2009/01/18 12:13:04 lukem Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <paths.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a lockfile. Return 0 when locked, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
pidlock(const char *lockfile, int flags, pid_t *locker, const char *info)
|
||||||
|
{
|
||||||
|
char tempfile[MAXPATHLEN];
|
||||||
|
char hostname[MAXHOSTNAMELEN + 1];
|
||||||
|
pid_t pid2 = -1;
|
||||||
|
struct stat st;
|
||||||
|
int err;
|
||||||
|
int f = -1;
|
||||||
|
char s[256];
|
||||||
|
char *p;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
_DIAGASSERT(lockfile != NULL);
|
||||||
|
/* locker may be NULL */
|
||||||
|
/* info may be NULL */
|
||||||
|
|
||||||
|
|
||||||
|
if (gethostname(hostname, sizeof(hostname)))
|
||||||
|
return -1;
|
||||||
|
hostname[sizeof(hostname) - 1] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build a path to the temporary file.
|
||||||
|
* We use the path with the PID and hostname appended.
|
||||||
|
* XXX This is not thread safe.
|
||||||
|
*/
|
||||||
|
if (snprintf(tempfile, sizeof(tempfile), "%s.%d.%s", lockfile,
|
||||||
|
(int) getpid(), hostname) >= (int)sizeof(tempfile)) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open it, write pid, hostname, info. */
|
||||||
|
if ((f = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0600)) == -1)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
(void)snprintf(s, sizeof(s), "%10d\n", getpid()); /* pid */
|
||||||
|
if (write(f, s, (size_t)11) != 11)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if ((flags & PIDLOCK_USEHOSTNAME)) { /* hostname */
|
||||||
|
len = strlen(hostname);
|
||||||
|
if ((size_t)write(f, hostname, len) != len
|
||||||
|
|| write(f, "\n", (size_t)1) != 1)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (info) { /* info */
|
||||||
|
if (!(flags & PIDLOCK_USEHOSTNAME)) {
|
||||||
|
/* write blank line because there's no hostname */
|
||||||
|
if (write(f, "\n", (size_t)1) != 1)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
len = strlen(info);
|
||||||
|
if ((size_t)write(f, info, len) != len ||
|
||||||
|
write(f, "\n", (size_t)1) != 1)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
(void)close(f);
|
||||||
|
f = -1;
|
||||||
|
|
||||||
|
/* Hard link the temporary file to the real lock file. */
|
||||||
|
/* This is an atomic operation. */
|
||||||
|
lockfailed:
|
||||||
|
while (link(tempfile, lockfile) == -1) {
|
||||||
|
if (errno != EEXIST)
|
||||||
|
goto out;
|
||||||
|
/* Find out who has this lockfile. */
|
||||||
|
if ((f = open(lockfile, O_RDONLY, 0)) != -1) {
|
||||||
|
if ((err = read(f, s, (size_t)11)) == -1)
|
||||||
|
goto out;
|
||||||
|
if (err == 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
pid2 = atoi(s);
|
||||||
|
if ((err = read(f, s, sizeof(s) - 2)) == -1)
|
||||||
|
goto out;
|
||||||
|
if (err == 0)
|
||||||
|
*s = '\0';
|
||||||
|
s[sizeof(s) - 1] = '\0';
|
||||||
|
if ((p = strchr(s, '\n')) != NULL)
|
||||||
|
*p = '\0';
|
||||||
|
(void)close(f);
|
||||||
|
f = -1;
|
||||||
|
|
||||||
|
if ((flags & PIDLOCK_USEHOSTNAME) == 0 ||
|
||||||
|
strcmp(s, hostname) == 0) {
|
||||||
|
if (kill(pid2, 0) == -1 && errno == ESRCH) {
|
||||||
|
/* process doesn't exist */
|
||||||
|
(void)unlink(lockfile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flags & PIDLOCK_NONBLOCK) {
|
||||||
|
if (locker)
|
||||||
|
*locker = pid2;
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
goto out;
|
||||||
|
} else
|
||||||
|
sleep(5);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Check to see that we really were successful (in case we're
|
||||||
|
* using NFS) by making sure that something really is linked
|
||||||
|
* to our tempfile (reference count is two).
|
||||||
|
*/
|
||||||
|
if (stat(tempfile, &st) == -1)
|
||||||
|
goto out;
|
||||||
|
if (st.st_nlink != 2)
|
||||||
|
goto lockfailed;
|
||||||
|
|
||||||
|
(void)unlink(tempfile);
|
||||||
|
if (locker)
|
||||||
|
*locker = getpid(); /* return this process's PID on lock */
|
||||||
|
errno = 0;
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
err = errno;
|
||||||
|
if (f != -1)
|
||||||
|
(void)close(f);
|
||||||
|
(void)unlink(tempfile);
|
||||||
|
errno = err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
checktty(const char *tty)
|
||||||
|
{
|
||||||
|
char ttyfile[MAXPATHLEN];
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
(void)strlcpy(ttyfile, _PATH_DEV, sizeof(ttyfile));
|
||||||
|
(void)strlcat(ttyfile, tty, sizeof(ttyfile));
|
||||||
|
|
||||||
|
/* make sure the tty exists */
|
||||||
|
if (stat(ttyfile, &sb) == -1)
|
||||||
|
return -1;
|
||||||
|
if (!S_ISCHR(sb.st_mode)) {
|
||||||
|
errno = EFTYPE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOCKPATH "/var/spool/lock/LCK.."
|
||||||
|
|
||||||
|
static char *
|
||||||
|
makelock(char *buf, size_t bufsiz, const char *tty)
|
||||||
|
{
|
||||||
|
(void)strlcpy(buf, LOCKPATH, bufsiz);
|
||||||
|
(void)strlcat(buf, tty, bufsiz);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
ttylock(const char *tty, int flags, pid_t *locker)
|
||||||
|
{
|
||||||
|
char lockfile[MAXPATHLEN];
|
||||||
|
|
||||||
|
_DIAGASSERT(tty != NULL);
|
||||||
|
|
||||||
|
if (checktty(tty) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* do the lock */
|
||||||
|
return pidlock(makelock(lockfile, sizeof(lockfile), tty),
|
||||||
|
flags, locker, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ttyunlock(const char *tty)
|
||||||
|
{
|
||||||
|
char lockfile[MAXPATHLEN];
|
||||||
|
|
||||||
|
_DIAGASSERT(tty != NULL);
|
||||||
|
|
||||||
|
if (checktty(tty) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* remove the lock */
|
||||||
|
return unlink(makelock(lockfile, sizeof(lockfile), tty));
|
||||||
|
}
|
170
lib/libutil/pty.c
Normal file
170
lib/libutil/pty.c
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
/* $NetBSD: pty.c,v 1.31 2009/02/20 16:44:06 christos Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)pty.c 8.3 (Berkeley) 5/16/94";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: pty.c,v 1.31 2009/02/20 16:44:06 christos Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: `v' removed until no ports are using console devices which use ttyv0
|
||||||
|
*/
|
||||||
|
#define TTY_LETTERS "pqrstuwxyzPQRST"
|
||||||
|
#define TTY_OLD_SUFFIX "0123456789abcdef"
|
||||||
|
#define TTY_NEW_SUFFIX "ghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
int
|
||||||
|
openpty(int *amaster, int *aslave, char *name, struct termios *term,
|
||||||
|
struct winsize *winp)
|
||||||
|
{
|
||||||
|
char line[] = "/dev/XtyXX";
|
||||||
|
const char *cp1, *cp2, *cp, *linep;
|
||||||
|
int master, slave;
|
||||||
|
gid_t ttygid;
|
||||||
|
mode_t mode;
|
||||||
|
struct group grs, *grp;
|
||||||
|
char grbuf[1024];
|
||||||
|
|
||||||
|
_DIAGASSERT(amaster != NULL);
|
||||||
|
_DIAGASSERT(aslave != NULL);
|
||||||
|
/* name may be NULL */
|
||||||
|
/* term may be NULL */
|
||||||
|
/* winp may be NULL */
|
||||||
|
|
||||||
|
#ifndef __minix
|
||||||
|
if ((master = open("/dev/ptm", O_RDWR)) != -1) {
|
||||||
|
struct ptmget pt;
|
||||||
|
if (ioctl(master, TIOCPTMGET, &pt) != -1) {
|
||||||
|
(void)close(master);
|
||||||
|
master = pt.cfd;
|
||||||
|
slave = pt.sfd;
|
||||||
|
linep = pt.sn;
|
||||||
|
goto gotit;
|
||||||
|
}
|
||||||
|
(void)close(master);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void)getgrnam_r("tty", &grs, grbuf, sizeof(grbuf), &grp);
|
||||||
|
if (grp != NULL) {
|
||||||
|
ttygid = grp->gr_gid;
|
||||||
|
mode = S_IRUSR|S_IWUSR|S_IWGRP;
|
||||||
|
} else {
|
||||||
|
ttygid = getgid();
|
||||||
|
mode = S_IRUSR|S_IWUSR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cp1 = TTY_LETTERS; *cp1; cp1++) {
|
||||||
|
line[8] = *cp1;
|
||||||
|
for (cp = cp2 = TTY_OLD_SUFFIX TTY_NEW_SUFFIX; *cp2; cp2++) {
|
||||||
|
line[5] = 'p';
|
||||||
|
line[9] = *cp2;
|
||||||
|
if ((master = open(line, O_RDWR, 0)) == -1) {
|
||||||
|
if (errno != ENOENT)
|
||||||
|
continue; /* busy */
|
||||||
|
if ((size_t)(cp2 - cp + 1) < sizeof(TTY_OLD_SUFFIX))
|
||||||
|
return -1; /* out of ptys */
|
||||||
|
else
|
||||||
|
break; /* out of ptys in this group */
|
||||||
|
}
|
||||||
|
line[5] = 't';
|
||||||
|
linep = line;
|
||||||
|
if (chown(line, getuid(), ttygid) == 0 &&
|
||||||
|
chmod(line, mode) == 0 &&
|
||||||
|
revoke(line) == 0 &&
|
||||||
|
(slave = open(line, O_RDWR, 0)) != -1) {
|
||||||
|
gotit:
|
||||||
|
*amaster = master;
|
||||||
|
*aslave = slave;
|
||||||
|
if (name)
|
||||||
|
(void)strcpy(name, linep);
|
||||||
|
if (term)
|
||||||
|
(void)tcsetattr(slave, TCSAFLUSH, term);
|
||||||
|
if (winp)
|
||||||
|
(void)ioctl(slave, TIOCSWINSZ, winp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
(void)close(master);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errno = ENOENT; /* out of ptys */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
forkpty(int *amaster, char *name, struct termios *term, struct winsize *winp)
|
||||||
|
{
|
||||||
|
int master, slave;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
_DIAGASSERT(amaster != NULL);
|
||||||
|
/* name may be NULL */
|
||||||
|
/* term may be NULL */
|
||||||
|
/* winp may be NULL */
|
||||||
|
|
||||||
|
if (openpty(&master, &slave, name, term, winp) == -1)
|
||||||
|
return -1;
|
||||||
|
switch (pid = fork()) {
|
||||||
|
case -1:
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
/*
|
||||||
|
* child
|
||||||
|
*/
|
||||||
|
(void)close(master);
|
||||||
|
login_tty(slave);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* parent
|
||||||
|
*/
|
||||||
|
*amaster = master;
|
||||||
|
(void)close(slave);
|
||||||
|
return pid;
|
||||||
|
}
|
114
lib/libutil/pw_getconf.3
Normal file
114
lib/libutil/pw_getconf.3
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
.\" $NetBSD: pw_getconf.3,v 1.12 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\" This product includes software developed by Niels Provos.
|
||||||
|
.\" 4. The name of the author may not be used to endorse or promote products
|
||||||
|
.\" derived from this software without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" from OpenBSD: pw_getconf.3,v 1.5 1999/09/21 04:52:46 csapuntz Exp
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt PW_GETCONF 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pw_getconf ,
|
||||||
|
.Nm pw_getpwconf
|
||||||
|
.Nd password encryption configuration access function
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_getconf "char *data" "size_t len" "const char *key" "const char *option"
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_getpwconf "char *data" "size_t len" "const struct passwd *pwd" "const char *option"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn pw_getconf
|
||||||
|
function reads
|
||||||
|
.Pa /etc/passwd.conf
|
||||||
|
and retrieves the value of the option specified
|
||||||
|
by
|
||||||
|
.Pa option
|
||||||
|
from the section given by
|
||||||
|
.Pa key .
|
||||||
|
If no suitable entry is found
|
||||||
|
for the
|
||||||
|
.Pa key
|
||||||
|
an empty string will be returned in data.
|
||||||
|
.Pp
|
||||||
|
To retrieve default values the key
|
||||||
|
.Pa default
|
||||||
|
can be used.
|
||||||
|
In this case, if
|
||||||
|
.Pa /etc/passwd.conf
|
||||||
|
does not exist or does not contain a
|
||||||
|
.Pa default
|
||||||
|
section, the built-in defaults will be returned.
|
||||||
|
They are as follows:
|
||||||
|
.Bl -column localcipher data -offset indent
|
||||||
|
.It Sy option data
|
||||||
|
.It ypcipher old
|
||||||
|
.It localcipher old
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
An empty string is returned for all errors.
|
||||||
|
.Pp
|
||||||
|
.Fn pw_getpwconf
|
||||||
|
returns the value for the option specified for the particular user
|
||||||
|
specified in
|
||||||
|
.Ar pwd .
|
||||||
|
If that option is not found, then it tries to find the option in
|
||||||
|
the primary group of that user, and if that fails, then it returns
|
||||||
|
the default entry.
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /etc/passwd.conf -compact
|
||||||
|
.It Pa /etc/passwd.conf
|
||||||
|
.El
|
||||||
|
.Sh ERRORS
|
||||||
|
.Fn pw_getconf
|
||||||
|
and
|
||||||
|
.Fn pw_getpwconf
|
||||||
|
will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er ENOENT
|
||||||
|
There is no option named
|
||||||
|
.Pa option
|
||||||
|
in the specified key.
|
||||||
|
.It Bq Er ENOTDIR
|
||||||
|
There is no key in
|
||||||
|
.Pa /etc/passwd.conf
|
||||||
|
named
|
||||||
|
.Pa key .
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr passwd 5 ,
|
||||||
|
.Xr passwd.conf 5
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn pw_getconf
|
||||||
|
function first appeared in
|
||||||
|
.Nx 1.6 .
|
229
lib/libutil/pw_init.3
Normal file
229
lib/libutil/pw_init.3
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
.\" $NetBSD: pw_init.3,v 1.15 2010/05/05 22:05:31 wiz Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1995
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software developed by the Computer Systems
|
||||||
|
.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract
|
||||||
|
.\" BG 91-66 and contributed to Berkeley.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd August 1, 2004
|
||||||
|
.Dt PW_INIT 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pw_init ,
|
||||||
|
.Nm pw_edit ,
|
||||||
|
.Nm pw_prompt ,
|
||||||
|
.Nm pw_copy ,
|
||||||
|
.Nm pw_copyx ,
|
||||||
|
.Nm pw_scan ,
|
||||||
|
.Nm pw_error
|
||||||
|
.Nd utility functions for interactive passwd file updates
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In pwd.h
|
||||||
|
.In util.h
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_init "void"
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_edit "int notsetuid" "const char *filename"
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_prompt "void"
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_copy "int ffd" "int tfd" "struct passwd *pw" "struct passwd *old_pw"
|
||||||
|
.Ft int
|
||||||
|
.Fn pw_copyx "int ffd" "int tfd" "struct passwd *pw" "struct passwd *old_pw" \
|
||||||
|
"char *errbuf" "size_t errbufsz"
|
||||||
|
.Ft int
|
||||||
|
.Fn pw_scan "char *bp" "struct passwd *pw" "int *flags"
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_error "const char *name" "int err" "int eval"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
These functions are designed as conveniences for interactive programs
|
||||||
|
which update the passwd file and do nothing else.
|
||||||
|
They generally handle errors by printing out a message to the standard error
|
||||||
|
stream and possibly aborting the process.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_init
|
||||||
|
function prepares for a passwd update by unlimiting all resource
|
||||||
|
constraints, disabling core dumps (thus preventing dumping the
|
||||||
|
contents of the passwd database into a world-readable file), and
|
||||||
|
disabling most signals.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_edit
|
||||||
|
function runs an editor (named by the environment variable EDITOR, or
|
||||||
|
.Pa /usr/bin/vi
|
||||||
|
if EDITOR is not set) on the file
|
||||||
|
.Fa filename
|
||||||
|
(or
|
||||||
|
.Pa /etc/ptmp
|
||||||
|
if
|
||||||
|
.Fa filename
|
||||||
|
is
|
||||||
|
.Dv NULL ) .
|
||||||
|
If
|
||||||
|
.Fa notsetuid
|
||||||
|
is nonzero,
|
||||||
|
.Fn pw_edit
|
||||||
|
will set the effective user and group ID to the real user and group ID
|
||||||
|
before running the editor.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_prompt
|
||||||
|
function asks the user whether he or she wants to re-edit the password
|
||||||
|
file; if the answer is no,
|
||||||
|
.Fn pw_prompt
|
||||||
|
deletes the lock file and exits the process.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_copy
|
||||||
|
function reads a passwd file from
|
||||||
|
.Fa ffd
|
||||||
|
and writes it to
|
||||||
|
.Fa tfd ,
|
||||||
|
updating the entry corresponding to pw-\*[Gt]pw_name with the information
|
||||||
|
in
|
||||||
|
.Fa pw .
|
||||||
|
If
|
||||||
|
.Fa old_pw
|
||||||
|
is not
|
||||||
|
.Dv NULL ,
|
||||||
|
it checks to make sure the old entry is the same as
|
||||||
|
the one described in
|
||||||
|
.Fa old_pw
|
||||||
|
or the process is aborted.
|
||||||
|
If an entry is not found to match
|
||||||
|
.Fa pw ,
|
||||||
|
a new entry is appended to the passwd file only if the real user
|
||||||
|
ID is 0.
|
||||||
|
If an error occurs,
|
||||||
|
.Fn pw_copy
|
||||||
|
will display a message on
|
||||||
|
.Dv stderr
|
||||||
|
and call
|
||||||
|
.Fn pw_error .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_copyx
|
||||||
|
function performs the same operation as
|
||||||
|
.Fn pw_copy
|
||||||
|
with the exception of error handling.
|
||||||
|
Upon an error,
|
||||||
|
.Fn pw_copyx
|
||||||
|
will write an error message into the buffer pointed to by
|
||||||
|
.Fa errbuf
|
||||||
|
which has the size
|
||||||
|
.Fa errbufsz .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_scan
|
||||||
|
function accepts in
|
||||||
|
.Fa bp
|
||||||
|
a passwd entry as it would be represented in
|
||||||
|
.Pa /etc/master.passwd
|
||||||
|
and fills in
|
||||||
|
.Fa pw
|
||||||
|
with corresponding values; string fields in
|
||||||
|
.Fa pw
|
||||||
|
will be pointers into
|
||||||
|
.Fa bp .
|
||||||
|
Some characters in
|
||||||
|
.Fa bp
|
||||||
|
will be overwritten with 0s in order to terminate the strings pointed
|
||||||
|
to by
|
||||||
|
.Fa pw .
|
||||||
|
If
|
||||||
|
.Fa flags
|
||||||
|
is non-null, it should be cleared and the following options
|
||||||
|
enabled if required:
|
||||||
|
.Bl -tag -offset indent -width _PASSWORD_OLDFMT
|
||||||
|
.It Dv _PASSWORD_NOWARN
|
||||||
|
Don't print warnings.
|
||||||
|
.It Dv _PASSWORD_OLDFMT
|
||||||
|
Parse
|
||||||
|
.Fa bp
|
||||||
|
as an old format entry as found in
|
||||||
|
.Pa /etc/passwd .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Upon return it is cleared, and filled in with the following flags:
|
||||||
|
.Bl -tag -offset indent -width _PASSWORD_NOGID
|
||||||
|
.It Dv _PASSWORD_NOUID
|
||||||
|
The uid field of
|
||||||
|
.Fa bp
|
||||||
|
is empty.
|
||||||
|
.It Dv _PASSWORD_NOGID
|
||||||
|
The gid field of
|
||||||
|
.Fa bp
|
||||||
|
is empty.
|
||||||
|
.It Dv _PASSWORD_NOCHG
|
||||||
|
The change field of
|
||||||
|
.Fa bp
|
||||||
|
is empty.
|
||||||
|
.It Dv _PASSWORD_NOEXP
|
||||||
|
The expire field of
|
||||||
|
.Fa bp
|
||||||
|
is empty.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_error
|
||||||
|
function displays an error message, aborts the current passwd update,
|
||||||
|
and exits the current process.
|
||||||
|
If
|
||||||
|
.Fa err
|
||||||
|
is non-zero, a warning message beginning with
|
||||||
|
.Fa name
|
||||||
|
is printed for the current value of
|
||||||
|
.Va errno .
|
||||||
|
The process exits with status
|
||||||
|
.Fa eval .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn pw_copyx
|
||||||
|
function returns 1 if the new password entry was successfully written
|
||||||
|
to the destination file, and 0 otherwise.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_scan
|
||||||
|
function prints a warning message and returns 0 if the string in the
|
||||||
|
.Fa bp
|
||||||
|
argument is not a valid passwd string.
|
||||||
|
Otherwise,
|
||||||
|
.Fn pw_scan
|
||||||
|
returns 1.
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /etc/master.passwd -compact
|
||||||
|
.It Pa /etc/master.passwd
|
||||||
|
.It Pa /etc/ptmp
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr pw_lock 3 ,
|
||||||
|
.Xr passwd 5
|
139
lib/libutil/pw_lock.3
Normal file
139
lib/libutil/pw_lock.3
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
.\" $NetBSD: pw_lock.3,v 1.14 2010/05/05 22:05:31 wiz Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1995
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software developed by the Computer Systems
|
||||||
|
.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract
|
||||||
|
.\" BG 91-66 and contributed to Berkeley.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd February 17, 2007
|
||||||
|
.Dt PW_LOCK 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pw_lock ,
|
||||||
|
.Nm pw_mkdb ,
|
||||||
|
.Nm pw_abort ,
|
||||||
|
.Nm pw_setprefix ,
|
||||||
|
.Nm pw_getprefix
|
||||||
|
.Nd passwd file update functions
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn pw_lock "int retries"
|
||||||
|
.Ft int
|
||||||
|
.Fn pw_mkdb "const char *username" "int secureonly"
|
||||||
|
.Ft void
|
||||||
|
.Fn pw_abort "void"
|
||||||
|
.Ft int
|
||||||
|
.Fn pw_setprefix "const char *new_prefix"
|
||||||
|
.Ft "const char *"
|
||||||
|
.Fn pw_getprefix "void"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn pw_lock ,
|
||||||
|
.Fn pw_mkdb ,
|
||||||
|
and
|
||||||
|
.Fn pw_abort
|
||||||
|
functions allow a program to update the system passwd database.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_lock
|
||||||
|
function attempts to lock the passwd database by creating the file
|
||||||
|
.Pa /etc/ptmp ,
|
||||||
|
and returns the file descriptor of that file.
|
||||||
|
If
|
||||||
|
.Fa retries
|
||||||
|
is greater than zero,
|
||||||
|
.Fn pw_lock
|
||||||
|
will try multiple times to open
|
||||||
|
.Pa /etc/ptmp ,
|
||||||
|
waiting one second between tries.
|
||||||
|
In addition to being a lock file,
|
||||||
|
.Pa /etc/ptmp
|
||||||
|
will also hold the contents of the new passwd file.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_mkdb
|
||||||
|
function updates the passwd file from the contents of
|
||||||
|
.Pa /etc/ptmp .
|
||||||
|
You should finish writing to and close the file descriptor returned by
|
||||||
|
.Fn pw_lock
|
||||||
|
before calling
|
||||||
|
.Fn pw_mkdb .
|
||||||
|
If
|
||||||
|
.Fn pw_mkdb
|
||||||
|
fails and you do not wish to retry, you should make sure to call
|
||||||
|
.Fn pw_abort
|
||||||
|
to clean up the lock file.
|
||||||
|
If the
|
||||||
|
.Ar username
|
||||||
|
argument is not
|
||||||
|
.Dv NULL ,
|
||||||
|
only database entries pertaining to the specified user
|
||||||
|
will be modified.
|
||||||
|
If the
|
||||||
|
.Ar secureonly
|
||||||
|
argument is non-zero, only the secure database will be updated.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_abort
|
||||||
|
function aborts a passwd file update by deleting
|
||||||
|
.Pa /etc/ptmp .
|
||||||
|
The passwd database remains unchanged.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_setprefix
|
||||||
|
function defines the root directory used for passwd file updates.
|
||||||
|
If the prefix is set to
|
||||||
|
.Pa /newroot
|
||||||
|
.Fn pw_lock
|
||||||
|
will operate on
|
||||||
|
.Pa /newroot/etc/ptmp
|
||||||
|
afterwards.
|
||||||
|
The default prefix is an empty string.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pw_getprefix
|
||||||
|
function returns the root directory which is currently used for passwd file
|
||||||
|
updates.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn pw_lock
|
||||||
|
and
|
||||||
|
.Fn pw_mkdb
|
||||||
|
functions return -1 if they are unable to complete properly.
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /etc/master.passwd -compact
|
||||||
|
.It Pa /etc/master.passwd
|
||||||
|
.It Pa /etc/ptmp
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr pw_init 3 ,
|
||||||
|
.Xr pwd_mkdb 8
|
116
lib/libutil/raise_default_signal.3
Normal file
116
lib/libutil/raise_default_signal.3
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
.\" $NetBSD: raise_default_signal.3,v 1.2 2008/04/30 13:10:52 martin Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Luke Mewburn.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd September 25, 2007
|
||||||
|
.Dt RAISE_DEFAULT_SIGNAL 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm raise_default_signal
|
||||||
|
.Nd raise the default signal handler
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fo raise_default_signal
|
||||||
|
.Fa "int sig"
|
||||||
|
.Fc
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn raise_default_signal
|
||||||
|
function raises the default signal handler for the signal
|
||||||
|
.Fa sig .
|
||||||
|
This function may be used by a user-defined signal handler router
|
||||||
|
to ensure that a parent process receives the correct notification
|
||||||
|
of a process termination by a signal.
|
||||||
|
This can be used to avoid a common programming mistake
|
||||||
|
when terminating a process from a custom
|
||||||
|
.Dv SIGINT
|
||||||
|
or
|
||||||
|
.Dv SIGQUIT
|
||||||
|
signal handler.
|
||||||
|
.Pp
|
||||||
|
The operations performed are:
|
||||||
|
.Bl -enum -offset indent
|
||||||
|
.It
|
||||||
|
Block all signals, using
|
||||||
|
.Xr sigprocmask 3 .
|
||||||
|
.It
|
||||||
|
Set the signal handler for signal
|
||||||
|
.Fa sig
|
||||||
|
to the default signal handler
|
||||||
|
.Dv ( SIG_DFL ) .
|
||||||
|
.It
|
||||||
|
.Xr raise 3
|
||||||
|
signal
|
||||||
|
.Fa sig .
|
||||||
|
.It
|
||||||
|
Unblock signal
|
||||||
|
.Fa sig
|
||||||
|
to deliver it.
|
||||||
|
.It
|
||||||
|
Restore the original signal mask and handler,
|
||||||
|
even if there was a failure.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
See
|
||||||
|
.Xr signal 7
|
||||||
|
for a table of signals and default actions.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn raise_default_signal
|
||||||
|
function should be async-signal-safe.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
Upon successful completion, a value of 0 is returned.
|
||||||
|
Otherwise, a value of \-1 is returned and the global variable
|
||||||
|
.Va errno
|
||||||
|
is set to indicate the error.
|
||||||
|
.Sh ERRORS
|
||||||
|
The
|
||||||
|
.Fn raise_default_signal
|
||||||
|
function may fail and set
|
||||||
|
.Va errno
|
||||||
|
for any of the errors specified for the functions
|
||||||
|
.Xr sigemptyset 3 ,
|
||||||
|
.Xr sigfillset 3 ,
|
||||||
|
.Xr sigaddset 3 ,
|
||||||
|
.Xr sigprocmask 2 ,
|
||||||
|
.Xr sigaction 2 ,
|
||||||
|
or
|
||||||
|
.Xr raise 3 .
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr sigaction 2 ,
|
||||||
|
.Xr sigprocmask 2 ,
|
||||||
|
.Xr raise 3 ,
|
||||||
|
.Xr signal 7
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn raise_default_signal
|
||||||
|
function first appeared in
|
||||||
|
.Nx 5.0 .
|
117
lib/libutil/raise_default_signal.c
Normal file
117
lib/libutil/raise_default_signal.c
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/* $NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Luke Mewburn.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_NBTOOL_CONFIG_H
|
||||||
|
#include "nbtool_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: raise_default_signal.c,v 1.3 2008/04/28 20:23:03 martin Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
#if ! HAVE_RAISE_DEFAULT_SIGNAL
|
||||||
|
/*
|
||||||
|
* raise_default_signal sig
|
||||||
|
* Raise the default signal handler for sig, by
|
||||||
|
* - block all signals
|
||||||
|
* - set the signal handler to SIG_DFL
|
||||||
|
* - raise the signal
|
||||||
|
* - unblock the signal to deliver it
|
||||||
|
*
|
||||||
|
* The original signal mask and signal handler is restored on exit
|
||||||
|
* (whether successful or not).
|
||||||
|
*
|
||||||
|
* Returns 0 on success, or -1 on failure with errno set to
|
||||||
|
* on of the values for sigemptyset(), sigaddset(), sigprocmask(),
|
||||||
|
* sigaction(), or raise().
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
raise_default_signal(int sig)
|
||||||
|
{
|
||||||
|
struct sigaction origact, act;
|
||||||
|
sigset_t origmask, fullmask, mask;
|
||||||
|
int retval, oerrno;
|
||||||
|
|
||||||
|
retval = -1;
|
||||||
|
|
||||||
|
/* Setup data structures */
|
||||||
|
/* XXX memset(3) isn't async-safe according to signal(7) */
|
||||||
|
(void)memset(&act, 0, sizeof(act));
|
||||||
|
act.sa_handler = SIG_DFL;
|
||||||
|
act.sa_flags = 0;
|
||||||
|
if ((sigemptyset(&act.sa_mask) == -1) ||
|
||||||
|
(sigfillset(&fullmask) == -1) ||
|
||||||
|
(sigemptyset(&mask) == -1) ||
|
||||||
|
(sigaddset(&mask, sig) == -1))
|
||||||
|
goto restore_none;
|
||||||
|
|
||||||
|
/* Block all signals */
|
||||||
|
if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1)
|
||||||
|
goto restore_none;
|
||||||
|
/* (use 'goto restore_mask' to restore state) */
|
||||||
|
|
||||||
|
/* Enable the SIG_DFL handler */
|
||||||
|
if (sigaction(sig, &act, &origact) == -1)
|
||||||
|
goto restore_mask;
|
||||||
|
/* (use 'goto restore_act' to restore state) */
|
||||||
|
|
||||||
|
/* Raise the signal, and unblock the signal to deliver it */
|
||||||
|
if ((raise(sig) == -1) ||
|
||||||
|
(sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1))
|
||||||
|
goto restore_act;
|
||||||
|
|
||||||
|
/* Flag successful raise() */
|
||||||
|
retval = 0;
|
||||||
|
|
||||||
|
/* Restore the original handler */
|
||||||
|
restore_act:
|
||||||
|
oerrno = errno;
|
||||||
|
(void)sigaction(sig, &origact, NULL);
|
||||||
|
errno = oerrno;
|
||||||
|
|
||||||
|
/* Restore the original mask */
|
||||||
|
restore_mask:
|
||||||
|
oerrno = errno;
|
||||||
|
(void)sigprocmask(SIG_SETMASK, &origmask, NULL);
|
||||||
|
errno = oerrno;
|
||||||
|
|
||||||
|
restore_none:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ! HAVE_RAISE_DEFAULT_SIGNAL */
|
71
lib/libutil/secure_path.3
Normal file
71
lib/libutil/secure_path.3
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
.\" $NetBSD: secure_path.3,v 1.10 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1996,1997 Berkeley Software Design, Inc. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\" This product includes software developed by Berkeley Software Design,
|
||||||
|
.\" Inc.
|
||||||
|
.\" 4. The name of Berkeley Software Design, Inc. may not be used to endorse
|
||||||
|
.\" or promote products derived from this software without specific prior
|
||||||
|
.\" written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" from BSDI: login_cap.3,v 1.4 1997/11/07 16:22:27 jch Exp
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt SECURE_PATH 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm secure_path
|
||||||
|
.Nd determine if a file appears to be ``secure''
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn secure_path "const char *path"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn secure_path
|
||||||
|
function takes a path name and returns zero if the referenced file is
|
||||||
|
.Dq secure ,
|
||||||
|
non-zero if not.
|
||||||
|
Any
|
||||||
|
.Dq insecurity ,
|
||||||
|
other than failure to access
|
||||||
|
the referenced file, will be logged to the system log.
|
||||||
|
.Pp
|
||||||
|
To be
|
||||||
|
.Dq secure ,
|
||||||
|
the referenced file must exist, be a regular file (and not a
|
||||||
|
directory), owned by the super-user, and writable only by the super-user.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr openlog 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn secure_path
|
||||||
|
function is based on the
|
||||||
|
.Bsx
|
||||||
|
implementation of same, and appeared in
|
||||||
|
.Nx 1.5
|
||||||
|
by kind permission.
|
72
lib/libutil/secure_path.c
Normal file
72
lib/libutil/secure_path.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/* $NetBSD: secure_path.c,v 1.2 2003/01/06 20:30:30 wiz Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1995,1997 Berkeley Software Design, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Berkeley Software Design,
|
||||||
|
* Inc.
|
||||||
|
* 4. The name of Berkeley Software Design, Inc. may not be used to endorse
|
||||||
|
* or promote products derived from this software without specific prior
|
||||||
|
* written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* BSDI login_cap.c,v 2.13 1998/02/07 03:17:05 prb Exp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: secure_path.c,v 1.2 2003/01/06 20:30:30 wiz Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
secure_path(const char *path)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
_DIAGASSERT(path != NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If not a regular file, or is owned/writable by someone
|
||||||
|
* other than root, quit.
|
||||||
|
*/
|
||||||
|
if (lstat(path, &sb) < 0)
|
||||||
|
/* syslog(LOG_ERR, "cannot stat %s: %m", path) */;
|
||||||
|
else if (!S_ISREG(sb.st_mode))
|
||||||
|
syslog(LOG_ERR, "%s: not a regular file", path);
|
||||||
|
else if (sb.st_uid != 0)
|
||||||
|
syslog(LOG_ERR, "%s: not owned by root", path);
|
||||||
|
else if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|
||||||
|
syslog(LOG_ERR, "%s: writable by non-root", path);
|
||||||
|
else
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
return (-1);
|
||||||
|
}
|
5
lib/libutil/shlib_version
Normal file
5
lib/libutil/shlib_version
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# $NetBSD: shlib_version,v 1.47 2009/05/13 02:50:32 pgoyette Exp $
|
||||||
|
# Remember to update distrib/sets/lists/base/shl.* when changing
|
||||||
|
#
|
||||||
|
major=7
|
||||||
|
minor=17
|
279
lib/libutil/snprintb.3
Normal file
279
lib/libutil/snprintb.3
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
.\" $NetBSD: snprintb.3,v 1.14 2009/05/13 02:50:32 pgoyette Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Jeremy Cooper.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 7, 2009
|
||||||
|
.Dt SNPRINTB 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm snprintb
|
||||||
|
.Nd bitmask output conversion
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn "snprintb" "char *buf" "size_t buflen" "const char *fmt" "uint64_t val"
|
||||||
|
.Ft int
|
||||||
|
.Fn "snprintb_m" "char *buf" "size_t buflen" "const char *fmt" "uint64_t val" \
|
||||||
|
"size_t max"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn snprintb
|
||||||
|
function formats a bitmask into a mnemonic form suitable for printing.
|
||||||
|
.Pp
|
||||||
|
This conversion is useful for decoding bit fields in device registers.
|
||||||
|
It formats the integer
|
||||||
|
.Fa val
|
||||||
|
into the buffer
|
||||||
|
.Fa buf ,
|
||||||
|
of size
|
||||||
|
.Fa buflen ,
|
||||||
|
using a specified radix and an interpretation of
|
||||||
|
the bits within that integer as though they were flags.
|
||||||
|
The buffer is always NUL-terminated.
|
||||||
|
If the buffer
|
||||||
|
.Fa buf
|
||||||
|
is too small to hold the formatted output,
|
||||||
|
.Fn snprintb
|
||||||
|
will fill as much as it can, and return the number of bytes
|
||||||
|
that would have written if the buffer was long enough excluding the
|
||||||
|
terminating NUL.
|
||||||
|
.Pp
|
||||||
|
The decoding directive string
|
||||||
|
.Fa fmt
|
||||||
|
describes how the bitfield is to be interpreted and displayed.
|
||||||
|
It follows two possible syntaxes, referred to as
|
||||||
|
.Dq old
|
||||||
|
and
|
||||||
|
.Dq new .
|
||||||
|
The main advantage of the
|
||||||
|
.Dq new
|
||||||
|
formatting is that it is capable of handling multi-bit fields.
|
||||||
|
.Pp
|
||||||
|
The first character of
|
||||||
|
.Fa fmt
|
||||||
|
may be
|
||||||
|
.Li \e177 ,
|
||||||
|
indicating that the remainder of the format string follows the
|
||||||
|
.Dq new
|
||||||
|
syntax.
|
||||||
|
The second character
|
||||||
|
.Pq the first for the old format
|
||||||
|
is a binary character representation of the
|
||||||
|
output numeral base in which the bitfield will be printed before it is decoded.
|
||||||
|
Recognized radix values
|
||||||
|
.Pq in C escape-character format
|
||||||
|
are
|
||||||
|
.Li \e10
|
||||||
|
.Pq octal ,
|
||||||
|
.Li \e12
|
||||||
|
.Pq decimal ,
|
||||||
|
and
|
||||||
|
.Li \e20
|
||||||
|
.Pq hexadecimal .
|
||||||
|
.Pp
|
||||||
|
The remaining characters in
|
||||||
|
.Fa fmt
|
||||||
|
are interpreted as a list of bit-position\(endescription pairs.
|
||||||
|
From here the syntaxes diverge.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Dq old
|
||||||
|
format syntax is series of bit-position\(endescription pairs.
|
||||||
|
Each begins with a binary character value that represents the position
|
||||||
|
of the bit being described.
|
||||||
|
A bit position value of one describes the least significant bit.
|
||||||
|
Whereas a position value of 32
|
||||||
|
.Pq octal 40, hexadecimal 20, the ASCII space character
|
||||||
|
describes the most significant bit.
|
||||||
|
.Pp
|
||||||
|
The remaining characters in a bit-position\(endescription pair are the
|
||||||
|
characters to print should the bit being described be set.
|
||||||
|
Description strings are delimited by the next bit position value character
|
||||||
|
encountered
|
||||||
|
.Pq distinguishable by its value being \*[Le] 32 ,
|
||||||
|
or the end of the decoding directive string itself.
|
||||||
|
.Pp
|
||||||
|
For the
|
||||||
|
.Dq new
|
||||||
|
format syntax, a bit-position\(endescription begins with a field type
|
||||||
|
followed by a binary bit-position and possibly a field length.
|
||||||
|
The least significant bit is bit-position zero, unlike the
|
||||||
|
.Dq old
|
||||||
|
syntax where it is one.
|
||||||
|
.Bl -tag -width "xxxxx"
|
||||||
|
.It Cm b\eB
|
||||||
|
Describes a bit position.
|
||||||
|
The bit-position
|
||||||
|
.Fa B
|
||||||
|
indicates the corresponding bit, as in the
|
||||||
|
.Dq old
|
||||||
|
format.
|
||||||
|
.It Cm f\eB\eL
|
||||||
|
Describes a multi-bit field beginning at bit-position
|
||||||
|
.Fa B
|
||||||
|
and having a bit-length of
|
||||||
|
.Fa L .
|
||||||
|
The remaining characters are printed as a description of the field
|
||||||
|
followed by
|
||||||
|
.Sq \&=
|
||||||
|
and the value of the field.
|
||||||
|
The value of the field is printed in the base specified as the second
|
||||||
|
character of the decoding directive string
|
||||||
|
.Ar fmt .
|
||||||
|
.It Cm F\eB\eL
|
||||||
|
Describes a multi-bit field like
|
||||||
|
.Sq f ,
|
||||||
|
but just extracts the value for use with the
|
||||||
|
.Sq \&=
|
||||||
|
and
|
||||||
|
.Sq \&:
|
||||||
|
formatting directives described below.
|
||||||
|
.It Cm \&=\eV
|
||||||
|
The field previously extracted by the last
|
||||||
|
.Sq f
|
||||||
|
or
|
||||||
|
.Sq F
|
||||||
|
operator is compared to the byte
|
||||||
|
.Sq Cm V
|
||||||
|
.Pq for values 0 through 255 .
|
||||||
|
If they are equal,
|
||||||
|
.Sq \&=
|
||||||
|
followed by the string following
|
||||||
|
.Sq Cm V
|
||||||
|
is printed.
|
||||||
|
This and the
|
||||||
|
.Sq \&:
|
||||||
|
operator may be repeated to annotate multiple possible values.
|
||||||
|
.It Cm :\eV
|
||||||
|
Operates like the
|
||||||
|
.Sq \&=
|
||||||
|
operator, but omits the leading
|
||||||
|
.Sq \&= .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Finally, each field is delimited by a NUL
|
||||||
|
.Pq Sq \e0
|
||||||
|
character.
|
||||||
|
By convention, the format string has an additional NUL character at
|
||||||
|
the end, following that delimiting the last bit-position\(endescription
|
||||||
|
pair.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn snprintb_m
|
||||||
|
function accepts an additional
|
||||||
|
.Fa max
|
||||||
|
argument.
|
||||||
|
If this argument is zero, the
|
||||||
|
.Fn snprintb_m
|
||||||
|
function returns exactly the same results in the
|
||||||
|
.Fa buf
|
||||||
|
as the
|
||||||
|
.Fn snprintb
|
||||||
|
function.
|
||||||
|
If the
|
||||||
|
.Fa max
|
||||||
|
argument is present and has a non-zero value, it represents the maximum
|
||||||
|
length of a formatted string.
|
||||||
|
If the formatted string would require more than
|
||||||
|
.Fa max
|
||||||
|
characters, the
|
||||||
|
.Fn snprintb_m
|
||||||
|
function returns multiple formatted strings in the output buffer
|
||||||
|
.Fa buf .
|
||||||
|
Each string is NUL-terminated, and the last string is followed by an
|
||||||
|
additional NUL character (or, if you prefer, a zero-length string).
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn snprintb
|
||||||
|
and
|
||||||
|
.Fn snprintb_m
|
||||||
|
functions return the number of bytes that would have written to the buffer
|
||||||
|
if there was adequate space, excluding the final terminating NUL, or \-1 in
|
||||||
|
case an error occurred.
|
||||||
|
For
|
||||||
|
.Fn snprintb_m ,
|
||||||
|
the NUL characters terminating each individual string are included in the
|
||||||
|
total number of bytes.
|
||||||
|
.Sh EXAMPLES
|
||||||
|
Two examples of the old formatting style:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
snprintb(buf, buflen, "\e10\e2BITTWO\e1BITONE", 3)
|
||||||
|
\(rA "3\*[Lt]BITTWO,BITONE\*[Gt]"
|
||||||
|
|
||||||
|
snprintb(buf, buflen,
|
||||||
|
"\e20\ex10NOTBOOT\ex0fFPP\ex0eSDVMA\ex0cVIDEO"
|
||||||
|
"\ex0bLORES\ex0aFPA\ex09DIAG\ex07CACHE"
|
||||||
|
"\ex06IOCACHE\ex05LOOPBACK\ex04DBGCACHE",
|
||||||
|
0xe860)
|
||||||
|
\(rA "e860\*[Lt]NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE\*[Gt]"
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
An example of the new formatting style:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
snprintb(buf, buflen,
|
||||||
|
"\e177\e020b\e0LSB\e0b\e1_BITONE\e0f\e4\e4NIBBLE2\e0"
|
||||||
|
"f\ex10\e4BURST\e0=\e4FOUR\e0=\exfSIXTEEN\e0"
|
||||||
|
"b\ex1fMSB\e0\e0",
|
||||||
|
0x800f0701)
|
||||||
|
\(rA "800f0701\*[Lt]LSB,NIBBLE2=0,BURST=f=SIXTEEN,MSB\*[Gt]"
|
||||||
|
.Ed
|
||||||
|
.Sh ERRORS
|
||||||
|
.Fn snprintb
|
||||||
|
will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EINVAL
|
||||||
|
The leading character does not describe a supported format,
|
||||||
|
or
|
||||||
|
.Fn snprintf
|
||||||
|
failed.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr printf 3 ,
|
||||||
|
.Xr snprintf 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn snprintb
|
||||||
|
function was originally implemented as a non-standard
|
||||||
|
.Li %b
|
||||||
|
format string for the kernel
|
||||||
|
.Fn printf
|
||||||
|
function in
|
||||||
|
.Nx 1.5
|
||||||
|
and earlier releases.
|
||||||
|
It was called
|
||||||
|
.Fn bitmask_snprintf
|
||||||
|
in
|
||||||
|
.Nx 5.0
|
||||||
|
and earlier releases.
|
||||||
|
.Sh AUTHORS
|
||||||
|
The
|
||||||
|
.Dq new
|
||||||
|
format was the invention of
|
||||||
|
.An Chris Torek .
|
236
lib/libutil/sockaddr_snprintf.3
Normal file
236
lib/libutil/sockaddr_snprintf.3
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
.\" $NetBSD: sockaddr_snprintf.3,v 1.7 2009/04/11 16:13:49 joerg Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Christos Zoulas.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd April 9, 2005
|
||||||
|
.Dt SOCKADDR_SNPRINTF 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm sockaddr_snprintf
|
||||||
|
.Nd formatting function for socket address structures
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn sockaddr_snprintf "char *buf" "size_t buflen" "const char *fmt" "const struct sockaddr *sa"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn sockaddr_snprintf
|
||||||
|
function formats a socket address into a form suitable for printing.
|
||||||
|
.Pp
|
||||||
|
This function is convenient because it is protocol independent, i.e. one does
|
||||||
|
not need to know the address family of the sockaddr in order to print it.
|
||||||
|
The
|
||||||
|
.Xr printf 3
|
||||||
|
like format string specifies how the address is going to be printed.
|
||||||
|
Some formatting characters are only supported by some address families.
|
||||||
|
If a certain formatting character is not supported, then the string
|
||||||
|
.Dq N/A
|
||||||
|
is printed.
|
||||||
|
.Pp
|
||||||
|
The resulting formatted string is placed into
|
||||||
|
.Fa buf .
|
||||||
|
Up to
|
||||||
|
.Fa buflen
|
||||||
|
characters are placed in
|
||||||
|
.Fa buf .
|
||||||
|
.Pp
|
||||||
|
The following formatting characters are supported (immediately
|
||||||
|
after a percent
|
||||||
|
.Pq Sq %
|
||||||
|
sign):
|
||||||
|
.Bl -tag -width %a
|
||||||
|
.It a
|
||||||
|
The node address portion of the socket address is printed numerically.
|
||||||
|
For
|
||||||
|
.Dv AF_INET
|
||||||
|
the address is printed as:
|
||||||
|
.Dq A.B.C.D
|
||||||
|
and
|
||||||
|
for AF_INET6
|
||||||
|
the address is printed as:
|
||||||
|
.Dq A:B...[%if]
|
||||||
|
using
|
||||||
|
.Xr getnameinfo 3
|
||||||
|
internally with
|
||||||
|
.Dv NI_NUMERICHOST .
|
||||||
|
For
|
||||||
|
.Dv AF_APPLETALK
|
||||||
|
the address is printed as:
|
||||||
|
.Dq A.B
|
||||||
|
For
|
||||||
|
.Dv AF_LOCAL
|
||||||
|
.Pq Dv AF_UNIX
|
||||||
|
the address is printed as:
|
||||||
|
.Dq socket-path
|
||||||
|
For
|
||||||
|
.Dv AF_LINK
|
||||||
|
the address is printed as:
|
||||||
|
.Dq a.b.c.d.e.f
|
||||||
|
using
|
||||||
|
.Xr link_ntoa 3 ,
|
||||||
|
but the interface portion is skipped (see below).
|
||||||
|
For
|
||||||
|
.Dv AF_UNSPEC
|
||||||
|
nothing is printed.
|
||||||
|
.It A
|
||||||
|
The symbolic name of the address is printed.
|
||||||
|
For
|
||||||
|
.Dv AF_INET
|
||||||
|
and
|
||||||
|
.Dv AF_INET6
|
||||||
|
this is the hostname associated with the address.
|
||||||
|
For all other address families, it is the same as the
|
||||||
|
.Dq a
|
||||||
|
format.
|
||||||
|
.It f
|
||||||
|
The numeric value of the family of the address is printed.
|
||||||
|
.It l
|
||||||
|
The length of the socket address is printed.
|
||||||
|
.It p
|
||||||
|
For
|
||||||
|
.Dv AF_INET ,
|
||||||
|
.Dv AF_INET6 ,
|
||||||
|
and
|
||||||
|
.Dv AF_APPLETALK
|
||||||
|
the numeric value of the port portion of the address is printed.
|
||||||
|
.It P
|
||||||
|
For
|
||||||
|
.Dv AF_INET
|
||||||
|
and
|
||||||
|
.Dv AF_INET6
|
||||||
|
this is the name of the service associated with the port number, if
|
||||||
|
available.
|
||||||
|
For all other address families, it is the same as the
|
||||||
|
.Dq p
|
||||||
|
format.
|
||||||
|
.It I
|
||||||
|
For
|
||||||
|
.Dv AF_LINK
|
||||||
|
addresses, the interface name portion is printed.
|
||||||
|
.It F
|
||||||
|
For
|
||||||
|
.Dv AF_INET6
|
||||||
|
addresses, the flowinfo portion of the address is printed numerically.
|
||||||
|
.It R
|
||||||
|
For
|
||||||
|
.Dv AF_APPLETALK
|
||||||
|
addresses, the netrange portion of the address is printed as:
|
||||||
|
.Dq phase:[firstnet,lastnet]
|
||||||
|
.It S
|
||||||
|
For
|
||||||
|
.Dv AF_INET6
|
||||||
|
addresses, the scope portion of the address is printed numerically.
|
||||||
|
.It ?
|
||||||
|
If present between
|
||||||
|
.Dq %
|
||||||
|
and the format character, and the selected format does not apply to
|
||||||
|
the given address family, the
|
||||||
|
.Dq N/A
|
||||||
|
string is elided and no output results.
|
||||||
|
.El
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn sockaddr_snprintf
|
||||||
|
function returns the number of characters that are required to format the
|
||||||
|
value
|
||||||
|
.Fa val
|
||||||
|
given the format string
|
||||||
|
.Fa fmt
|
||||||
|
excluding the terminating NUL.
|
||||||
|
The returned string in
|
||||||
|
.Fa buf
|
||||||
|
is always NUL-terminated.
|
||||||
|
If the address family is not supported,
|
||||||
|
.Fn sockaddr_snprintf
|
||||||
|
returns \-1 and sets
|
||||||
|
.Va errno
|
||||||
|
to
|
||||||
|
.Dv EAFNOSUPPORT .
|
||||||
|
For
|
||||||
|
.Dv AF_INET
|
||||||
|
and
|
||||||
|
.Dv AF_INET6
|
||||||
|
addresses
|
||||||
|
.Fn sockaddr_snprintf
|
||||||
|
returns \-1 if the
|
||||||
|
.Xr getnameinfo 3
|
||||||
|
conversion failed, and
|
||||||
|
.Fa errno
|
||||||
|
is set to the error value from
|
||||||
|
.Xr getnameinfo 3 .
|
||||||
|
.Sh ERRORS
|
||||||
|
If the buffer
|
||||||
|
.Fa buf
|
||||||
|
is too small to hold the formatted output,
|
||||||
|
.Fn sockaddr_snprintf
|
||||||
|
will still return the buffer, containing a truncated string.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr getaddrinfo 3 ,
|
||||||
|
.Xr getnameinfo 3 ,
|
||||||
|
.Xr link_ntoa 3 ,
|
||||||
|
.Xr snprintf 3
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Fn sockaddr_snprintf
|
||||||
|
first appeared in
|
||||||
|
.Nx 3.0 .
|
||||||
|
.Sh BUGS
|
||||||
|
The
|
||||||
|
.Fn sockaddr_snprintf
|
||||||
|
interface is experimental and might change in the future.
|
||||||
|
.Pp
|
||||||
|
There is no way to specify different formatting styles for particular
|
||||||
|
addresses.
|
||||||
|
For example it would be useful to print
|
||||||
|
.Dv AF_LINK
|
||||||
|
addresses as
|
||||||
|
.Dq %.2x:%.2x...
|
||||||
|
instead of
|
||||||
|
.Dq %x.%x...
|
||||||
|
.Pp
|
||||||
|
This function is supposed to be quick, but
|
||||||
|
.Xr getnameinfo 3
|
||||||
|
might use system calls to convert the scope number to an interface
|
||||||
|
name and the
|
||||||
|
.Dq A
|
||||||
|
and
|
||||||
|
.Dq P
|
||||||
|
format characters call
|
||||||
|
.Xr getaddrinfo 3
|
||||||
|
which may block for a noticeable period of time.
|
||||||
|
.Pp
|
||||||
|
Not all formatting characters are supported by all address families and
|
||||||
|
printing
|
||||||
|
.Dq N/A
|
||||||
|
is not very convenient.
|
||||||
|
The
|
||||||
|
.Dq \&?
|
||||||
|
character can suppress this, but other formatting (e.g., spacing or
|
||||||
|
punctuation) will remain.
|
229
lib/libutil/sockaddr_snprintf.c
Normal file
229
lib/libutil/sockaddr_snprintf.c
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
/* $NetBSD: sockaddr_snprintf.c,v 1.9 2008/04/28 20:23:03 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: sockaddr_snprintf.c,v 1.9 2008/04/28 20:23:03 martin Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netatalk/at.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
sockaddr_snprintf(char * const sbuf, const size_t len, const char * const fmt,
|
||||||
|
const struct sockaddr * const sa)
|
||||||
|
{
|
||||||
|
const void *a = NULL;
|
||||||
|
char abuf[1024], nbuf[1024], *addr = NULL, *w = NULL;
|
||||||
|
char Abuf[1024], pbuf[32], *name = NULL, *port = NULL;
|
||||||
|
char *ebuf = &sbuf[len - 1], *buf = sbuf;
|
||||||
|
const char *ptr, *s;
|
||||||
|
int p = -1;
|
||||||
|
const struct sockaddr_at *sat = NULL;
|
||||||
|
const struct sockaddr_in *sin4 = NULL;
|
||||||
|
const struct sockaddr_in6 *sin6 = NULL;
|
||||||
|
const struct sockaddr_un *sun = NULL;
|
||||||
|
const struct sockaddr_dl *sdl = NULL;
|
||||||
|
int na = 1;
|
||||||
|
|
||||||
|
#define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \
|
||||||
|
while (/*CONSTCOND*/0)
|
||||||
|
#define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \
|
||||||
|
while (/*CONSTCOND*/0)
|
||||||
|
#define ADDNA() do { if (na) ADDS("N/A"); } \
|
||||||
|
while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
switch (sa->sa_family) {
|
||||||
|
case AF_UNSPEC:
|
||||||
|
goto done;
|
||||||
|
case AF_APPLETALK:
|
||||||
|
sat = ((const struct sockaddr_at *)(const void *)sa);
|
||||||
|
p = ntohs(sat->sat_port);
|
||||||
|
(void)snprintf(addr = abuf, sizeof(abuf), "%u.%u",
|
||||||
|
ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
|
||||||
|
(void)snprintf(port = pbuf, sizeof(pbuf), "%d", p);
|
||||||
|
break;
|
||||||
|
case AF_LOCAL:
|
||||||
|
sun = ((const struct sockaddr_un *)(const void *)sa);
|
||||||
|
(void)strlcpy(addr = abuf, sun->sun_path, SUN_LEN(sun));
|
||||||
|
break;
|
||||||
|
case AF_INET:
|
||||||
|
sin4 = ((const struct sockaddr_in *)(const void *)sa);
|
||||||
|
p = ntohs(sin4->sin_port);
|
||||||
|
a = &sin4->sin_addr;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
sin6 = ((const struct sockaddr_in6 *)(const void *)sa);
|
||||||
|
p = ntohs(sin6->sin6_port);
|
||||||
|
a = &sin6->sin6_addr;
|
||||||
|
break;
|
||||||
|
case AF_LINK:
|
||||||
|
sdl = ((const struct sockaddr_dl *)(const void *)sa);
|
||||||
|
(void)strlcpy(addr = abuf, link_ntoa(sdl), sizeof(abuf));
|
||||||
|
if ((w = strchr(addr, ':')) != 0) {
|
||||||
|
*w++ = '\0';
|
||||||
|
addr = w;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr == abuf)
|
||||||
|
name = addr;
|
||||||
|
|
||||||
|
if (a && getnameinfo(sa, (socklen_t)sa->sa_len, addr = abuf,
|
||||||
|
(unsigned int)sizeof(abuf), NULL, 0,
|
||||||
|
NI_NUMERICHOST|NI_NUMERICSERV) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (ptr = fmt; *ptr; ptr++) {
|
||||||
|
if (*ptr != '%') {
|
||||||
|
ADDC(*ptr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
next_char:
|
||||||
|
switch (*++ptr) {
|
||||||
|
case '?':
|
||||||
|
na = 0;
|
||||||
|
goto next_char;
|
||||||
|
case 'a':
|
||||||
|
ADDS(addr);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (p != -1) {
|
||||||
|
(void)snprintf(nbuf, sizeof(nbuf), "%d", p);
|
||||||
|
ADDS(nbuf);
|
||||||
|
} else
|
||||||
|
ADDNA();
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
(void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_family);
|
||||||
|
ADDS(nbuf);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
(void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_len);
|
||||||
|
ADDS(nbuf);
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
if (name)
|
||||||
|
ADDS(name);
|
||||||
|
else if (!a)
|
||||||
|
ADDNA();
|
||||||
|
else {
|
||||||
|
getnameinfo(sa, (socklen_t)sa->sa_len,
|
||||||
|
name = Abuf,
|
||||||
|
(unsigned int)sizeof(nbuf), NULL, 0, 0);
|
||||||
|
ADDS(name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
if (port)
|
||||||
|
ADDS(port);
|
||||||
|
else if (p == -1)
|
||||||
|
ADDNA();
|
||||||
|
else {
|
||||||
|
getnameinfo(sa, (socklen_t)sa->sa_len, NULL, 0,
|
||||||
|
port = pbuf,
|
||||||
|
(unsigned int)sizeof(pbuf), 0);
|
||||||
|
ADDS(port);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
if (sdl && addr != abuf) {
|
||||||
|
ADDS(abuf);
|
||||||
|
} else {
|
||||||
|
ADDNA();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (sin6) {
|
||||||
|
(void)snprintf(nbuf, sizeof(nbuf), "%d",
|
||||||
|
sin6->sin6_flowinfo);
|
||||||
|
ADDS(nbuf);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ADDNA();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
if (sin6) {
|
||||||
|
(void)snprintf(nbuf, sizeof(nbuf), "%d",
|
||||||
|
sin6->sin6_scope_id);
|
||||||
|
ADDS(nbuf);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ADDNA();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
if (sat) {
|
||||||
|
const struct netrange *n =
|
||||||
|
&sat->sat_range.r_netrange;
|
||||||
|
(void)snprintf(nbuf, sizeof(nbuf),
|
||||||
|
"%d:[%d,%d]", n->nr_phase , n->nr_firstnet,
|
||||||
|
n->nr_lastnet);
|
||||||
|
ADDS(nbuf);
|
||||||
|
} else {
|
||||||
|
ADDNA();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ADDC('%');
|
||||||
|
if (na == 0)
|
||||||
|
ADDC('?');
|
||||||
|
if (*ptr == '\0')
|
||||||
|
goto done;
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case '%':
|
||||||
|
ADDC(*ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
na = 1;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
if (buf < ebuf)
|
||||||
|
*buf = '\0';
|
||||||
|
else if (len != 0)
|
||||||
|
sbuf[len - 1] = '\0';
|
||||||
|
return (int)(buf - sbuf);
|
||||||
|
}
|
125
lib/libutil/stat_flags.3
Normal file
125
lib/libutil/stat_flags.3
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
.\" $NetBSD: stat_flags.3,v 1.6 2010/05/04 06:53:35 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Christos Zoulas.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt STAT_FLAGS 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm string_to_flags ,
|
||||||
|
.Nm flags_to_string
|
||||||
|
.Nd Stat flags parsing and printing functions
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft char *
|
||||||
|
.Fn flags_to_string "u_long flags" "const char *def"
|
||||||
|
.Ft int
|
||||||
|
.Fn string_to_flags "char **stringp" "u_long *setp" "u_long clrp"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn flags_to_string
|
||||||
|
and
|
||||||
|
.Fn string_to_flags
|
||||||
|
functions are used by
|
||||||
|
programs such as
|
||||||
|
.Xr ls 1 ,
|
||||||
|
.Xr mtree 8 ,
|
||||||
|
.Xr makefs 8 ,
|
||||||
|
etc., to parse and/or print the
|
||||||
|
.Dv st_flags field in the
|
||||||
|
.Xr stat 2
|
||||||
|
structure.
|
||||||
|
.Pp
|
||||||
|
They recognize the following flags:
|
||||||
|
.Bl -column -offset indent "uappnd " "SF_IMMUTABLE" "xxx"
|
||||||
|
.It Sy String Ta Sy Flag Ta Sy Description
|
||||||
|
.It Va arch Ta Dv SF_ARCHIVED Ta file is archived
|
||||||
|
.It Va nodump Ta Dv UF_NODUMP Ta do not dump file
|
||||||
|
.It Va opaque Ta Dv UF_OPAQUE Ta directory is opaque in union filesystems
|
||||||
|
.It Va sappnd Ta Dv SF_APPEND Ta writes to the file may only append
|
||||||
|
.It Va schg Ta Dv SF_IMMUTABLE Ta file cannot be changed; it is immutable
|
||||||
|
.It Va snap Ta Dv SF_SNAPSHOT Ta file is a snapshot inode
|
||||||
|
.It Va uappnd Ta Dv UF_APPEND Ta writes to the file may only append
|
||||||
|
.It Va uchg Ta Dv UF_IMMUTABLE Ta file cannot be changed; it is immutable
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Dv SF_APPEND
|
||||||
|
and
|
||||||
|
.Dv SF_IMMUTABLE
|
||||||
|
flags are for the superuser only, whereas
|
||||||
|
.Dv UF_APPEND
|
||||||
|
and
|
||||||
|
.Dv UF_IMMUTABLE
|
||||||
|
are for the user only.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn flags_to_string
|
||||||
|
function converts the bits set in the
|
||||||
|
.Fa flags
|
||||||
|
argument to a comma-separated string and returns it.
|
||||||
|
If no flags are set, then the
|
||||||
|
.Fa def
|
||||||
|
string is returned.
|
||||||
|
The returned string is allocated via
|
||||||
|
.Xr malloc 3
|
||||||
|
and it is the responsibility of the caller to
|
||||||
|
.Xr free 3
|
||||||
|
it.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn string_to_flags
|
||||||
|
function takes a
|
||||||
|
.Fa stringp
|
||||||
|
of space, comma, or tab separated flag names
|
||||||
|
and places their bit value on the
|
||||||
|
.Fa setp
|
||||||
|
argument.
|
||||||
|
If the flag name is prefixed by:
|
||||||
|
.Dq no ,
|
||||||
|
then the bit value is placed on the
|
||||||
|
.Fa clrp
|
||||||
|
argument.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn flags_to_string
|
||||||
|
returns the symbolic representation of flags, the default string, or
|
||||||
|
.Dv NULL
|
||||||
|
if allocation failed.
|
||||||
|
.Pp
|
||||||
|
.Fn string_to_flags
|
||||||
|
returns
|
||||||
|
.Dv 0
|
||||||
|
on success and
|
||||||
|
.Dv 1
|
||||||
|
if it fails to parse the string, setting
|
||||||
|
.Fa stringp
|
||||||
|
to point to the first string that it failed to parse.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr stat 2
|
186
lib/libutil/stat_flags.c
Normal file
186
lib/libutil/stat_flags.c
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/* $NetBSD: stat_flags.c,v 1.2 2007/01/16 17:34:02 cbiere Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_NBTOOL_CONFIG_H
|
||||||
|
#include "nbtool_config.h"
|
||||||
|
#else
|
||||||
|
#define HAVE_STRUCT_STAT_ST_FLAGS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)stat_flags.c 8.2 (Berkeley) 7/28/94";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: stat_flags.c,v 1.2 2007/01/16 17:34:02 cbiere Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define SAPPEND(s) do { \
|
||||||
|
if (prefix != NULL) \
|
||||||
|
(void)strlcat(string, prefix, sizeof(string)); \
|
||||||
|
(void)strlcat(string, s, sizeof(string)); \
|
||||||
|
prefix = ","; \
|
||||||
|
} while (/* CONSTCOND */ 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flags_to_string --
|
||||||
|
* Convert stat flags to a comma-separated string. If no flags
|
||||||
|
* are set, return the default string.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
flags_to_string(u_long flags, const char *def)
|
||||||
|
{
|
||||||
|
char string[128];
|
||||||
|
const char *prefix;
|
||||||
|
|
||||||
|
string[0] = '\0';
|
||||||
|
prefix = NULL;
|
||||||
|
#if HAVE_STRUCT_STAT_ST_FLAGS
|
||||||
|
if (flags & UF_APPEND)
|
||||||
|
SAPPEND("uappnd");
|
||||||
|
if (flags & UF_IMMUTABLE)
|
||||||
|
SAPPEND("uchg");
|
||||||
|
if (flags & UF_NODUMP)
|
||||||
|
SAPPEND("nodump");
|
||||||
|
if (flags & UF_OPAQUE)
|
||||||
|
SAPPEND("opaque");
|
||||||
|
if (flags & SF_APPEND)
|
||||||
|
SAPPEND("sappnd");
|
||||||
|
if (flags & SF_ARCHIVED)
|
||||||
|
SAPPEND("arch");
|
||||||
|
if (flags & SF_IMMUTABLE)
|
||||||
|
SAPPEND("schg");
|
||||||
|
#ifdef SF_SNAPSHOT
|
||||||
|
if (flags & SF_SNAPSHOT)
|
||||||
|
SAPPEND("snap");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (prefix != NULL)
|
||||||
|
return strdup(string);
|
||||||
|
return strdup(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST(a, b, f) { \
|
||||||
|
if (!strcmp(a, b)) { \
|
||||||
|
if (clear) { \
|
||||||
|
if (clrp) \
|
||||||
|
*clrp |= (f); \
|
||||||
|
if (setp) \
|
||||||
|
*setp &= ~(f); \
|
||||||
|
} else { \
|
||||||
|
if (setp) \
|
||||||
|
*setp |= (f); \
|
||||||
|
if (clrp) \
|
||||||
|
*clrp &= ~(f); \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* string_to_flags --
|
||||||
|
* Take string of arguments and return stat flags. Return 0 on
|
||||||
|
* success, 1 on failure. On failure, stringp is set to point
|
||||||
|
* to the offending token.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
string_to_flags(char **stringp, u_long *setp, u_long *clrp)
|
||||||
|
{
|
||||||
|
int clear;
|
||||||
|
char *string, *p;
|
||||||
|
|
||||||
|
if (setp)
|
||||||
|
*setp = 0;
|
||||||
|
if (clrp)
|
||||||
|
*clrp = 0;
|
||||||
|
|
||||||
|
#if HAVE_STRUCT_STAT_ST_FLAGS
|
||||||
|
string = *stringp;
|
||||||
|
while ((p = strsep(&string, "\t ,")) != NULL) {
|
||||||
|
clear = 0;
|
||||||
|
*stringp = p;
|
||||||
|
if (*p == '\0')
|
||||||
|
continue;
|
||||||
|
if (p[0] == 'n' && p[1] == 'o') {
|
||||||
|
clear = 1;
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
switch (p[0]) {
|
||||||
|
case 'a':
|
||||||
|
TEST(p, "arch", SF_ARCHIVED);
|
||||||
|
TEST(p, "archived", SF_ARCHIVED);
|
||||||
|
return (1);
|
||||||
|
case 'd':
|
||||||
|
clear = !clear;
|
||||||
|
TEST(p, "dump", UF_NODUMP);
|
||||||
|
return (1);
|
||||||
|
case 'n':
|
||||||
|
/*
|
||||||
|
* Support `nonodump'. Note that
|
||||||
|
* the state of clear is not changed.
|
||||||
|
*/
|
||||||
|
TEST(p, "nodump", UF_NODUMP);
|
||||||
|
return (1);
|
||||||
|
case 'o':
|
||||||
|
TEST(p, "opaque", UF_OPAQUE);
|
||||||
|
return (1);
|
||||||
|
case 's':
|
||||||
|
TEST(p, "sappnd", SF_APPEND);
|
||||||
|
TEST(p, "sappend", SF_APPEND);
|
||||||
|
TEST(p, "schg", SF_IMMUTABLE);
|
||||||
|
TEST(p, "schange", SF_IMMUTABLE);
|
||||||
|
TEST(p, "simmutable", SF_IMMUTABLE);
|
||||||
|
return (1);
|
||||||
|
case 'u':
|
||||||
|
TEST(p, "uappnd", UF_APPEND);
|
||||||
|
TEST(p, "uappend", UF_APPEND);
|
||||||
|
TEST(p, "uchg", UF_IMMUTABLE);
|
||||||
|
TEST(p, "uchange", UF_IMMUTABLE);
|
||||||
|
TEST(p, "uimmutable", UF_IMMUTABLE);
|
||||||
|
return (1);
|
||||||
|
default:
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
108
lib/libutil/ttyaction.3
Normal file
108
lib/libutil/ttyaction.3
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
.\" $NetBSD: ttyaction.3,v 1.15 2010/05/04 06:41:27 jruoho Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
.\" by Gordon W. Ross.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd May 4, 2010
|
||||||
|
.Dt TTYACTION 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm ttyaction
|
||||||
|
.Nd ttyaction utility function
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft int
|
||||||
|
.Fn ttyaction "char *ttyname" "char *action" "char *username"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn ttyaction
|
||||||
|
function is used by
|
||||||
|
.Xr login 1 ,
|
||||||
|
.Xr getty 8 ,
|
||||||
|
.Xr telnetd 8
|
||||||
|
and
|
||||||
|
.Xr rlogind 8
|
||||||
|
to execute site-specific commands
|
||||||
|
when a login session begins and ends.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn ttyaction
|
||||||
|
function scans the
|
||||||
|
.Pa /etc/ttyaction
|
||||||
|
file for any records that match the current
|
||||||
|
.Fa ttyname
|
||||||
|
and
|
||||||
|
.Fa action
|
||||||
|
parameters, and for each matching record,
|
||||||
|
runs the shell command shown in that record.
|
||||||
|
The record format is described in
|
||||||
|
.Xr ttyaction 5 .
|
||||||
|
The parameter
|
||||||
|
.Fa username
|
||||||
|
is the name of the new owner of the
|
||||||
|
.Fa ttyname
|
||||||
|
device.
|
||||||
|
Note that the
|
||||||
|
.Fa ttyname
|
||||||
|
parameter may be passed as a fully qualified pathname, and the
|
||||||
|
.Fn ttyaction
|
||||||
|
function will skip the leading "/dev/" part of the string.
|
||||||
|
(This is a convenience for login and getty.)
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn ttyaction
|
||||||
|
returns the status of the last command it executed,
|
||||||
|
or zero if no matching commands were found.
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /etc/ttyaction -compact
|
||||||
|
.It Pa /dev/\(**
|
||||||
|
.It Pa /etc/ttyaction
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr ttyaction 5
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An Gordon W. Ross
|
||||||
|
.Aq gwr@NetBSD.org ,
|
||||||
|
.An Chris G. Demetriou
|
||||||
|
.Aq cgd@NetBSD.org ,
|
||||||
|
.An Ty Sarna
|
||||||
|
.Aq tsarna@NetBSD.org .
|
||||||
|
.Sh BUGS
|
||||||
|
There should be some
|
||||||
|
.Em other
|
||||||
|
mechanism to allow selection of different access control policies
|
||||||
|
on a per-line basis.
|
||||||
|
It has been suggested that the same
|
||||||
|
.Fn ttyaction
|
||||||
|
mechanism should also be used for determining access control, but
|
||||||
|
it was decided (after much discussion) that
|
||||||
|
.Fn ttyaction
|
||||||
|
should only describe actions to be performed
|
||||||
|
.Em after
|
||||||
|
the system has decided to change the ownership of some tty.
|
||||||
|
Access control policies will be handled by a separate mechanism.
|
160
lib/libutil/ttyaction.c
Normal file
160
lib/libutil/ttyaction.c
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/* $NetBSD: ttyaction.c,v 1.19 2008/04/28 20:23:03 martin Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Gordon W. Ross.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each matching "tty" and "action" run the "command."
|
||||||
|
* See fnmatch() for matching the tty name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
__RCSID("$NetBSD: ttyaction.c,v 1.19 2008/04/28 20:23:03 martin Exp $");
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#ifndef _PATH_TTYACTION
|
||||||
|
#define _PATH_TTYACTION "/etc/ttyaction"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char *actfile = _PATH_TTYACTION;
|
||||||
|
static const char *pathenv = "PATH=" _PATH_STDPATH;
|
||||||
|
|
||||||
|
int
|
||||||
|
ttyaction(const char *tty, const char *act, const char *user)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char *p1, *p2;
|
||||||
|
const char *argv[4];
|
||||||
|
const char *envp[8];
|
||||||
|
char *lastp;
|
||||||
|
char line[1024];
|
||||||
|
char env_tty[64];
|
||||||
|
char env_act[64];
|
||||||
|
char env_user[256];
|
||||||
|
int error, linenum, status;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
_DIAGASSERT(tty != NULL);
|
||||||
|
_DIAGASSERT(act != NULL);
|
||||||
|
_DIAGASSERT(user != NULL);
|
||||||
|
|
||||||
|
fp = fopen(actfile, "r");
|
||||||
|
if (fp == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Skip the "/dev/" part of the first arg. */
|
||||||
|
if (!strncmp(tty, "/dev/", (size_t)5))
|
||||||
|
tty += 5;
|
||||||
|
|
||||||
|
/* Args will be: "sh -c ..." */
|
||||||
|
argv[0] = _PATH_BSHELL;
|
||||||
|
argv[1] = "-c";
|
||||||
|
argv[2] = NULL; /* see below */
|
||||||
|
argv[3] = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Environment needs: TTY, ACT, USER
|
||||||
|
*/
|
||||||
|
snprintf(env_tty, sizeof(env_tty), "TTY=%s", tty);
|
||||||
|
snprintf(env_act, sizeof(env_act), "ACT=%s", act);
|
||||||
|
snprintf(env_user, sizeof(env_user), "USER=%s", user);
|
||||||
|
envp[0] = pathenv;
|
||||||
|
envp[1] = env_tty;
|
||||||
|
envp[2] = env_act;
|
||||||
|
envp[3] = env_user;
|
||||||
|
envp[4] = NULL;
|
||||||
|
|
||||||
|
linenum = 0;
|
||||||
|
status = 0;
|
||||||
|
while (fgets(line, (int)sizeof(line), fp)) {
|
||||||
|
linenum++;
|
||||||
|
|
||||||
|
/* Allow comment lines. */
|
||||||
|
if (line[0] == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p1 = strtok_r(line, " \t", &lastp);
|
||||||
|
p2 = strtok_r(NULL, " \t", &lastp);
|
||||||
|
/* This arg goes to end of line. */
|
||||||
|
argv[2] = strtok_r(NULL, "\n", &lastp);
|
||||||
|
if (!p1 || !p2 || !argv[2]) {
|
||||||
|
warnx("%s: line %d format error", actfile, linenum);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fnmatch(p1, tty, 0) || fnmatch(p2, act, 0))
|
||||||
|
continue;
|
||||||
|
/* OK, this is a match. Run the command. */
|
||||||
|
pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
warnx("fork failed: %s", strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pid == 0) {
|
||||||
|
/* This is the child. */
|
||||||
|
error = execve(argv[0],
|
||||||
|
(char *const *)__UNCONST(argv),
|
||||||
|
(char *const *)__UNCONST(envp));
|
||||||
|
/* If we get here, it is an error. */
|
||||||
|
warnx("%s: line %d: exec failed: %s",
|
||||||
|
actfile, linenum, strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
/* This is the parent. */
|
||||||
|
error = waitpid(pid, &status, 0);
|
||||||
|
if (error == -1) {
|
||||||
|
warnx("%s: line %d: wait failed: %s",
|
||||||
|
actfile, linenum, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (WTERMSIG(status)) {
|
||||||
|
warnx("%s: line %d: child died with signal %d",
|
||||||
|
actfile, linenum, WTERMSIG(status));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return status;
|
||||||
|
}
|
60
lib/libutil/ttymsg.3
Normal file
60
lib/libutil/ttymsg.3
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
.\" $NetBSD: ttymsg.3,v 1.11 2008/04/30 13:10:52 martin Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.Dd June 29, 1997
|
||||||
|
.Dt TTYMSG 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm ttymsg
|
||||||
|
.Nd ttymsg utility function
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In util.h
|
||||||
|
.Ft char *
|
||||||
|
.Fn ttymsg "struct iovec *iov" "int iovlen" "const char *tty" "int tmout"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Fn ttymsg
|
||||||
|
function is used by
|
||||||
|
programs such as
|
||||||
|
.Xr talkd 8 ,
|
||||||
|
.Xr syslogd 8 ,
|
||||||
|
.Xr wall 1 ,
|
||||||
|
etc., to display the contents of a uio structure on a terminal.
|
||||||
|
.Fn ttymsg
|
||||||
|
forks and finishes in the child if the write would block after
|
||||||
|
waiting up to
|
||||||
|
.Fa tmout
|
||||||
|
seconds.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
.Fn ttymsg
|
||||||
|
returns a pointer to an error string on unexpected
|
||||||
|
error; the string is not newline-terminated.
|
||||||
|
Various "normal" errors are
|
||||||
|
ignored (exclusive-use, lack of permission, etc.).
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr writev 2
|
208
lib/libutil/ttymsg.c
Normal file
208
lib/libutil/ttymsg.c
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
/* $NetBSD: ttymsg.c,v 1.23 2009/01/18 12:13:04 lukem Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)ttymsg.c 8.2 (Berkeley) 11/16/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: ttymsg.c,v 1.23 2009/01/18 12:13:04 lukem Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display the contents of a uio structure on a terminal. Used by wall(1),
|
||||||
|
* syslogd(8), and talkd(8). Forks and finishes in child if write would block,
|
||||||
|
* waiting up to tmout seconds. Returns pointer to error string on unexpected
|
||||||
|
* error; string is not newline-terminated. Various "normal" errors are
|
||||||
|
* ignored (exclusive-use, lack of permission, etc.).
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
|
||||||
|
{
|
||||||
|
static char errbuf[1024];
|
||||||
|
char device[MAXNAMLEN];
|
||||||
|
const char *ptr;
|
||||||
|
int fd, ret;
|
||||||
|
struct iovec localiov[32];
|
||||||
|
sigset_t nset;
|
||||||
|
int forked = 0;
|
||||||
|
size_t cnt, left, wret;
|
||||||
|
|
||||||
|
_DIAGASSERT(iov != NULL);
|
||||||
|
_DIAGASSERT(iovcnt >= 0);
|
||||||
|
_DIAGASSERT(line != NULL);
|
||||||
|
|
||||||
|
if (iovcnt < 0) {
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: negative iovcnt", __func__);
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t)iovcnt >= sizeof(localiov) / sizeof(localiov[0])) {
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: too many iov's (%d) max is %zu", __func__,
|
||||||
|
iovcnt, sizeof(localiov) / sizeof(localiov[0]));
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = strncmp(line, "pts/", (size_t)4) == 0 ? line + 4 : line;
|
||||||
|
if (strcspn(ptr, "./") != strlen(ptr)) {
|
||||||
|
/* A slash or dot is an attempt to break security... */
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: '/' or '.' in \"%s\"", __func__, line);
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
ret = snprintf(device, sizeof(device), "%s%s", _PATH_DEV, line);
|
||||||
|
if (ret == -1 || ret >= (int)sizeof(device)) {
|
||||||
|
(void) snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: line `%s' too long", __func__, line);
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
cnt = (size_t)ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open will fail on slip lines or exclusive-use lines
|
||||||
|
* if not running as root; not an error.
|
||||||
|
*/
|
||||||
|
if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
|
||||||
|
if (errno == EBUSY || errno == EACCES)
|
||||||
|
return NULL;
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: Cannot open `%s' (%s)",
|
||||||
|
__func__, device, strerror(errno));
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
if (!isatty(fd)) {
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: line `%s' is not a tty device", __func__, device);
|
||||||
|
(void)close(fd);
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cnt = left = 0; cnt < (size_t)iovcnt; ++cnt)
|
||||||
|
left += iov[cnt].iov_len;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
wret = writev(fd, iov, iovcnt);
|
||||||
|
if (wret >= left)
|
||||||
|
break;
|
||||||
|
if (wret > 0) {
|
||||||
|
left -= wret;
|
||||||
|
if (iov != localiov) {
|
||||||
|
(void)memcpy(localiov, iov,
|
||||||
|
iovcnt * sizeof(struct iovec));
|
||||||
|
iov = localiov;
|
||||||
|
}
|
||||||
|
for (cnt = 0; wret >= iov->iov_len; ++cnt) {
|
||||||
|
wret -= iov->iov_len;
|
||||||
|
++iov;
|
||||||
|
--iovcnt;
|
||||||
|
}
|
||||||
|
if (wret) {
|
||||||
|
iov->iov_base =
|
||||||
|
(char *)iov->iov_base + wret;
|
||||||
|
iov->iov_len -= wret;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (wret == 0) {
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: failed writing %zu bytes to `%s'", __func__,
|
||||||
|
left, device);
|
||||||
|
(void) close(fd);
|
||||||
|
if (forked)
|
||||||
|
_exit(1);
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
if (errno == EWOULDBLOCK) {
|
||||||
|
pid_t cpid;
|
||||||
|
|
||||||
|
if (forked) {
|
||||||
|
(void)close(fd);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
cpid = fork();
|
||||||
|
if (cpid < 0) {
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: Cannot fork (%s)", __func__,
|
||||||
|
strerror(errno));
|
||||||
|
(void)close(fd);
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
if (cpid) { /* parent */
|
||||||
|
(void)close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
forked++;
|
||||||
|
/* wait at most tmout seconds */
|
||||||
|
(void)signal(SIGALRM, SIG_DFL);
|
||||||
|
(void)signal(SIGTERM, SIG_DFL); /* XXX */
|
||||||
|
sigfillset(&nset);
|
||||||
|
(void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
|
||||||
|
(void)alarm((u_int)tmout);
|
||||||
|
(void)fcntl(fd, F_SETFL, 0); /* clear O_NONBLOCK */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* We get ENODEV on a slip line if we're running as root,
|
||||||
|
* and EIO if the line just went away.
|
||||||
|
*/
|
||||||
|
if (errno == ENODEV || errno == EIO)
|
||||||
|
break;
|
||||||
|
(void) close(fd);
|
||||||
|
if (forked)
|
||||||
|
_exit(1);
|
||||||
|
(void)snprintf(errbuf, sizeof(errbuf),
|
||||||
|
"%s: Write to line `%s' failed (%s)", __func__,
|
||||||
|
device, strerror(errno));
|
||||||
|
return errbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) close(fd);
|
||||||
|
if (forked)
|
||||||
|
_exit(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue