summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2010-03-10 02:16:04 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2010-03-10 02:16:04 +0000
commit50568f27d680f3a286fdcfaebb5e4f361c4c7e8b (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904
parentd14d0b2c1107f8cf2cb372a38f82146fca1a9a2a (diff)
downloadpw-darwin-50568f27d680f3a286fdcfaebb5e4f361c4c7e8b.tar.gz
pw-darwin-50568f27d680f3a286fdcfaebb5e4f361c4c7e8b.tar.zst
pw-darwin-50568f27d680f3a286fdcfaebb5e4f361c4c7e8b.zip
Create the altix project branch. The altix project will add support
for the SGI Altix 350 to FreeBSD/ia64. The hardware used for porting is a two-module system, consisting of a base compute module and a CPU expansion module. SGI's NUMAFlex architecture can be an excellent platform to test CPU affinity and NUMA-aware features in FreeBSD.
-rw-r--r--adduser/Makefile6
-rw-r--r--adduser/adduser.8480
-rw-r--r--adduser/adduser.conf.5221
-rw-r--r--adduser/adduser.sh1050
-rw-r--r--adduser/rmuser.8210
-rw-r--r--adduser/rmuser.sh361
-rw-r--r--chpass/Makefile49
-rw-r--r--chpass/chpass.1492
-rw-r--r--chpass/chpass.c302
-rw-r--r--chpass/chpass.h79
-rw-r--r--chpass/edit.c296
-rw-r--r--chpass/field.c261
-rw-r--r--chpass/table.c69
-rw-r--r--chpass/util.c182
-rw-r--r--libc/gen/pw_scan.c212
-rw-r--r--libc/gen/pw_scan.h36
-rw-r--r--libc/stdlib/strtonum.c68
-rw-r--r--libutil/_secure_path.c74
-rw-r--r--libutil/flopen.c105
-rw-r--r--libutil/gr_util.c250
-rw-r--r--libutil/libutil.h212
-rw-r--r--libutil/login_cap.c819
-rw-r--r--libutil/login_cap.h166
-rw-r--r--libutil/login_crypt.c50
-rw-r--r--libutil/pw_util.c621
-rw-r--r--pw/Makefile14
-rw-r--r--pw/README22
-rw-r--r--pw/bitmap.c132
-rw-r--r--pw/bitmap.h50
-rw-r--r--pw/cpdir.c130
-rw-r--r--pw/edgroup.c229
-rw-r--r--pw/fileupd.c203
-rw-r--r--pw/grupd.c171
-rw-r--r--pw/psdate.c295
-rw-r--r--pw/psdate.h40
-rw-r--r--pw/pw.81001
-rw-r--r--pw/pw.c456
-rw-r--r--pw/pw.conf.5318
-rw-r--r--pw/pw.h132
-rw-r--r--pw/pw_conf.c516
-rw-r--r--pw/pw_group.c423
-rw-r--r--pw/pw_log.c68
-rw-r--r--pw/pw_nis.c72
-rw-r--r--pw/pw_user.c1274
-rw-r--r--pw/pw_vpw.c316
-rw-r--r--pw/pwupd.c213
-rw-r--r--pw/pwupd.h160
-rw-r--r--pw/rm_r.c75
48 files changed, 0 insertions, 12981 deletions
diff --git a/adduser/Makefile b/adduser/Makefile
deleted file mode 100644
index 0ca2dae..0000000
--- a/adduser/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# $FreeBSD$
-
-SCRIPTS=adduser.sh rmuser.sh
-MAN= adduser.conf.5 adduser.8 rmuser.8
-
-.include <bsd.prog.mk>
diff --git a/adduser/adduser.8 b/adduser/adduser.8
deleted file mode 100644
index 03f7e34..0000000
--- a/adduser/adduser.8
+++ /dev/null
@@ -1,480 +0,0 @@
-.\" Copyright (c) 1995-1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
-.\" All rights reserved.
-.\" Copyright (c) 2002-2004 Michael Telahun Makonnen <mtm@FreeBSD.org>
-.\" 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 AUTHOR 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 AUTHOR 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd March 16, 2008
-.Dt ADDUSER 8
-.Os
-.Sh NAME
-.Nm adduser
-.Nd command for adding new users
-.Sh SYNOPSIS
-.Nm
-.Op Fl CDENShq
-.Op Fl G Ar groups
-.Op Fl L Ar login_class
-.Op Fl M Ar mode
-.Op Fl d Ar partition
-.Op Fl f Ar file
-.Op Fl g Ar login_group
-.Op Fl k Ar dotdir
-.Op Fl m Ar message_file
-.Op Fl s Ar shell
-.Op Fl u Ar uid_start
-.Op Fl w Ar type
-.Sh DESCRIPTION
-The
-.Nm
-utility is a shell script, implemented around the
-.Xr pw 8
-command, for adding new users.
-It creates passwd/group entries, a home directory,
-copies dotfiles and sends the new user a welcome message.
-It supports two modes of operation.
-It may be used interactively
-at the command line to add one user at a time, or it may be directed
-to get the list of new users from a file and operate in batch mode
-without requiring any user interaction.
-.Sh RESTRICTIONS
-.Bl -tag -width indent
-.It username
-Login name.
-The user name is restricted to whatever
-.Xr pw 8
-will accept.
-Generally this means it
-may contain only lowercase characters or digits but cannot begin with the
-.Ql -
-character.
-Maximum length
-is 16 characters.
-The reasons for this limit are historical.
-Given that people have traditionally wanted to break this
-limit for aesthetic reasons, it has never been of great importance to break
-such a basic fundamental parameter in
-.Ux .
-You can change
-.Dv UT_NAMESIZE
-in
-.In utmp.h
-and recompile the
-world; people have done this and it works, but you will have problems
-with any precompiled programs, or source that assumes the 8-character
-name limit, such as NIS.
-The NIS protocol mandates an 8-character username.
-If you need a longer login name for e-mail addresses,
-you can define an alias in
-.Pa /etc/mail/aliases .
-.It "full name"
-This is typically known as the gecos field and usually contains
-the user's full name.
-Additionally, it may contain a comma separated
-list of values such as office number and work and home phones.
-If the
-name contains an ampersand it will be replaced by the capitalized
-login name when displayed by other programs.
-The
-.Ql \&:
-character is not allowed.
-.It shell
-Unless the
-.Fl S
-argument is supplied only valid shells from the shell database
-.Pq Pa /etc/shells
-are allowed.
-In addition,
-either the base name or the full path of the shell may be supplied.
-.It UID
-Automatically generated or your choice.
-It must be less than 32000.
-.It "GID/login group"
-Automatically generated or your choice.
-It must be less than 32000.
-.It password
-You may choose an empty password, disable the password, use a
-randomly generated password or specify your own plaintext password,
-which will be encrypted before being stored in the user database.
-.El
-.Sh UNIQUE GROUPS
-Perhaps you are missing what
-.Em can
-be done with this scheme that falls apart
-with most other schemes.
-With each user in their own group,
-they can safely run with a umask of 002 instead of the usual 022
-and create files in their home directory
-without worrying about others being able to change them.
-.Pp
-For a shared area you create a separate UID/GID (like cvs or ncvs on freefall),
-you place each person that should be able to access this area into that new
-group.
-.Pp
-This model of UID/GID administration allows far greater flexibility than lumping
-users into groups and having to muck with the umask when working in a shared
-area.
-.Pp
-I have been using this model for almost 10 years and found that it works
-for most situations, and has never gotten in the way.
-(Rod Grimes)
-.Sh CONFIGURATION
-The
-.Nm
-utility reads its configuration information from
-.Pa /etc/adduser.conf .
-If this file does not exist, it will use predefined defaults.
-While this file may be edited by hand,
-the safer option is to use the
-.Fl C
-command line argument.
-With this argument,
-.Nm
-will start interactive input, save the answers to its prompts in
-.Pa /etc/adduser.conf ,
-and promptly exit without modifying the user
-database.
-Options specified on the command line will take precedence over
-any values saved in this file.
-.Sh OPTIONS
-.Bl -tag -width indent
-.It Fl C
-Create new configuration file and exit.
-This option is mutually exclusive with the
-.Fl f
-option.
-.It Fl d Ar partition
-Home partition.
-Default partition, under which all user directories
-will be located.
-The
-.Pa /nonexistent
-partition is considered special.
-The
-.Nm
-script will not create and populate a home directory by that name.
-Otherwise,
-by default it attempts to create a home directory.
-.It Fl D
-Do not attempt to create the home directory.
-.It Fl E
-Disable the account.
-This option will lock the account by prepending the string
-.Dq Li *LOCKED*
-to the password field.
-The account may be unlocked
-by the super-user with the
-.Xr pw 8
-command:
-.Pp
-.D1 Nm pw Cm unlock Op Ar name | uid
-.It Fl f Ar file
-Get the list of accounts to create from
-.Ar file .
-If
-.Ar file
-is
-.Dq Fl ,
-then get the list from standard input.
-If this option is specified,
-.Nm
-will operate in batch mode and will not seek any user input.
-If an error is encountered while processing an account, it will write a
-message to standard error and move to the next account.
-The format
-of the input file is described below.
-.It Fl g Ar login_group
-Normally,
-if no login group is specified,
-it is assumed to be the same as the username.
-This option makes
-.Ar login_group
-the default.
-.It Fl G Ar groups
-Space-separated list of additional groups.
-This option allows the user to specify additional groups to add users to.
-The user is a member of these groups in addition to their login group.
-.It Fl h
-Print a summary of options and exit.
-.It Fl k Ar directory
-Copy files from
-.Ar directory
-into the home
-directory of new users;
-.Pa dot.foo
-will be renamed to
-.Pa .foo .
-.It Fl L Ar login_class
-Set default login class.
-.It Fl m Ar file
-Send new users a welcome message from
-.Ar file .
-Specifying a value of
-.Cm no
-for
-.Ar file
-causes no message to be sent to new users.
-Please note that the message
-file can reference the internal variables of the
-.Nm
-script.
-.It Fl M Ar mode
-Create the home directory with permissions set to
-.Ar mode .
-.It Fl N
-Do not read the default configuration file.
-.It Fl q
-Minimal user feedback.
-In particular, the random password will not be echoed to
-standard output.
-.It Fl s Ar shell
-Default shell for new users.
-The
-.Ar shell
-argument may be the base name of the shell or the full path.
-Unless the
-.Fl S
-argument is supplied the shell must exist in
-.Pa /etc/shells
-or be the special shell
-.Em nologin
-to be considered a valid shell.
-.It Fl S
-The existence or validity of the specified shell will not be checked.
-.It Fl u Ar uid
-Use UIDs from
-.Ar uid
-on up.
-.It Fl w Ar type
-Password type.
-The
-.Nm
-utility allows the user to specify what type of password to create.
-The
-.Ar type
-argument may have one of the following values:
-.Bl -tag -width ".Cm random"
-.It Cm no
-Disable the password.
-Instead of an encrypted string, the password field will contain a single
-.Ql *
-character.
-The user may not log in until the super-user
-manually enables the password.
-.It Cm none
-Use an empty string as the password.
-.It Cm yes
-Use a user-supplied string as the password.
-In interactive mode,
-the user will be prompted for the password.
-In batch mode, the
-last (10th) field in the line is assumed to be the password.
-.It Cm random
-Generate a random string and use it as a password.
-The password will be echoed to standard output.
-In addition, it will be available for inclusion in the message file in the
-.Va randompass
-variable.
-.El
-.El
-.Sh FORMAT
-When the
-.Fl f
-option is used, the account information must be stored in a specific
-format.
-All empty lines or lines beginning with a
-.Ql #
-will be ignored.
-All other lines must contain ten colon
-.Pq Ql \&:
-separated fields as described below.
-Command line options do not take precedence
-over values in the fields.
-Only the password field may contain a
-.Ql \&:
-character as part of the string.
-.Pp
-.Sm off
-.D1 Ar name : uid : gid : class : change : expire : gecos : home_dir : shell : password
-.Sm on
-.Bl -tag -width ".Ar password"
-.It Ar name
-Login name.
-This field may not be empty.
-.It Ar uid
-Numeric login user ID.
-If this field is left empty, it will be automatically generated.
-.It Ar gid
-Numeric primary group ID.
-If this field is left empty, a group with the
-same name as the user name will be created and its GID will be used
-instead.
-.It Ar class
-Login class.
-This field may be left empty.
-.It Ar change
-Password ageing.
-This field denotes the password change date for the account.
-The format of this field is the same as the format of the
-.Fl p
-argument to
-.Xr pw 8 .
-It may be
-.Ar dd Ns - Ns Ar mmm Ns - Ns Ar yy Ns Op Ar yy ,
-where
-.Ar dd
-is for the day,
-.Ar mmm
-is for the month in numeric or alphabetical format:
-.Dq Li 10
-or
-.Dq Li Oct ,
-and
-.Ar yy Ns Op Ar yy
-is the four or two digit year.
-To denote a time relative to the current date the format is:
-.No + Ns Ar n Ns Op Ar mhdwoy ,
-where
-.Ar n
-denotes a number, followed by the minutes, hours, days, weeks,
-months or years after which the password must be changed.
-This field may be left empty to turn it off.
-.It Ar expire
-Account expiration.
-This field denotes the expiry date of the account.
-The account may not be used after the specified date.
-The format of this field is the same as that for password ageing.
-This field may be left empty to turn it off.
-.It Ar gecos
-Full name and other extra information about the user.
-.It Ar home_dir
-Home directory.
-If this field is left empty, it will be automatically
-created by appending the username to the home partition.
-The
-.Pa /nonexistent
-home directory is considered special and
-is understood to mean that no home directory is to be
-created for the user.
-.It Ar shell
-Login shell.
-This field should contain either the base name or
-the full path to a valid login shell.
-.It Ar password
-User password.
-This field should contain a plaintext string, which will
-be encrypted before being placed in the user database.
-If the password type is
-.Cm yes
-and this field is empty, it is assumed the account will have an empty password.
-If the password type is
-.Cm random
-and this field is
-.Em not
-empty, its contents will be used
-as a password.
-This field will be ignored if the
-.Fl w
-option is used with a
-.Cm no
-or
-.Cm none
-argument.
-Be careful not to terminate this field with a closing
-.Ql \&:
-because it will be treated as part of the password.
-.El
-.Sh FILES
-.Bl -tag -width ".Pa /etc/adduser.message" -compact
-.It Pa /etc/master.passwd
-user database
-.It Pa /etc/group
-group database
-.It Pa /etc/shells
-shell database
-.It Pa /etc/login.conf
-login classes database
-.It Pa /etc/adduser.conf
-configuration file for
-.Nm
-.It Pa /etc/adduser.message
-message file for
-.Nm
-.It Pa /usr/share/skel
-skeletal login directory
-.It Pa /var/log/adduser
-logfile for
-.Nm
-.El
-.Sh SEE ALSO
-.Xr chpass 1 ,
-.Xr passwd 1 ,
-.Xr adduser.conf 5 ,
-.Xr aliases 5 ,
-.Xr group 5 ,
-.Xr login.conf 5 ,
-.Xr passwd 5 ,
-.Xr shells 5 ,
-.Xr adding_user 8 ,
-.Xr pw 8 ,
-.Xr pwd_mkdb 8 ,
-.Xr rmuser 8 ,
-.Xr vipw 8 ,
-.Xr yp 8
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Fx 2.1 .
-.Sh AUTHORS
-.An -nosplit
-This manual page and the original script, in Perl, was written by
-.An Wolfram Schneider Aq wosch@FreeBSD.org .
-The replacement script, written as a Bourne
-shell script with some enhancements, and the man page modification that
-came with it were done by
-.An Mike Makonnen Aq mtm@identd.net .
-.Sh BUGS
-In order for
-.Nm
-to correctly expand variables such as
-.Va $username
-and
-.Va $randompass
-in the message sent to new users, it must let the shell evaluate
-each line of the message file.
-This means that shell commands can also be embedded in the message file.
-The
-.Nm
-utility attempts to mitigate the possibility of an attacker using this
-feature by refusing to evaluate the file if it is not owned and writable
-only by the root user.
-In addition, shell special characters and operators will have to be
-escaped when used in the message file.
-.Pp
-Also, password ageing and account expiry times are currently settable
-only in batch mode or when specified in
-.Pa /etc/adduser.conf .
-The user should be able to set them in interactive mode as well.
diff --git a/adduser/adduser.conf.5 b/adduser/adduser.conf.5
deleted file mode 100644
index a78aeea..0000000
--- a/adduser/adduser.conf.5
+++ /dev/null
@@ -1,221 +0,0 @@
-.\"
-.\" Copyright (c) 2004 Tom Rhodes
-.\" 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 AUTHOR 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 AUTHOR 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd April 12, 2007
-.Dt ADDUSER.CONF 5
-.Os
-.Sh NAME
-.Nm adduser.conf
-.Nd
-.Xr adduser 8
-configuration file
-.Sh DESCRIPTION
-The
-.Pa /etc/adduser.conf
-file is automatically generated by the
-.Xr adduser 8
-utility when invoked with the
-.Fl C
-command-line option.
-It is not meant to be edited by hand.
-.Pp
-The
-.Pa /etc/adduser.conf
-file is used to pre-set certain configuration options for
-the
-.Xr adduser 8
-utility.
-When
-.Xr adduser 8
-is invoked, it will check to see if this file exists, and
-if so, the configuration will be used or offered as the
-default settings.
-The
-.Nm
-file offers three types of configuration:
-.Bl -bullet
-.It
-Default settings offered by
-.Xr adduser 8 .
-These options are specified in the configuration file and offered
-as the default during every invocation of the
-.Xr adduser 8
-utility.
-.It
-Configuration options which can be set in
-.Nm ,
-but overridden by passing a flag to
-.Xr adduser 8 .
-.It
-Configuration supported by
-.Xr adduser 8
-but not offered by a flag or during initial invocation.
-.El
-.Pp
-In the first case, these options can be set in
-.Nm
-but will still be offered when
-.Xr adduser 8
-is invoked.
-In the second case,
-.Xr adduser 8
-will read the configuration data unless a flag
-has been passed to override it.
-For example, the
-.Va defaultshell
-option.
-In the third case, the configuration will be utilized, but the
-user will never be prompted to modify the default setting by
-either a flag or an
-.Xr adduser 8
-prompt.
-For example, the
-.Va upwexpire
-setting.
-.Pp
-The following configuration options can be set in
-.Nm :
-.Bl -tag -width ".Va defaultgroups" -offset indent
-.It Va defaultLgroup
-The default group new users will be added to.
-.It Va defaultclass
-The default class to place users in as described in
-.Xr login.conf 5 .
-.It Va defaultgroups
-This option is used to specify what other groups the new account
-should be added to.
-.It Va passwdtype
-May be one of
-.Cm no , none , random ,
-or
-.Cm yes ,
-as described in
-.Xr adduser 8 .
-As such, the text is not duplicated here and may be
-read in
-.Xr adduser 8 .
-.It Va homeprefix
-The default home directory prefix, usually
-.Pa /home .
-.It Va defaultshell
-The user's default shell which may be any of the shells listed in
-.Xr shells 5 .
-.It Va udotdir
-Defines the location of the default shell and environment
-configuration files.
-.It Va msgfile
-Location of the default new user message file.
-This message will be sent to all new users if specified
-here or at the
-.Xr adduser 8
-prompt.
-.It Va disableflag
-The default message enclosed in brackets for the
-lock account prompt.
-.It Va upwexpire
-The default password expiration time.
-Format of the date is either a
-.Ux
-time in decimal, or a date in
-.Sm off
-.Ar dd No - Ar mmm No - Ar yy Op Ar yy
-.Sm on
-format, where
-.Ar dd
-is the day,
-.Ar mmm
-is the month in either numeric or
-alphabetic format, and
-.Ar yy Ns Op Ar yy
-is either a two or four digit year.
-This option also accepts a relative date in the form of
-.Sm off
-.Ar n Op Ar m h d w o y
-.Sm on
-where
-.Ar n
-is a decimal, octal (leading 0) or hexadecimal (leading 0x) digit
-followed by the number of Minutes, Hours, Days, Weeks, Months or
-Years from the current date at
-which the expiration time is to be set.
-.It Va uexpire
-The default account expire time.
-The format is similar to the
-.Va upwexpire
-option.
-.It Va ugecos
-The default information to be held in the GECOS field of
-.Pa /etc/master.passwd .
-.It Va uidstart
-The default user ID setting.
-This must be a number above 1000 and fewer than 65534.
-.El
-.Sh EXAMPLES
-The following is an example
-.Nm
-file created with the
-.Fl C
-.Xr adduser 8
-flag and modified.
-.Bd -literal -offset indent
-# Configuration file for adduser(8).
-# NOTE: only *some* variables are saved.
-# Last Modified on Fri Mar 30 14:04:05 EST 2004.
-
-defaultLgroup=
-defaultclass=
-defaultgroups=
-passwdtype=yes
-homeprefix=/home
-defaultshell=/bin/csh
-udotdir=/usr/share/skel
-msgfile=/etc/adduser.msg
-disableflag=
-upwexpire=91d # Expire passwords 91 days after creation.
-.Ed
-.Sh SEE ALSO
-.Xr group 5 ,
-.Xr passwd 5 ,
-.Xr adduser 8 ,
-.Xr pw 8 ,
-.Xr rmuser 8
-.Sh HISTORY
-The
-.Nm
-manual page first appeared in
-.Fx 5.3 .
-.Sh BUGS
-The internal variables documented here may change without notice.
-Do not rely on them.
-To modify this file invoke
-.Xr adduser 8
-with the
-.Fl C
-option instead.
-.Sh AUTHORS
-This manual page was written by
-.An Tom Rhodes Aq trhodes@FreeBSD.org .
diff --git a/adduser/adduser.sh b/adduser/adduser.sh
deleted file mode 100644
index 8e05f33..0000000
--- a/adduser/adduser.sh
+++ /dev/null
@@ -1,1050 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2002-2004 Michael Telahun Makonnen. 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 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.
-#
-# Email: Mike Makonnen <mtm@FreeBSD.Org>
-#
-# $FreeBSD$
-#
-
-# err msg
-# Display $msg on stderr, unless we're being quiet.
-#
-err() {
- if [ -z "$quietflag" ]; then
- echo 1>&2 ${THISCMD}: ERROR: $*
- fi
-}
-
-# info msg
-# Display $msg on stdout, unless we're being quiet.
-#
-info() {
- if [ -z "$quietflag" ]; then
- echo ${THISCMD}: INFO: $*
- fi
-}
-
-# get_nextuid
-# Output the value of $_uid if it is available for use. If it
-# is not, output the value of the next higher uid that is available.
-# If a uid is not specified, output the first available uid, as indicated
-# by pw(8).
-#
-get_nextuid () {
- _uid=$1
- _nextuid=
-
- if [ -z "$_uid" ]; then
- _nextuid="`${PWCMD} usernext | cut -f1 -d:`"
- else
- while : ; do
- ${PWCMD} usershow $_uid > /dev/null 2>&1
- if [ ! "$?" -eq 0 ]; then
- _nextuid=$_uid
- break
- fi
- _uid=$(($_uid + 1))
- done
- fi
- echo $_nextuid
-}
-
-# show_usage
-# Display usage information for this utility.
-#
-show_usage() {
- echo "usage: ${THISCMD} [options]"
- echo " options may include:"
- echo " -C save to the configuration file only"
- echo " -D do not attempt to create the home directory"
- echo " -E disable this account after creation"
- echo " -G additional groups to add accounts to"
- echo " -L login class of the user"
- echo " -M file permission for home directory"
- echo " -N do not read configuration file"
- echo " -S a nonexistent shell is not an error"
- echo " -d home directory"
- echo " -f file from which input will be received"
- echo " -g default login group"
- echo " -h display this usage message"
- echo " -k path to skeleton home directory"
- echo " -m user welcome message file"
- echo " -q absolute minimal user feedback"
- echo " -s shell"
- echo " -u uid to start at"
- echo " -w password type: no, none, yes or random"
-}
-
-# valid_shells
-# Outputs a list of valid shells from /etc/shells. Only the
-# basename of the shell is output.
-#
-valid_shells() {
- _prefix=
- cat ${ETCSHELLS} |
- while read _path _junk ; do
- case $_path in
- \#*|'')
- ;;
- *)
- echo -n "${_prefix}`basename $_path`"
- _prefix=' '
- ;;
- esac
- done
-
- # /usr/sbin/nologin is a special case
- [ -x "${NOLOGIN_PATH}" ] && echo -n " ${NOLOGIN}"
-}
-
-# fullpath_from_shell shell
-# Given $shell, which is either the full path to a shell or
-# the basename component of a valid shell, get the
-# full path to the shell from the /etc/shells file.
-#
-fullpath_from_shell() {
- _shell=$1
- [ -z "$_shell" ] && return 1
-
- # /usr/sbin/nologin is a special case; it needs to be handled
- # before the cat | while loop, since a 'return' from within
- # a subshell will not terminate the function's execution, and
- # the path to the nologin shell might be printed out twice.
- #
- if [ "$_shell" = "${NOLOGIN}" -o \
- "$_shell" = "${NOLOGIN_PATH}" ]; then
- echo ${NOLOGIN_PATH}
- return 0;
- fi
-
- cat ${ETCSHELLS} |
- while read _path _junk ; do
- case "$_path" in
- \#*|'')
- ;;
- *)
- if [ "$_path" = "$_shell" -o \
- "`basename $_path`" = "$_shell" ]; then
- echo $_path
- return 0
- fi
- ;;
- esac
- done
-
- return 1
-}
-
-# shell_exists shell
-# If the given shell is listed in ${ETCSHELLS} or it is
-# the nologin shell this function will return 0.
-# Otherwise, it will return 1. If shell is valid but
-# the path is invalid or it is not executable it
-# will emit an informational message saying so.
-#
-shell_exists() {
- _sh="$1"
- _shellchk="${GREPCMD} '^$_sh$' ${ETCSHELLS} > /dev/null 2>&1"
-
- if ! eval $_shellchk; then
- # The nologin shell is not listed in /etc/shells.
- if [ "$_sh" != "${NOLOGIN_PATH}" ]; then
- err "Invalid shell ($_sh) for user $username."
- return 1
- fi
- fi
- ! [ -x "$_sh" ] &&
- info "The shell ($_sh) does not exist or is not executable."
-
- return 0
-}
-
-# save_config
-# Save some variables to a configuration file.
-# Note: not all script variables are saved, only those that
-# it makes sense to save.
-#
-save_config() {
- echo "# Configuration file for adduser(8)." > ${ADDUSERCONF}
- echo "# NOTE: only *some* variables are saved." >> ${ADDUSERCONF}
- echo "# Last Modified on `${DATECMD}`." >> ${ADDUSERCONF}
- echo '' >> ${ADDUSERCONF}
- echo "defaultHomePerm=$uhomeperm" >> ${ADDUSERCONF}
- echo "defaultLgroup=$ulogingroup" >> ${ADDUSERCONF}
- echo "defaultclass=$uclass" >> ${ADDUSERCONF}
- echo "defaultgroups=$ugroups" >> ${ADDUSERCONF}
- echo "passwdtype=$passwdtype" >> ${ADDUSERCONF}
- echo "homeprefix=$homeprefix" >> ${ADDUSERCONF}
- echo "defaultshell=$ushell" >> ${ADDUSERCONF}
- echo "udotdir=$udotdir" >> ${ADDUSERCONF}
- echo "msgfile=$msgfile" >> ${ADDUSERCONF}
- echo "disableflag=$disableflag" >> ${ADDUSERCONF}
- echo "uidstart=$uidstart" >> ${ADDUSERCONF}
-}
-
-# add_user
-# Add a user to the user database. If the user chose to send a welcome
-# message or lock the account, do so.
-#
-add_user() {
-
- # Is this a configuration run? If so, don't modify user database.
- #
- if [ -n "$configflag" ]; then
- save_config
- return
- fi
-
- _uid=
- _name=
- _comment=
- _gecos=
- _home=
- _group=
- _grouplist=
- _shell=
- _class=
- _dotdir=
- _expire=
- _pwexpire=
- _passwd=
- _upasswd=
- _passwdmethod=
-
- _name="-n '$username'"
- [ -n "$uuid" ] && _uid='-u "$uuid"'
- [ -n "$ulogingroup" ] && _group='-g "$ulogingroup"'
- [ -n "$ugroups" ] && _grouplist='-G "$ugroups"'
- [ -n "$ushell" ] && _shell='-s "$ushell"'
- [ -n "$uclass" ] && _class='-L "$uclass"'
- [ -n "$ugecos" ] && _comment='-c "$ugecos"'
- [ -n "$udotdir" ] && _dotdir='-k "$udotdir"'
- [ -n "$uexpire" ] && _expire='-e "$uexpire"'
- [ -n "$upwexpire" ] && _pwexpire='-p "$upwexpire"'
- if [ -z "$Dflag" -a -n "$uhome" ]; then
- # The /nonexistent home directory is special. It
- # means the user has no home directory.
- if [ "$uhome" = "$NOHOME" ]; then
- _home='-d "$uhome"'
- else
- # Use home directory permissions if specified
- if [ -n "$uhomeperm" ]; then
- _home='-m -d "$uhome" -M "$uhomeperm"'
- else
- _home='-m -d "$uhome"'
- fi
- fi
- elif [ -n "$Dflag" -a -n "$uhome" ]; then
- _home='-d "$uhome"'
- fi
- case $passwdtype in
- no)
- _passwdmethod="-w no"
- _passwd="-h -"
- ;;
- yes)
- # Note on processing the password: The outer double quotes
- # make literal everything except ` and \ and $.
- # The outer single quotes make literal ` and $.
- # We can ensure the \ isn't treated specially by specifying
- # the -r switch to the read command used to obtain the input.
- #
- _passwdmethod="-w yes"
- _passwd="-h 0"
- _upasswd='echo "$upass" |'
- ;;
- none)
- _passwdmethod="-w none"
- ;;
- random)
- _passwdmethod="-w random"
- ;;
- esac
-
- _pwcmd="$_upasswd ${PWCMD} useradd $_uid $_name $_group $_grouplist $_comment"
- _pwcmd="$_pwcmd $_shell $_class $_home $_dotdir $_passwdmethod $_passwd"
- _pwcmd="$_pwcmd $_expire $_pwexpire"
-
- if ! _output=`eval $_pwcmd` ; then
- err "There was an error adding user ($username)."
- return 1
- else
- info "Successfully added ($username) to the user database."
- if [ "random" = "$passwdtype" ]; then
- randompass="$_output"
- info "Password for ($username) is: $randompass"
- fi
- fi
-
- if [ -n "$disableflag" ]; then
- if ${PWCMD} lock $username ; then
- info "Account ($username) is locked."
- else
- info "Account ($username) could NOT be locked."
- fi
- fi
-
- _line=
- _owner=
- _perms=
- if [ -n "$msgflag" ]; then
- [ -r "$msgfile" ] && {
- # We're evaluating the contents of an external file.
- # Let's not open ourselves up for attack. _perms will
- # be empty if it's writeable only by the owner. _owner
- # will *NOT* be empty if the file is owned by root.
- #
- _dir="`dirname $msgfile`"
- _file="`basename $msgfile`"
- _perms=`/usr/bin/find $_dir -name $_file -perm +07022 -prune`
- _owner=`/usr/bin/find $_dir -name $_file -user 0 -prune`
- if [ -z "$_owner" -o -n "$_perms" ]; then
- err "The message file ($msgfile) may be writeable only by root."
- return 1
- fi
- cat "$msgfile" |
- while read _line ; do
- eval echo "$_line"
- done | ${MAILCMD} -s"Welcome" ${username}
- info "Sent welcome message to ($username)."
- }
- fi
-}
-
-# get_user
-# Reads username of the account from standard input or from a global
-# variable containing an account line from a file. The username is
-# required. If this is an interactive session it will prompt in
-# a loop until a username is entered. If it is batch processing from
-# a file it will output an error message and return to the caller.
-#
-get_user() {
- _input=
-
- # No need to take down user names if this is a configuration saving run.
- [ -n "$configflag" ] && return
-
- while : ; do
- if [ -z "$fflag" ]; then
- echo -n "Username: "
- read _input
- else
- _input="`echo "$fileline" | cut -f1 -d:`"
- fi
-
- # There *must* be a username, and it must not exist. If
- # this is an interactive session give the user an
- # opportunity to retry.
- #
- if [ -z "$_input" ]; then
- err "You must enter a username!"
- [ -z "$fflag" ] && continue
- fi
- ${PWCMD} usershow $_input > /dev/null 2>&1
- if [ "$?" -eq 0 ]; then
- err "User exists!"
- [ -z "$fflag" ] && continue
- fi
- break
- done
- username="$_input"
-}
-
-# get_gecos
-# Reads extra information about the user. Can be used both in interactive
-# and batch (from file) mode.
-#
-get_gecos() {
- _input=
-
- # No need to take down additional user information for a configuration run.
- [ -n "$configflag" ] && return
-
- if [ -z "$fflag" ]; then
- echo -n "Full name: "
- read _input
- else
- _input="`echo "$fileline" | cut -f7 -d:`"
- fi
- ugecos="$_input"
-}
-
-# get_shell
-# Get the account's shell. Works in interactive and batch mode. It
-# accepts either the base name of the shell or the full path.
-# If an invalid shell is entered it will simply use the default shell.
-#
-get_shell() {
- _input=
- _fullpath=
- ushell="$defaultshell"
-
- # Make sure the current value of the shell is a valid one
- if [ -z "$Sflag" ]; then
- if ! shell_exists $ushell ; then
- info "Using default shell ${defaultshell}."
- ushell="$defaultshell"
- fi
- fi
-
- if [ -z "$fflag" ]; then
- echo -n "Shell ($shells) [`basename $ushell`]: "
- read _input
- else
- _input="`echo "$fileline" | cut -f9 -d:`"
- fi
- if [ -n "$_input" ]; then
- if [ -n "$Sflag" ]; then
- ushell="$_input"
- else
- _fullpath=`fullpath_from_shell $_input`
- if [ -n "$_fullpath" ]; then
- ushell="$_fullpath"
- else
- err "Invalid shell ($_input) for user $username."
- info "Using default shell ${defaultshell}."
- ushell="$defaultshell"
- fi
- fi
- fi
-}
-
-# get_homedir
-# Reads the account's home directory. Used both with interactive input
-# and batch input.
-#
-get_homedir() {
- _input=
- if [ -z "$fflag" ]; then
- echo -n "Home directory [${homeprefix}/${username}]: "
- read _input
- else
- _input="`echo "$fileline" | cut -f8 -d:`"
- fi
-
- if [ -n "$_input" ]; then
- uhome="$_input"
- # if this is a configuration run, then user input is the home
- # directory prefix. Otherwise it is understood to
- # be $prefix/$user
- #
- [ -z "$configflag" ] && homeprefix="`dirname $uhome`" || homeprefix="$uhome"
- else
- uhome="${homeprefix}/${username}"
- fi
-}
-
-# get_homeperm
-# Reads the account's home directory permissions.
-#
-get_homeperm() {
- uhomeperm=$defaultHomePerm
- _input=
- _prompt=
-
- if [ -n "$uhomeperm" ]; then
- _prompt="Home directory permissions [${uhomeperm}]: "
- else
- _prompt="Home directory permissions (Leave empty for default): "
- fi
- if [ -z "$fflag" ]; then
- echo -n "$_prompt"
- read _input
- fi
-
- if [ -n "$_input" ]; then
- uhomeperm="$_input"
- fi
-}
-
-# get_uid
-# Reads a numeric userid in an interactive or batch session. Automatically
-# allocates one if it is not specified.
-#
-get_uid() {
- uuid=${uidstart}
- _input=
- _prompt=
-
- if [ -n "$uuid" ]; then
- _prompt="Uid [$uuid]: "
- else
- _prompt="Uid (Leave empty for default): "
- fi
- if [ -z "$fflag" ]; then
- echo -n "$_prompt"
- read _input
- else
- _input="`echo "$fileline" | cut -f2 -d:`"
- fi
-
- [ -n "$_input" ] && uuid=$_input
- uuid=`get_nextuid $uuid`
- uidstart=$uuid
-}
-
-# get_class
-# Reads login class of account. Can be used in interactive or batch mode.
-#
-get_class() {
- uclass="$defaultclass"
- _input=
- _class=${uclass:-"default"}
-
- if [ -z "$fflag" ]; then
- echo -n "Login class [$_class]: "
- read _input
- else
- _input="`echo "$fileline" | cut -f4 -d:`"
- fi
-
- [ -n "$_input" ] && uclass="$_input"
-}
-
-# get_logingroup
-# Reads user's login group. Can be used in both interactive and batch
-# modes. The specified value can be a group name or its numeric id.
-# This routine leaves the field blank if nothing is provided and
-# a default login group has not been set. The pw(8) command
-# will then provide a login group with the same name as the username.
-#
-get_logingroup() {
- ulogingroup="$defaultLgroup"
- _input=
-
- if [ -z "$fflag" ]; then
- echo -n "Login group [${ulogingroup:-$username}]: "
- read _input
- else
- _input="`echo "$fileline" | cut -f3 -d:`"
- fi
-
- # Pw(8) will use the username as login group if it's left empty
- [ -n "$_input" ] && ulogingroup="$_input"
-}
-
-# get_groups
-# Read additional groups for the user. It can be used in both interactive
-# and batch modes.
-#
-get_groups() {
- ugroups="$defaultgroups"
- _input=
- _group=${ulogingroup:-"${username}"}
-
- if [ -z "$configflag" ]; then
- [ -z "$fflag" ] && echo -n "Login group is $_group. Invite $username"
- [ -z "$fflag" ] && echo -n " into other groups? [$ugroups]: "
- else
- [ -z "$fflag" ] && echo -n "Enter additional groups [$ugroups]: "
- fi
- read _input
-
- [ -n "$_input" ] && ugroups="$_input"
-}
-
-# get_expire_dates
-# Read expiry information for the account and also for the password. This
-# routine is used only from batch processing mode.
-#
-get_expire_dates() {
- upwexpire="`echo "$fileline" | cut -f5 -d:`"
- uexpire="`echo "$fileline" | cut -f6 -d:`"
-}
-
-# get_password
-# Read the password in batch processing mode. The password field matters
-# only when the password type is "yes" or "random". If the field is empty and the
-# password type is "yes", then it assumes the account has an empty passsword
-# and changes the password type accordingly. If the password type is "random"
-# and the password field is NOT empty, then it assumes the account will NOT
-# have a random password and set passwdtype to "yes."
-#
-get_password() {
- # We may temporarily change a password type. Make sure it's changed
- # back to whatever it was before we process the next account.
- #
- [ -n "$savedpwtype" ] && {
- passwdtype=$savedpwtype
- savedpwtype=
- }
-
- # There may be a ':' in the password
- upass=${fileline#*:*:*:*:*:*:*:*:*:}
-
- if [ -z "$upass" ]; then
- case $passwdtype in
- yes)
- # if it's empty, assume an empty password
- passwdtype=none
- savedpwtype=yes
- ;;
- esac
- else
- case $passwdtype in
- random)
- passwdtype=yes
- savedpwtype=random
- ;;
- esac
- fi
-}
-
-# input_from_file
-# Reads a line of account information from standard input and
-# adds it to the user database.
-#
-input_from_file() {
- _field=
-
- while read -r fileline ; do
- case "$fileline" in
- \#*|'')
- ;;
- *)
- get_user || continue
- get_gecos
- get_uid
- get_logingroup
- get_class
- get_shell
- get_homedir
- get_homeperm
- get_password
- get_expire_dates
- ugroups="$defaultgroups"
-
- add_user
- ;;
- esac
- done
-}
-
-# input_interactive
-# Prompts for user information interactively, and commits to
-# the user database.
-#
-input_interactive() {
- _disable=
- _pass=
- _passconfirm=
- _random="no"
- _emptypass="no"
- _usepass="yes"
- _logingroup_ok="no"
- _groups_ok="no"
- case $passwdtype in
- none)
- _emptypass="yes"
- _usepass="yes"
- ;;
- no)
- _usepass="no"
- ;;
- random)
- _random="yes"
- ;;
- esac
-
- get_user
- get_gecos
- get_uid
-
- # The case where group = user is handled elsewhere, so
- # validate any other groups the user is invited to.
- until [ "$_logingroup_ok" = yes ]; do
- get_logingroup
- _logingroup_ok=yes
- if [ -n "$ulogingroup" -a "$username" != "$ulogingroup" ]; then
- if ! ${PWCMD} show group $ulogingroup > /dev/null 2>&1; then
- echo "Group $ulogingroup does not exist!"
- _logingroup_ok=no
- fi
- fi
- done
- until [ "$_groups_ok" = yes ]; do
- get_groups
- _groups_ok=yes
- for i in $ugroups; do
- if [ "$username" != "$i" ]; then
- if ! ${PWCMD} show group $i > /dev/null 2>&1; then
- echo "Group $i does not exist!"
- _groups_ok=no
- fi
- fi
- done
- done
-
- get_class
- get_shell
- get_homedir
- get_homeperm
-
- while : ; do
- echo -n "Use password-based authentication? [$_usepass]: "
- read _input
- [ -z "$_input" ] && _input=$_usepass
- case $_input in
- [Nn][Oo]|[Nn])
- passwdtype="no"
- ;;
- [Yy][Ee][Ss]|[Yy][Ee]|[Yy])
- while : ; do
- echo -n "Use an empty password? (yes/no) [$_emptypass]: "
- read _input
- [ -n "$_input" ] && _emptypass=$_input
- case $_emptypass in
- [Nn][Oo]|[Nn])
- echo -n "Use a random password? (yes/no) [$_random]: "
- read _input
- [ -n "$_input" ] && _random="$_input"
- case $_random in
- [Yy][Ee][Ss]|[Yy][Ee]|[Yy])
- passwdtype="random"
- break
- ;;
- esac
- passwdtype="yes"
- [ -n "$configflag" ] && break
- trap 'stty echo; exit' 0 1 2 3 15
- stty -echo
- echo -n "Enter password: "
- read -r upass
- echo''
- echo -n "Enter password again: "
- read -r _passconfirm
- echo ''
- stty echo
- # if user entered a blank password
- # explicitly ask again.
- [ -z "$upass" -a -z "$_passconfirm" ] \
- && continue
- ;;
- [Yy][Ee][Ss]|[Yy][Ee]|[Yy])
- passwdtype="none"
- break;
- ;;
- *)
- # invalid answer; repeat the loop
- continue
- ;;
- esac
- if [ "$upass" != "$_passconfirm" ]; then
- echo "Passwords did not match!"
- continue
- fi
- break
- done
- ;;
- *)
- # invalid answer; repeat loop
- continue
- ;;
- esac
- break;
- done
- _disable=${disableflag:-"no"}
- while : ; do
- echo -n "Lock out the account after creation? [$_disable]: "
- read _input
- [ -z "$_input" ] && _input=$_disable
- case $_input in
- [Nn][Oo]|[Nn])
- disableflag=
- ;;
- [Yy][Ee][Ss]|[Yy][Ee]|[Yy])
- disableflag=yes
- ;;
- *)
- # invalid answer; repeat loop
- continue
- ;;
- esac
- break
- done
-
- # Display the information we have so far and prompt to
- # commit it.
- #
- _disable=${disableflag:-"no"}
- [ -z "$configflag" ] && printf "%-10s : %s\n" Username $username
- case $passwdtype in
- yes)
- _pass='*****'
- ;;
- no)
- _pass='<disabled>'
- ;;
- none)
- _pass='<blank>'
- ;;
- random)
- _pass='<random>'
- ;;
- esac
- [ -z "$configflag" ] && printf "%-10s : %s\n" "Password" "$_pass"
- [ -n "$configflag" ] && printf "%-10s : %s\n" "Pass Type" "$passwdtype"
- [ -z "$configflag" ] && printf "%-10s : %s\n" "Full Name" "$ugecos"
- [ -z "$configflag" ] && printf "%-10s : %s\n" "Uid" "$uuid"
- printf "%-10s : %s\n" "Class" "$uclass"
- printf "%-10s : %s %s\n" "Groups" "${ulogingroup:-$username}" "$ugroups"
- printf "%-10s : %s\n" "Home" "$uhome"
- printf "%-10s : %s\n" "Home Mode" "$uhomeperm"
- printf "%-10s : %s\n" "Shell" "$ushell"
- printf "%-10s : %s\n" "Locked" "$_disable"
- while : ; do
- echo -n "OK? (yes/no): "
- read _input
- case $_input in
- [Nn][Oo]|[Nn])
- return 1
- ;;
- [Yy][Ee][Ss]|[Yy][Ee]|[Yy])
- add_user
- ;;
- *)
- continue
- ;;
- esac
- break
- done
- return 0
-}
-
-#### END SUBROUTINE DEFINITION ####
-
-THISCMD=`/usr/bin/basename $0`
-DEFAULTSHELL=/bin/sh
-ADDUSERCONF="${ADDUSERCONF:-/etc/adduser.conf}"
-PWCMD="${PWCMD:-/usr/sbin/pw}"
-MAILCMD="${MAILCMD:-mail}"
-ETCSHELLS="${ETCSHELLS:-/etc/shells}"
-NOHOME="/nonexistent"
-NOLOGIN="nologin"
-NOLOGIN_PATH="/usr/sbin/nologin"
-GREPCMD="/usr/bin/grep"
-DATECMD="/bin/date"
-
-# Set default values
-#
-username=
-uuid=
-uidstart=
-ugecos=
-ulogingroup=
-uclass=
-uhome=
-uhomeperm=
-upass=
-ushell=
-udotdir=/usr/share/skel
-ugroups=
-uexpire=
-upwexpire=
-shells="`valid_shells`"
-passwdtype="yes"
-msgfile=/etc/adduser.msg
-msgflag=
-quietflag=
-configflag=
-fflag=
-infile=
-disableflag=
-Dflag=
-Sflag=
-readconfig="yes"
-homeprefix="/home"
-randompass=
-fileline=
-savedpwtype=
-defaultclass=
-defaultLgroup=
-defaultgroups=
-defaultshell="${DEFAULTSHELL}"
-defaultHomePerm=
-
-# Make sure the user running this program is root. This isn't a security
-# measure as much as it is a useful method of reminding the user to
-# 'su -' before he/she wastes time entering data that won't be saved.
-#
-procowner=${procowner:-`/usr/bin/id -u`}
-if [ "$procowner" != "0" ]; then
- err 'you must be the super-user (uid 0) to use this utility.'
- exit 1
-fi
-
-# Overide from our conf file
-# Quickly go through the commandline line to see if we should read
-# from our configuration file. The actual parsing of the commandline
-# arguments happens after we read in our configuration file (commandline
-# should override configuration file).
-#
-for _i in $* ; do
- if [ "$_i" = "-N" ]; then
- readconfig=
- break;
- fi
-done
-if [ -n "$readconfig" ]; then
- # On a long-lived system, the first time this script is run it
- # will barf upon reading the configuration file for its perl predecessor.
- if ( . ${ADDUSERCONF} > /dev/null 2>&1 ); then
- [ -r ${ADDUSERCONF} ] && . ${ADDUSERCONF} > /dev/null 2>&1
- fi
-fi
-
-# Proccess command-line options
-#
-for _switch ; do
- case $_switch in
- -L)
- defaultclass="$2"
- shift; shift
- ;;
- -C)
- configflag=yes
- shift
- ;;
- -D)
- Dflag=yes
- shift
- ;;
- -E)
- disableflag=yes
- shift
- ;;
- -k)
- udotdir="$2"
- shift; shift
- ;;
- -f)
- [ "$2" != "-" ] && infile="$2"
- fflag=yes
- shift; shift
- ;;
- -g)
- defaultLgroup="$2"
- shift; shift
- ;;
- -G)
- defaultgroups="$2"
- shift; shift
- ;;
- -h)
- show_usage
- exit 0
- ;;
- -d)
- homeprefix="$2"
- shift; shift
- ;;
- -m)
- case "$2" in
- [Nn][Oo])
- msgflag=
- ;;
- *)
- msgflag=yes
- msgfile="$2"
- ;;
- esac
- shift; shift
- ;;
- -M)
- defaultHomePerm=$2
- shift; shift
- ;;
- -N)
- readconfig=
- shift
- ;;
- -w)
- case "$2" in
- no|none|random|yes)
- passwdtype=$2
- ;;
- *)
- show_usage
- exit 1
- ;;
- esac
- shift; shift
- ;;
- -q)
- quietflag=yes
- shift
- ;;
- -s)
- defaultshell="`fullpath_from_shell $2`"
- shift; shift
- ;;
- -S)
- Sflag=yes
- shift
- ;;
- -u)
- uidstart=$2
- shift; shift
- ;;
- esac
-done
-
-# If the -f switch was used, get input from a file. Otherwise,
-# this is an interactive session.
-#
-if [ -n "$fflag" ]; then
- if [ -z "$infile" ]; then
- input_from_file
- elif [ -n "$infile" ]; then
- if [ -r "$infile" ]; then
- input_from_file < $infile
- else
- err "File ($infile) is unreadable or does not exist."
- fi
- fi
-else
- input_interactive
- while : ; do
- if [ -z "$configflag" ]; then
- echo -n "Add another user? (yes/no): "
- else
- echo -n "Re-edit the default configuration? (yes/no): "
- fi
- read _input
- case $_input in
- [Yy][Ee][Ss]|[Yy][Ee]|[Yy])
- uidstart=`get_nextuid $uidstart`
- input_interactive
- continue
- ;;
- [Nn][Oo]|[Nn])
- echo "Goodbye!"
- ;;
- *)
- continue
- ;;
- esac
- break
- done
-fi
diff --git a/adduser/rmuser.8 b/adduser/rmuser.8
deleted file mode 100644
index 68a99b5..0000000
--- a/adduser/rmuser.8
+++ /dev/null
@@ -1,210 +0,0 @@
-.\" Copyright 1995, 1996, 1997
-.\" Guy Helmer, Ames, Iowa 50014. 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 as
-.\" the first lines of this file unmodified.
-.\" 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. 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 GUY HELMER ``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 GUY HELMER 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd May 10, 2002
-.Dt RMUSER 8
-.Os
-.Sh NAME
-.Nm rmuser
-.Nd remove users from the system
-.Sh SYNOPSIS
-.Nm
-.Op Fl yv
-.Op Fl f Ar file
-.Op Ar username ...
-.Sh DESCRIPTION
-The
-.Nm
-utility removes one or more users submitted on the command line
-or from a file.
-In removing a user from the system, this utility:
-.Bl -enum
-.It
-Removes the user's
-.Xr crontab 1
-entry (if any).
-.It
-Removes any
-.Xr at 1
-jobs belonging to the user.
-.It
-Sends a
-.Dv SIGKILL
-signal to all processes owned by the user.
-.It
-Removes the user from the system's local password file.
-.It
-Removes the user's home directory (if it is owned by the user),
-including handling of symbolic links in the path to the actual home
-directory.
-.It
-Removes the incoming mail and POP daemon mail files belonging to the
-user from
-.Pa /var/mail .
-.It
-Removes all files owned by the user from
-.Pa /tmp , /var/tmp ,
-and
-.Pa /var/tmp/vi.recover .
-.It
-Removes the username from all groups to which it belongs in
-.Pa /etc/group .
-(If a group becomes empty and the group name is the same as the username,
-the group is removed; this complements
-.Xr adduser 8 Ns 's
-per-user unique groups.)
-.It
-Removes all message queues, shared memory segments and
-semaphores owned by the user.
-.El
-.Pp
-The
-.Nm
-utility refuses to remove users whose UID is 0 (typically root), since
-certain actions (namely, killing all the user's processes, and perhaps
-removing the user's home directory) would cause damage to a running system.
-If it is necessary to remove a user whose UID is 0, see
-.Xr vipw 8
-for information on directly editing the password file.
-.Pp
-If
-.Nm
-was not invoked with the
-.Fl y
-option, it will
-show the selected user's password file entry and ask for confirmation
-that the user be removed.
-It will then ask for confirmation to delete
-the user's home directory.
-If the answer is in the affirmative, the home
-directory and any files and subdirectories under it will be deleted only if
-they are owned by the user.
-See
-.Xr pw 8
-for more details.
-.Pp
-As
-.Nm
-operates, it informs the user regarding the current activity.
-If any
-errors occur, they are posted to standard error and, if it is possible for
-.Nm
-to continue, it will.
-.Pp
-The options are as follows:
-.Bl -tag -width ".Ar username"
-.It Fl f Ar file
-The
-.Nm
-utility will get a list of users to be removed from
-.Ar file ,
-which will contain one user per line.
-Anything following a hash mark
-.Pq Ql # ,
-including the hash mark itself, is considered a comment and will not
-be processed.
-If the file is owned by anyone other than a user with
-UID 0, or is writable by anyone other than the owner,
-.Nm
-will refuse to continue.
-.It Fl y
-Implicitly answer
-.Dq Li yes
-to any and all prompts.
-Currently, this includes
-prompts on whether to remove the specified user and whether to remove
-the home directory.
-This option requires that either the
-.Fl f
-option be used, or one or more user names be given as command line
-arguments.
-.It Fl v
-Enable verbose mode.
-Normally,
-the output includes one line per removed user;
-however,
-with this option
-.Nm
-will be much more chatty about the steps taken.
-.It Ar username
-Identifies one or more users to be removed; if not present,
-.Nm
-interactively asks for one or more users to be removed.
-.El
-.Sh FILES
-.Bl -tag -compact
-.It Pa /etc/master.passwd
-.It Pa /etc/passwd
-.It Pa /etc/group
-.It Pa /etc/spwd.db
-.It Pa /etc/pwd.db
-.El
-.Sh SEE ALSO
-.Xr at 1 ,
-.Xr chpass 1 ,
-.Xr crontab 1 ,
-.Xr finger 1 ,
-.Xr passwd 1 ,
-.Xr group 5 ,
-.Xr passwd 5 ,
-.Xr adduser 8 ,
-.Xr pw 8 ,
-.Xr pwd_mkdb 8 ,
-.Xr vipw 8
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Fx 2.2 .
-.Sh BUGS
-The
-.Nm
-utility does not comprehensively search the file system for all files
-owned by the removed user and remove them; to do so on a system
-of any size is prohibitively slow and I/O intensive.
-It is also unable to remove symbolic links that were created by the
-user in
-.Pa /tmp
-or
-.Pa /var/tmp ,
-as symbolic links on
-.Bx 4.4
-file systems do not contain information
-as to who created them.
-Also, there may be other files created in
-.Pa /var/mail
-other than
-.Pa /var/mail/ Ns Ar username
-and
-.Pa /var/mail/.pop. Ns Ar username
-that are not owned by the removed user but should be removed.
-.Pp
-The
-.Nm
-utility has no knowledge of YP/NIS, and it operates only on the
-local password file.
diff --git a/adduser/rmuser.sh b/adduser/rmuser.sh
deleted file mode 100644
index 6b09225..0000000
--- a/adduser/rmuser.sh
+++ /dev/null
@@ -1,361 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2002, 2003 Michael Telahun Makonnen. 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 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.
-#
-# Email: Mike Makonnen <mtm@FreeBSD.Org>
-#
-# $FreeBSD$
-#
-
-ATJOBDIR="/var/at/jobs"
-CRONJOBDIR="/var/cron/tabs"
-MAILSPOOL="/var/mail"
-SIGKILL="-KILL"
-TEMPDIRS="/tmp /var/tmp"
-THISCMD=`/usr/bin/basename $0`
-PWCMD="${PWCMD:-/usr/sbin/pw}"
-
-# err msg
-# Display $msg on stderr.
-#
-err() {
- echo 1>&2 ${THISCMD}: $*
-}
-
-# verbose
-# Returns 0 if verbose mode is set, 1 if it is not.
-#
-verbose() {
- [ -n "$vflag" ] && return 0 || return 1
-}
-
-# rm_files login
-# Removes files or empty directories belonging to $login from various
-# temporary directories.
-#
-rm_files() {
- # The argument is required
- [ -n $1 ] && login=$1 || return
-
- totalcount=0
- for _dir in ${TEMPDIRS} ; do
- filecount=0
- if [ ! -d $_dir ]; then
- err "$_dir is not a valid directory."
- continue
- fi
- verbose && echo -n "Removing files owned by ($login) in $_dir:"
- filecount=`find 2>/dev/null "$_dir" -user "$login" -delete -print |
- wc -l | sed 's/ *//'`
- verbose && echo " $filecount removed."
- totalcount=$(($totalcount + $filecount))
- done
- ! verbose && [ $totalcount -ne 0 ] && echo -n " files($totalcount)"
-}
-
-# rm_mail login
-# Removes unix mail and pop daemon files belonging to the user
-# specified in the $login argument.
-#
-rm_mail() {
- # The argument is required
- [ -n $1 ] && login=$1 || return
-
- verbose && echo -n "Removing mail spool(s) for ($login):"
- if [ -f ${MAILSPOOL}/$login ]; then
- verbose && echo -n " ${MAILSPOOL}/$login" ||
- echo -n " mailspool"
- rm ${MAILSPOOL}/$login
- fi
- if [ -f ${MAILSPOOL}/.${login}.pop ]; then
- verbose && echo -n " ${MAILSPOOL}/.${login}.pop" ||
- echo -n " pop3"
- rm ${MAILSPOOL}/.${login}.pop
- fi
- verbose && echo '.'
-}
-
-# kill_procs login
-# Send a SIGKILL to all processes owned by $login.
-#
-kill_procs() {
- # The argument is required
- [ -n $1 ] && login=$1 || return
-
- verbose && echo -n "Terminating all processes owned by ($login):"
- killcount=0
- proclist=`ps 2>/dev/null -U $login | grep -v '^\ *PID' | awk '{print $1}'`
- for _pid in $proclist ; do
- kill 2>/dev/null ${SIGKILL} $_pid
- killcount=$(($killcount + 1))
- done
- verbose && echo " ${SIGKILL} signal sent to $killcount processes."
- ! verbose && [ $killcount -ne 0 ] && echo -n " processes(${killcount})"
-}
-
-# rm_at_jobs login
-# Remove at (1) jobs belonging to $login.
-#
-rm_at_jobs() {
- # The argument is required
- [ -n $1 ] && login=$1 || return
-
- atjoblist=`find 2>/dev/null ${ATJOBDIR} -maxdepth 1 -user $login -print`
- jobcount=0
- verbose && echo -n "Removing at(1) jobs owned by ($login):"
- for _atjob in $atjoblist ; do
- rm -f $_atjob
- jobcount=$(($jobcount + 1))
- done
- verbose && echo " $jobcount removed."
- ! verbose && [ $jobcount -ne 0 ] && echo -n " at($jobcount)"
-}
-
-# rm_crontab login
-# Removes crontab file belonging to user $login.
-#
-rm_crontab() {
- # The argument is required
- [ -n $1 ] && login=$1 || return
-
- verbose && echo -n "Removing crontab for ($login):"
- if [ -f ${CRONJOBDIR}/$login ]; then
- verbose && echo -n " ${CRONJOBDIR}/$login" || echo -n " crontab"
- rm -f ${CRONJOBDIR}/$login
- fi
- verbose && echo '.'
-}
-
-# rm_ipc login
-# Remove all IPC mechanisms which are owned by $login.
-#
-rm_ipc() {
- verbose && echo -n "Removing IPC mechanisms"
- for i in s m q; do
- ipcs -$i |
- awk -v i=$i -v login=$1 '$1 == i && $5 == login { print $2 }' |
- xargs -n 1 ipcrm -$i
- done
- verbose && echo '.'
-}
-
-# rm_user login
-# Remove user $login from the system. This subroutine makes use
-# of the pw(8) command to remove a user from the system. The pw(8)
-# command will remove the specified user from the user database
-# and group file and remove any crontabs. His home
-# directory will be removed if it is owned by him and contains no
-# files or subdirectories owned by other users. Mail spool files will
-# also be removed.
-#
-rm_user() {
- # The argument is required
- [ -n $1 ] && login=$1 || return
-
- verbose && echo -n "Removing user ($login)"
- [ -n "$pw_rswitch" ] && {
- verbose && echo -n " (including home directory)"
- ! verbose && echo -n " home"
- }
- ! verbose && echo -n " passwd"
- verbose && echo -n " from the system:"
- ${PWCMD} userdel -n $login $pw_rswitch
- verbose && echo ' Done.'
-}
-
-# prompt_yesno msg
-# Prompts the user with a $msg. The answer is expected to be
-# yes, no, or some variation thereof. This subroutine returns 0
-# if the answer was yes, 1 if it was not.
-#
-prompt_yesno() {
- # The argument is required
- [ -n "$1" ] && msg="$1" || return
-
- while : ; do
- echo -n "$msg"
- read _ans
- case $_ans in
- [Nn][Oo]|[Nn])
- return 1
- ;;
- [Yy][Ee][Ss]|[Yy][Ee]|[Yy])
- return 0
- ;;
- *)
- ;;
- esac
- done
-}
-
-# show_usage
-# (no arguments)
-# Display usage message.
-#
-show_usage() {
- echo "usage: ${THISCMD} [-yv] [-f file] [user ...]"
- echo " if the -y switch is used, either the -f switch or"
- echo " one or more user names must be given"
-}
-
-#### END SUBROUTINE DEFENITION ####
-
-ffile=
-fflag=
-procowner=
-pw_rswitch=
-userlist=
-yflag=
-vflag=
-
-procowner=`/usr/bin/id -u`
-if [ "$procowner" != "0" ]; then
- err 'you must be root (0) to use this utility.'
- exit 1
-fi
-
-args=`getopt 2>/dev/null yvf: $*`
-if [ "$?" != "0" ]; then
- show_usage
- exit 1
-fi
-set -- $args
-for _switch ; do
- case $_switch in
- -y)
- yflag=1
- shift
- ;;
- -v)
- vflag=1
- shift
- ;;
- -f)
- fflag=1
- ffile="$2"
- shift; shift
- ;;
- --)
- shift
- break
- ;;
- esac
-done
-
-# Get user names from a file if the -f switch was used. Otherwise,
-# get them from the commandline arguments. If we're getting it
-# from a file, the file must be owned by and writable only by root.
-#
-if [ $fflag ]; then
- _insecure=`find $ffile ! -user 0 -or -perm +0022`
- if [ -n "$_insecure" ]; then
- err "file ($ffile) must be owned by and writeable only by root."
- exit 1
- fi
- if [ -r "$ffile" ]; then
- userlist=`cat $ffile | while read _user _junk ; do
- case $_user in
- \#*|'')
- ;;
- *)
- echo -n "$userlist $_user"
- ;;
- esac
- done`
- fi
-else
- while [ $1 ] ; do
- userlist="$userlist $1"
- shift
- done
-fi
-
-# If the -y or -f switch has been used and the list of users to remove
-# is empty it is a fatal error. Otherwise, prompt the user for a list
-# of one or more user names.
-#
-if [ ! "$userlist" ]; then
- if [ $fflag ]; then
- err "($ffile) does not exist or does not contain any user names."
- exit 1
- elif [ $yflag ]; then
- show_usage
- exit 1
- else
- echo -n "Please enter one or more usernames: "
- read userlist
- fi
-fi
-
-_user=
-_uid=
-for _user in $userlist ; do
- # Make sure the name exists in the passwd database and that it
- # does not have a uid of 0
- #
- userrec=`pw 2>/dev/null usershow -n $_user`
- if [ "$?" != "0" ]; then
- err "user ($_user) does not exist in the password database."
- continue
- fi
- _uid=`echo $userrec | awk -F: '{print $3}'`
- if [ "$_uid" = "0" ]; then
- err "user ($_user) has uid 0. You may not remove this user."
- continue
- fi
-
- # If the -y switch was not used ask for confirmation to remove the
- # user and home directory.
- #
- if [ -z "$yflag" ]; then
- echo "Matching password entry:"
- echo
- echo $userrec
- echo
- if ! prompt_yesno "Is this the entry you wish to remove? " ; then
- continue
- fi
- _homedir=`echo $userrec | awk -F: '{print $9}'`
- if prompt_yesno "Remove user's home directory ($_homedir)? "; then
- pw_rswitch="-r"
- fi
- else
- pw_rswitch="-r"
- fi
-
- # Disable any further attempts to log into this account
- ${PWCMD} 2>/dev/null lock $_user
-
- # Remove crontab, mail spool, etc. Then obliterate the user from
- # the passwd and group database.
- #
- ! verbose && echo -n "Removing user ($_user):"
- rm_crontab $_user
- rm_at_jobs $_user
- rm_ipc $_user
- kill_procs $_user
- rm_files $_user
- rm_mail $_user
- rm_user $_user
- ! verbose && echo "."
-done
diff --git a/chpass/Makefile b/chpass/Makefile
deleted file mode 100644
index a5571d7..0000000
--- a/chpass/Makefile
+++ /dev/null
@@ -1,49 +0,0 @@
-# @(#)Makefile 8.2 (Berkeley) 4/2/94
-# $FreeBSD$
-
-.include <bsd.own.mk>
-
-.PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../lib/libc/gen
-
-PROG= chpass
-SRCS= chpass.c edit.c field.c pw_scan.c table.c util.c
-BINOWN= root
-BINMODE=4555
-.if ${MK_NIS} != "no"
-CFLAGS+= -DYP
-.endif
-#Some people need this, uncomment to activate
-#CFLAGS+=-DRESTRICT_FULLNAME_CHANGE
-CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../lib/libc/gen -I.
-
-DPADD= ${LIBCRYPT} ${LIBUTIL}
-LDADD= -lcrypt -lutil
-.if ${MK_NIS} != "no"
-DPADD+= ${LIBYPCLNT}
-LDADD+= -lypclnt
-.endif
-
-LINKS= ${BINDIR}/chpass ${BINDIR}/chfn
-LINKS+= ${BINDIR}/chpass ${BINDIR}/chsh
-.if ${MK_NIS} != "no"
-LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchpass
-LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchfn
-LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchsh
-.endif
-
-MLINKS= chpass.1 chfn.1 chpass.1 chsh.1
-.if ${MK_NIS} != "no"
-MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1
-.endif
-
-beforeinstall:
-.for i in chpass chfn chsh ypchpass ypchfn ypchsh
- -chflags noschg ${DESTDIR}${BINDIR}/$i
-.endfor
-
-.if !defined(NO_FSCHG)
-afterinstall:
- -chflags schg ${DESTDIR}${BINDIR}/chpass
-.endif
-
-.include <bsd.prog.mk>
diff --git a/chpass/chpass.1 b/chpass/chpass.1
deleted file mode 100644
index a926607..0000000
--- a/chpass/chpass.1
+++ /dev/null
@@ -1,492 +0,0 @@
-.\" Copyright (c) 1988, 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. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. 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.
-.\"
-.\" @(#)chpass.1 8.2 (Berkeley) 12/30/93
-.\" $FreeBSD$
-.\"
-.Dd December 30, 1993
-.Dt CHPASS 1
-.Os
-.Sh NAME
-.Nm chpass ,
-.Nm chfn ,
-.Nm chsh ,
-.Nm ypchpass ,
-.Nm ypchfn ,
-.Nm ypchsh
-.Nd add or change user database information
-.Sh SYNOPSIS
-.Nm
-.Op Fl a Ar list
-.Op Fl p Ar encpass
-.Op Fl e Ar expiretime
-.Op Fl s Ar newshell
-.Op user
-.Nm
-.Op Fl oly
-.Op Fl a Ar list
-.Op Fl p Ar encpass
-.Op Fl e Ar expiretime
-.Op Fl s Ar newshell
-.Op Fl d Ar domain
-.Op Fl h Ar host
-.Op user
-.Sh DESCRIPTION
-The
-.Nm
-utility
-allows editing of the user database information associated
-with
-.Ar user
-or, by default, the current user.
-.Pp
-The
-.Nm chfn ,
-.Nm chsh ,
-.Nm ypchpass ,
-.Nm ypchfn
-and
-.Nm ypchsh
-utilities behave identically to
-.Nm .
-(There is only one program.)
-.Pp
-The information is formatted and supplied to an editor for changes.
-.Pp
-Only the information that the user is allowed to change is displayed.
-.Pp
-The options are as follows:
-.Bl -tag -width indent
-.It Fl a
-The super-user is allowed to directly supply a user database
-entry, in the format specified by
-.Xr passwd 5 ,
-as an argument.
-This argument must be a colon
-.Pq Dq \&:
-separated list of all the
-user database fields, although they may be empty.
-.It Fl p
-The super-user is allowed to directly supply an encrypted password field,
-in the format used by
-.Xr crypt 3 ,
-as an argument.
-.It Fl e Ar expiretime
-Change the account expire time.
-This option is used to set the expire time
-from a script as if it was done in the interactive editor.
-.It Fl s Ar newshell
-Attempt to change the user's shell to
-.Ar newshell .
-.El
-.Pp
-Possible display items are as follows:
-.Pp
-.Bl -tag -width "Other Information:" -compact -offset indent
-.It Login:
-user's login name
-.It Password:
-user's encrypted password
-.It Uid:
-user's login
-.It Gid:
-user's login group
-.It Class:
-user's general classification
-.It Change:
-password change time
-.It Expire:
-account expiration time
-.It Full Name:
-user's real name
-.It Office Location:
-user's office location (1)
-.It Office Phone:
-user's office phone (1)
-.It Home Phone:
-user's home phone (1)
-.It Other Information:
-any locally defined parameters for user (1)
-.It Home Directory:
-user's home directory
-.It Shell:
-user's login shell
-.Pp
-.It NOTE(1) -
-In the actual master.passwd file, these fields are comma-delimited
-fields embedded in the FullName field.
-.El
-.Pp
-The
-.Ar login
-field is the user name used to access the computer account.
-.Pp
-The
-.Ar password
-field contains the encrypted form of the user's password.
-.Pp
-The
-.Ar uid
-field is the number associated with the
-.Ar login
-field.
-Both of these fields should be unique across the system (and often
-across a group of systems) as they control file access.
-.Pp
-While it is possible to have multiple entries with identical login names
-and/or identical user id's, it is usually a mistake to do so.
-Routines
-that manipulate these files will often return only one of the multiple
-entries, and that one by random selection.
-.Pp
-The
-.Ar gid
-field is the group that the user will be placed in at login.
-Since
-.Bx
-supports multiple groups (see
-.Xr groups 1 )
-this field currently has little special meaning.
-This field may be filled in with either a number or a group name (see
-.Xr group 5 ) .
-.Pp
-The
-.Ar class
-field references class descriptions in
-.Pa /etc/login.conf
-and is typically used to initialize the user's system resource limits
-when they login.
-.Pp
-The
-.Ar change
-field is the date by which the password must be changed.
-.Pp
-The
-.Ar expire
-field is the date on which the account expires.
-.Pp
-Both the
-.Ar change
-and
-.Ar expire
-fields should be entered in the form
-.Dq month day year
-where
-.Ar month
-is the month name (the first three characters are sufficient),
-.Ar day
-is the day of the month, and
-.Ar year
-is the year.
-.Pp
-Five fields are available for storing the user's
-.Ar full name , office location ,
-.Ar work
-and
-.Ar home telephone
-numbers and finally
-.Ar other information
-which is a single comma delimited string to represent any additional
-gecos fields (typically used for site specific user information).
-Note that
-.Xr finger 1
-will display the office location and office phone together under the
-heading
-.Ar Office: .
-.Pp
-The user's
-.Ar home directory
-is the full
-.Ux
-path name where the user
-will be placed at login.
-.Pp
-The
-.Ar shell
-field is the command interpreter the user prefers.
-If the
-.Ar shell
-field is empty, the Bourne shell,
-.Pa /bin/sh ,
-is assumed.
-When altering a login shell, and not the super-user, the user
-may not change from a non-standard shell or to a non-standard
-shell.
-Non-standard is defined as a shell not found in
-.Pa /etc/shells .
-.Pp
-Once the information has been verified,
-.Nm
-uses
-.Xr pwd_mkdb 8
-to update the user database.
-.Sh ENVIRONMENT
-The
-.Xr vi 1
-editor will be used unless the environment variable
-.Ev EDITOR
-is set to
-an alternate editor.
-When the editor terminates, the information is re-read and used to
-update the user database itself.
-Only the user, or the super-user, may edit the information associated
-with the user.
-.Pp
-See
-.Xr pwd_mkdb 8
-for an explanation of the impact of setting the
-.Ev PW_SCAN_BIG_IDS
-environment variable.
-.Sh NIS INTERACTION
-The
-.Nm
-utility can also be used in conjunction with NIS, however some restrictions
-apply.
-Currently,
-.Nm
-can only make changes to the NIS passwd maps through
-.Xr rpc.yppasswdd 8 ,
-which normally only permits changes to a user's password, shell and GECOS
-fields.
-Except when invoked by the super-user on the NIS master server,
-.Nm
-(and, similarly,
-.Xr passwd 1 )
-cannot use the
-.Xr rpc.yppasswdd 8
-server to change other user information or
-add new records to the NIS passwd maps.
-Furthermore,
-.Xr rpc.yppasswdd 8
-requires password authentication before it will make any
-changes.
-The only user allowed to submit changes without supplying
-a password is the super-user on the NIS master server; all other users,
-including those with root privileges on NIS clients (and NIS slave
-servers) must enter a password.
-(The super-user on the NIS master is allowed to bypass these restrictions
-largely for convenience: a user with root access
-to the NIS master server already has the privileges required to make
-updates to the NIS maps, but editing the map source files by hand can
-be cumbersome.
-.Pp
-Note: these exceptions only apply when the NIS master server is a
-.Fx
-system).
-.Pp
-Consequently, except where noted, the following restrictions apply when
-.Nm
-is used with NIS:
-.Bl -enum -offset indent
-.It
-.Em "Only the shell and GECOS information may be changed" .
-All other
-fields are restricted, even when
-.Nm
-is invoked by the super-user.
-While support for
-changing other fields could be added, this would lead to
-compatibility problems with other NIS-capable systems.
-Even though the super-user may supply data for other fields
-while editing an entry, the extra information (other than the
-password -- see below) will be silently discarded.
-.Pp
-Exception: the super-user on the NIS master server is permitted to
-change any field.
-.Pp
-.It
-.Em "Password authentication is required" .
-The
-.Nm
-utility will prompt for the user's NIS password before effecting
-any changes.
-If the password is invalid, all changes will be
-discarded.
-.Pp
-Exception: the super-user on the NIS master server is allowed to
-submit changes without supplying a password.
-(The super-user may
-choose to turn off this feature using the
-.Fl o
-flag, described below.)
-.It
-.Em "Adding new records to the local password database is discouraged" .
-The
-.Nm
-utility will allow the administrator to add new records to the
-local password database while NIS is enabled, but this can lead to
-some confusion since the new records are appended to the end of
-the master password file, usually after the special NIS '+' entries.
-The administrator should use
-.Xr vipw 8
-to modify the local password
-file when NIS is running.
-.Pp
-The super-user on the NIS master server is permitted to add new records
-to the NIS password maps, provided the
-.Xr rpc.yppasswdd 8
-server has been started with the
-.Fl a
-flag to permitted additions (it refuses them by default).
-The
-.Nm
-utility tries to update the local password database by default; to update the
-NIS maps instead, invoke chpass with the
-.Fl y
-flag.
-.It
-.Em "Password changes are not permitted".
-Users should use
-.Xr passwd 1
-or
-.Xr yppasswd 1
-to change their NIS passwords.
-The super-user is allowed to specify
-a new password (even though the
-.Dq Password:
-field does not show
-up in the editor template, the super-user may add it back by hand),
-but even the super-user must supply the user's original password
-otherwise
-.Xr rpc.yppasswdd 8
-will refuse to update the NIS maps.
-.Pp
-Exception: the super-user on the NIS master server is permitted to
-change a user's NIS password with
-.Nm .
-.El
-.Pp
-There are also a few extra option flags that are available when
-.Nm
-is compiled with NIS support:
-.Bl -tag -width indent
-.It Fl l
-Force
-.Nm
-to modify the local copy of a user's password
-information in the event that a user exists in both
-the local and NIS databases.
-.It Fl y
-Opposite effect of
-.Fl l .
-This flag is largely redundant since
-.Nm
-operates on NIS entries by default if NIS is enabled.
-.It Fl d Ar domain
-Specify a particular NIS domain.
-The
-.Nm
-utility uses the system domain name by default, as set by the
-.Xr domainname 1
-utility.
-The
-.Fl d
-option can be used to override a default, or to specify a domain
-when the system domain name is not set.
-.It Fl h Ar host
-Specify the name or address of an NIS server to query.
-Normally,
-.Nm
-will communicate with the NIS master host specified in the
-.Pa master.passwd
-or
-.Pa passwd
-maps.
-On hosts that have not been configured as NIS clients, there is
-no way for the program to determine this information unless the user
-provides the hostname of a server.
-Note that the specified hostname need
-not be that of the NIS master server; the name of any server, master or
-slave, in a given NIS domain will do.
-.Pp
-When using the
-.Fl d
-option, the hostname defaults to
-.Dq localhost .
-The
-.Fl h
-option can be used in conjunction with the
-.Fl d
-option, in which case the user-specified hostname will override
-the default.
-.Pp
-.It Fl o
-Force the use of RPC-based updates when communicating with
-.Xr rpc.yppasswdd 8
-.Pq Dq old-mode .
-When invoked by the super-user on the NIS master server,
-.Nm
-allows unrestricted changes to the NIS passwd maps using dedicated,
-non-RPC-based mechanism (in this case, a
-.Ux
-domain socket).
-The
-.Fl o
-flag can be used to force
-.Nm
-to use the standard update mechanism instead.
-This option is provided
-mainly for testing purposes.
-.El
-.Sh FILES
-.Bl -tag -width /etc/master.passwd -compact
-.It Pa /etc/master.passwd
-the user database
-.It Pa /etc/passwd
-a Version 7 format password file
-.It Pa /etc/chpass.XXXXXX
-temporary copy of the password file
-.It Pa /etc/shells
-the list of approved shells
-.El
-.Sh SEE ALSO
-.Xr finger 1 ,
-.Xr login 1 ,
-.Xr passwd 1 ,
-.Xr getusershell 3 ,
-.Xr login.conf 5 ,
-.Xr passwd 5 ,
-.Xr pw 8 ,
-.Xr pwd_mkdb 8 ,
-.Xr vipw 8
-.Rs
-.%A Robert Morris
-and
-.%A Ken Thompson
-.%T "UNIX Password security"
-.Re
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Bx 4.3 Reno .
-.Sh BUGS
-User information should (and eventually will) be stored elsewhere.
diff --git a/chpass/chpass.c b/chpass/chpass.c
deleted file mode 100644
index 2504e68..0000000
--- a/chpass/chpass.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*-
- * Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project by
- * ThinkSec AS and NAI Labs, the Security Research Division of Network
- * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * 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 University of
- * California, Berkeley and its contributors.
- * 4. 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 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1988, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)chpass.c 8.4 (Berkeley) 4/2/94";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-
-#include <err.h>
-#include <errno.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#ifdef YP
-#include <ypclnt.h>
-#endif
-
-#include <pw_scan.h>
-#include <libutil.h>
-
-#include "chpass.h"
-
-int master_mode;
-
-static void baduser(void);
-static void usage(void);
-
-int
-main(int argc, char *argv[])
-{
- enum { NEWSH, LOADENTRY, EDITENTRY, NEWPW, NEWEXP } op;
- struct passwd lpw, *old_pw, *pw;
- int ch, pfd, tfd;
- const char *password;
- char *arg = NULL;
- uid_t uid;
-#ifdef YP
- struct ypclnt *ypclnt;
- const char *yp_domain = NULL, *yp_host = NULL;
-#endif
-
- pw = old_pw = NULL;
- op = EDITENTRY;
-#ifdef YP
- while ((ch = getopt(argc, argv, "a:p:s:e:d:h:loy")) != -1)
-#else
- while ((ch = getopt(argc, argv, "a:p:s:e:")) != -1)
-#endif
- switch (ch) {
- case 'a':
- op = LOADENTRY;
- arg = optarg;
- break;
- case 's':
- op = NEWSH;
- arg = optarg;
- break;
- case 'p':
- op = NEWPW;
- arg = optarg;
- break;
- case 'e':
- op = NEWEXP;
- arg = optarg;
- break;
-#ifdef YP
- case 'd':
- yp_domain = optarg;
- break;
- case 'h':
- yp_host = optarg;
- break;
- case 'l':
- case 'o':
- case 'y':
- /* compatibility */
- break;
-#endif
- case '?':
- default:
- usage();
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc > 1)
- usage();
-
- uid = getuid();
-
- if (op == EDITENTRY || op == NEWSH || op == NEWPW || op == NEWEXP) {
- if (argc == 0) {
- if ((pw = getpwuid(uid)) == NULL)
- errx(1, "unknown user: uid %lu",
- (unsigned long)uid);
- } else {
- if ((pw = getpwnam(*argv)) == NULL)
- errx(1, "unknown user: %s", *argv);
- if (uid != 0 && uid != pw->pw_uid)
- baduser();
- }
-
- /* Make a copy for later verification */
- if ((pw = pw_dup(pw)) == NULL ||
- (old_pw = pw_dup(pw)) == NULL)
- err(1, "pw_dup");
- }
-
-#ifdef YP
- if (pw != NULL && (pw->pw_fields & _PWF_SOURCE) == _PWF_NIS) {
- ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
- master_mode = (ypclnt != NULL &&
- ypclnt_connect(ypclnt) != -1 &&
- ypclnt_havepasswdd(ypclnt) == 1);
- ypclnt_free(ypclnt);
- } else
-#endif
- master_mode = (uid == 0);
-
- if (op == NEWSH) {
- /* protect p_shell -- it thinks NULL is /bin/sh */
- if (!arg[0])
- usage();
- if (p_shell(arg, pw, (ENTRY *)NULL) == -1)
- exit(1);
- }
-
- if (op == NEWEXP) {
- if (uid) /* only root can change expire */
- baduser();
- if (p_expire(arg, pw, (ENTRY *)NULL) == -1)
- exit(1);
- }
-
- if (op == LOADENTRY) {
- if (uid)
- baduser();
- pw = &lpw;
- old_pw = NULL;
- if (!__pw_scan(arg, pw, _PWSCAN_WARN|_PWSCAN_MASTER))
- exit(1);
- }
-
- if (op == NEWPW) {
- if (uid)
- baduser();
-
- if (strchr(arg, ':'))
- errx(1, "invalid format for password");
- pw->pw_passwd = arg;
- }
-
- if (op == EDITENTRY) {
- /*
- * We don't really need pw_*() here, but pw_edit() (used
- * by edit()) is just too useful...
- */
- if (pw_init(NULL, NULL))
- err(1, "pw_init()");
- if ((tfd = pw_tmp(-1)) == -1) {
- pw_fini();
- err(1, "pw_tmp()");
- }
- free(pw);
- pw = edit(pw_tempname(), old_pw);
- pw_fini();
- if (pw == NULL)
- err(1, "edit()");
- /*
- * pw_equal does not check for crypted passwords, so we
- * should do it explicitly
- */
- if (pw_equal(old_pw, pw) &&
- strcmp(old_pw->pw_passwd, pw->pw_passwd) == 0)
- errx(0, "user information unchanged");
- }
-
- if (old_pw && !master_mode) {
- password = getpass("Password: ");
- if (strcmp(crypt(password, old_pw->pw_passwd),
- old_pw->pw_passwd) != 0)
- baduser();
- } else {
- password = "";
- }
-
- if (old_pw != NULL)
- pw->pw_fields |= (old_pw->pw_fields & _PWF_SOURCE);
- switch (pw->pw_fields & _PWF_SOURCE) {
-#ifdef YP
- case _PWF_NIS:
- ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
- if (ypclnt == NULL ||
- ypclnt_connect(ypclnt) == -1 ||
- ypclnt_passwd(ypclnt, pw, password) == -1) {
- warnx("%s", ypclnt->error);
- ypclnt_free(ypclnt);
- exit(1);
- }
- ypclnt_free(ypclnt);
- errx(0, "NIS user information updated");
-#endif /* YP */
- case 0:
- case _PWF_FILES:
- if (pw_init(NULL, NULL))
- err(1, "pw_init()");
- if ((pfd = pw_lock()) == -1) {
- pw_fini();
- err(1, "pw_lock()");
- }
- if ((tfd = pw_tmp(-1)) == -1) {
- pw_fini();
- err(1, "pw_tmp()");
- }
- if (pw_copy(pfd, tfd, pw, old_pw) == -1) {
- pw_fini();
- err(1, "pw_copy");
- }
- if (pw_mkdb(pw->pw_name) == -1) {
- pw_fini();
- err(1, "pw_mkdb()");
- }
- pw_fini();
- errx(0, "user information updated");
- break;
- default:
- errx(1, "unsupported passwd source");
- }
-}
-
-static void
-baduser(void)
-{
-
- errx(1, "%s", strerror(EACCES));
-}
-
-static void
-usage(void)
-{
-
- (void)fprintf(stderr,
- "usage: chpass%s %s [user]\n",
-#ifdef YP
- " [-d domain] [-h host]",
-#else
- "",
-#endif
- "[-a list] [-p encpass] [-s shell] [-e mmm dd yy]");
- exit(1);
-}
diff --git a/chpass/chpass.h b/chpass/chpass.h
deleted file mode 100644
index ed1a586..0000000
--- a/chpass/chpass.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project by
- * ThinkSec AS and NAI Labs, the Security Research Division of Network
- * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * 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 University of
- * California, Berkeley and its contributors.
- * 4. 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.
- *
- * @(#)chpass.h 8.4 (Berkeley) 4/2/94
- * $FreeBSD$
- */
-
-struct passwd;
-
-typedef struct _entry {
- const char *prompt;
- int (*func)(char *, struct passwd *, struct _entry *);
- int restricted;
- size_t len;
- char *except, *save;
-} ENTRY;
-
-/* Field numbers. */
-#define E_BPHONE 8
-#define E_HPHONE 9
-#define E_LOCATE 10
-#define E_NAME 7
-#define E_OTHER 11
-#define E_SHELL 13
-
-extern ENTRY list[];
-extern int master_mode;
-
-int atot(char *, time_t *);
-struct passwd *edit(const char *, struct passwd *);
-int ok_shell(char *);
-char *dup_shell(char *);
-int p_change(char *, struct passwd *, ENTRY *);
-int p_class(char *, struct passwd *, ENTRY *);
-int p_expire(char *, struct passwd *, ENTRY *);
-int p_gecos(char *, struct passwd *, ENTRY *);
-int p_gid(char *, struct passwd *, ENTRY *);
-int p_hdir(char *, struct passwd *, ENTRY *);
-int p_login(char *, struct passwd *, ENTRY *);
-int p_passwd(char *, struct passwd *, ENTRY *);
-int p_shell(char *, struct passwd *, ENTRY *);
-int p_uid(char *, struct passwd *, ENTRY *);
-char *ttoa(time_t);
diff --git a/chpass/edit.c b/chpass/edit.c
deleted file mode 100644
index ce82f8e..0000000
--- a/chpass/edit.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project by
- * ThinkSec AS and NAI Labs, the Security Research Division of Network
- * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * 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 University of
- * California, Berkeley and its contributors.
- * 4. 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 0
-#ifndef lint
-static char sccsid[] = "@(#)edit.c 8.3 (Berkeley) 4/2/94";
-#endif /* not lint */
-#endif
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <paths.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <pw_scan.h>
-#include <libutil.h>
-
-#include "chpass.h"
-
-static int display(const char *tfn, struct passwd *pw);
-static struct passwd *verify(const char *tfn, struct passwd *pw);
-
-struct passwd *
-edit(const char *tfn, struct passwd *pw)
-{
- struct passwd *npw;
- char *line;
- size_t len;
-
- if (display(tfn, pw) == -1)
- return (NULL);
- for (;;) {
- switch (pw_edit(1)) {
- case -1:
- return (NULL);
- case 0:
- return (pw_dup(pw));
- default:
- break;
- }
- if ((npw = verify(tfn, pw)) != NULL)
- return (npw);
- free(npw);
- printf("re-edit the password file? ");
- fflush(stdout);
- if ((line = fgetln(stdin, &len)) == NULL) {
- warn("fgetln()");
- return (NULL);
- }
- if (len > 0 && (*line == 'N' || *line == 'n'))
- return (NULL);
- }
-}
-
-/*
- * display --
- * print out the file for the user to edit; strange side-effect:
- * set conditional flag if the user gets to edit the shell.
- */
-static int
-display(const char *tfn, struct passwd *pw)
-{
- FILE *fp;
- char *bp, *gecos, *p;
-
- if ((fp = fopen(tfn, "w")) == NULL) {
- warn("%s", tfn);
- return (-1);
- }
-
- (void)fprintf(fp,
- "#Changing user information for %s.\n", pw->pw_name);
- if (master_mode) {
- (void)fprintf(fp, "Login: %s\n", pw->pw_name);
- (void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
- (void)fprintf(fp, "Uid [#]: %lu\n", (unsigned long)pw->pw_uid);
- (void)fprintf(fp, "Gid [# or name]: %lu\n",
- (unsigned long)pw->pw_gid);
- (void)fprintf(fp, "Change [month day year]: %s\n",
- ttoa(pw->pw_change));
- (void)fprintf(fp, "Expire [month day year]: %s\n",
- ttoa(pw->pw_expire));
- (void)fprintf(fp, "Class: %s\n", pw->pw_class);
- (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir);
- (void)fprintf(fp, "Shell: %s\n",
- *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
- }
- /* Only admin can change "restricted" shells. */
-#if 0
- else if (ok_shell(pw->pw_shell))
- /*
- * Make shell a restricted field. Ugly with a
- * necklace, but there's not much else to do.
- */
-#else
- else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) ||
- master_mode)
- /*
- * If change not restrict (table.c) and standard shell
- * OR if root, then allow editing of shell.
- */
-#endif
- (void)fprintf(fp, "Shell: %s\n",
- *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
- else
- list[E_SHELL].restricted = 1;
-
- if ((bp = gecos = strdup(pw->pw_gecos)) == NULL) {
- warn(NULL);
- fclose(fp);
- return (-1);
- }
-
- p = strsep(&bp, ",");
- p = strdup(p ? p : "");
- list[E_NAME].save = p;
- if (!list[E_NAME].restricted || master_mode)
- (void)fprintf(fp, "Full Name: %s\n", p);
-
- p = strsep(&bp, ",");
- p = strdup(p ? p : "");
- list[E_LOCATE].save = p;
- if (!list[E_LOCATE].restricted || master_mode)
- (void)fprintf(fp, "Office Location: %s\n", p);
-
- p = strsep(&bp, ",");
- p = strdup(p ? p : "");
- list[E_BPHONE].save = p;
- if (!list[E_BPHONE].restricted || master_mode)
- (void)fprintf(fp, "Office Phone: %s\n", p);
-
- p = strsep(&bp, ",");
- p = strdup(p ? p : "");
- list[E_HPHONE].save = p;
- if (!list[E_HPHONE].restricted || master_mode)
- (void)fprintf(fp, "Home Phone: %s\n", p);
-
- bp = strdup(bp ? bp : "");
- list[E_OTHER].save = bp;
- if (!list[E_OTHER].restricted || master_mode)
- (void)fprintf(fp, "Other information: %s\n", bp);
-
- free(gecos);
-
- (void)fchown(fileno(fp), getuid(), getgid());
- (void)fclose(fp);
- return (0);
-}
-
-static struct passwd *
-verify(const char *tfn, struct passwd *pw)
-{
- struct passwd *npw;
- ENTRY *ep;
- char *buf, *p, *val;
- struct stat sb;
- FILE *fp;
- int line;
- size_t len;
-
- if ((pw = pw_dup(pw)) == NULL)
- return (NULL);
- if ((fp = fopen(tfn, "r")) == NULL ||
- fstat(fileno(fp), &sb) == -1) {
- warn("%s", tfn);
- free(pw);
- return (NULL);
- }
- if (sb.st_size == 0) {
- warnx("corrupted temporary file");
- fclose(fp);
- free(pw);
- return (NULL);
- }
- val = NULL;
- for (line = 1; (buf = fgetln(fp, &len)) != NULL; ++line) {
- if (*buf == '\0' || *buf == '#')
- continue;
- while (len > 0 && isspace(buf[len - 1]))
- --len;
- for (ep = list;; ++ep) {
- if (!ep->prompt) {
- warnx("%s: unrecognized field on line %d",
- tfn, line);
- goto bad;
- }
- if (ep->len > len)
- continue;
- if (strncasecmp(buf, ep->prompt, ep->len) != 0)
- continue;
- if (ep->restricted && !master_mode) {
- warnx("%s: you may not change the %s field",
- tfn, ep->prompt);
- goto bad;
- }
- for (p = buf; p < buf + len && *p != ':'; ++p)
- /* nothing */ ;
- if (*p != ':') {
- warnx("%s: line %d corrupted", tfn, line);
- goto bad;
- }
- while (++p < buf + len && isspace(*p))
- /* nothing */ ;
- free(val);
- asprintf(&val, "%.*s", (int)(buf + len - p), p);
- if (val == NULL)
- goto bad;
- if (ep->except && strpbrk(val, ep->except)) {
- warnx("%s: invalid character in \"%s\" field '%s'",
- tfn, ep->prompt, val);
- goto bad;
- }
- if ((ep->func)(val, pw, ep))
- goto bad;
- break;
- }
- }
- free(val);
- fclose(fp);
-
- /* Build the gecos field. */
- len = asprintf(&p, "%s,%s,%s,%s,%s", list[E_NAME].save,
- list[E_LOCATE].save, list[E_BPHONE].save,
- list[E_HPHONE].save, list[E_OTHER].save);
- if (p == NULL) {
- warn("asprintf()");
- free(pw);
- return (NULL);
- }
- while (len > 0 && p[len - 1] == ',')
- p[--len] = '\0';
- pw->pw_gecos = p;
- buf = pw_make(pw);
- free(pw);
- free(p);
- if (buf == NULL) {
- warn("pw_make()");
- return (NULL);
- }
- npw = pw_scan(buf, PWSCAN_WARN|PWSCAN_MASTER);
- free(buf);
- return (npw);
-bad:
- free(pw);
- free(val);
- fclose(fp);
- return (NULL);
-}
diff --git a/chpass/field.c b/chpass/field.c
deleted file mode 100644
index eac5561..0000000
--- a/chpass/field.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project by
- * ThinkSec AS and NAI Labs, the Security Research Division of Network
- * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * 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 University of
- * California, Berkeley and its contributors.
- * 4. 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 0
-#ifndef lint
-static char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94";
-#endif /* not lint */
-#endif
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <grp.h>
-#include <paths.h>
-#include <pwd.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "chpass.h"
-
-/* ARGSUSED */
-int
-p_login(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- if (!*p) {
- warnx("empty login field");
- return (-1);
- }
- if (*p == '-') {
- warnx("login names may not begin with a hyphen");
- return (-1);
- }
- if (!(pw->pw_name = strdup(p))) {
- warnx("can't save entry");
- return (-1);
- }
- if (strchr(p, '.'))
- warnx("\'.\' is dangerous in a login name");
- for (; *p; ++p)
- if (isupper(*p)) {
- warnx("upper-case letters are dangerous in a login name");
- break;
- }
- return (0);
-}
-
-/* ARGSUSED */
-int
-p_passwd(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- if (!(pw->pw_passwd = strdup(p))) {
- warnx("can't save password entry");
- return (-1);
- }
-
- return (0);
-}
-
-/* ARGSUSED */
-int
-p_uid(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- uid_t id;
- char *np;
-
- if (!*p) {
- warnx("empty uid field");
- return (-1);
- }
- if (!isdigit(*p)) {
- warnx("illegal uid");
- return (-1);
- }
- errno = 0;
- id = strtoul(p, &np, 10);
- if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
- warnx("illegal uid");
- return (-1);
- }
- pw->pw_uid = id;
- return (0);
-}
-
-/* ARGSUSED */
-int
-p_gid(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- struct group *gr;
- gid_t id;
- char *np;
-
- if (!*p) {
- warnx("empty gid field");
- return (-1);
- }
- if (!isdigit(*p)) {
- if (!(gr = getgrnam(p))) {
- warnx("unknown group %s", p);
- return (-1);
- }
- pw->pw_gid = gr->gr_gid;
- return (0);
- }
- errno = 0;
- id = strtoul(p, &np, 10);
- if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
- warnx("illegal gid");
- return (-1);
- }
- pw->pw_gid = id;
- return (0);
-}
-
-/* ARGSUSED */
-int
-p_class(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- if (!(pw->pw_class = strdup(p))) {
- warnx("can't save entry");
- return (-1);
- }
-
- return (0);
-}
-
-/* ARGSUSED */
-int
-p_change(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- if (!atot(p, &pw->pw_change))
- return (0);
- warnx("illegal date for change field");
- return (-1);
-}
-
-/* ARGSUSED */
-int
-p_expire(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- if (!atot(p, &pw->pw_expire))
- return (0);
- warnx("illegal date for expire field");
- return (-1);
-}
-
-/* ARGSUSED */
-int
-p_gecos(char *p, struct passwd *pw __unused, ENTRY *ep)
-{
- if (!(ep->save = strdup(p))) {
- warnx("can't save entry");
- return (-1);
- }
- return (0);
-}
-
-/* ARGSUSED */
-int
-p_hdir(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- if (!*p) {
- warnx("empty home directory field");
- return (-1);
- }
- if (!(pw->pw_dir = strdup(p))) {
- warnx("can't save entry");
- return (-1);
- }
- return (0);
-}
-
-/* ARGSUSED */
-int
-p_shell(char *p, struct passwd *pw, ENTRY *ep __unused)
-{
- struct stat sbuf;
-
- if (!*p) {
- pw->pw_shell = strdup(_PATH_BSHELL);
- return (0);
- }
- /* only admin can change from or to "restricted" shells */
- if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) {
- warnx("%s: current shell non-standard", pw->pw_shell);
- return (-1);
- }
- if (!ok_shell(p)) {
- if (!master_mode) {
- warnx("%s: non-standard shell", p);
- return (-1);
- }
- pw->pw_shell = strdup(p);
- }
- else
- pw->pw_shell = dup_shell(p);
- if (!pw->pw_shell) {
- warnx("can't save entry");
- return (-1);
- }
- if (stat(pw->pw_shell, &sbuf) < 0) {
- if (errno == ENOENT)
- warnx("WARNING: shell '%s' does not exist",
- pw->pw_shell);
- else
- warn("WARNING: can't stat shell '%s'", pw->pw_shell);
- return (0);
- }
- if (!S_ISREG(sbuf.st_mode)) {
- warnx("WARNING: shell '%s' is not a regular file",
- pw->pw_shell);
- return (0);
- }
- if ((sbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) {
- warnx("WARNING: shell '%s' is not executable", pw->pw_shell);
- return (0);
- }
- return (0);
-}
diff --git a/chpass/table.c b/chpass/table.c
deleted file mode 100644
index 19f1a99..0000000
--- a/chpass/table.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. 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 0
-#ifndef lint
-static const char sccsid[] = "@(#)table.c 8.3 (Berkeley) 4/2/94";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <stddef.h>
-#include "chpass.h"
-
-char e1[] = ": ";
-char e2[] = ":,";
-
-ENTRY list[] = {
- { "login", p_login, 1, 5, e1, NULL },
- { "password", p_passwd, 1, 8, e1, NULL },
- { "uid", p_uid, 1, 3, e1, NULL },
- { "gid", p_gid, 1, 3, e1, NULL },
- { "class", p_class, 1, 5, e1, NULL },
- { "change", p_change, 1, 6, NULL, NULL },
- { "expire", p_expire, 1, 6, NULL, NULL },
-#ifdef RESTRICT_FULLNAME_CHANGE /* do not allow fullname changes */
- { "full name", p_gecos, 1, 9, e2, NULL },
-#else
- { "full name", p_gecos, 0, 9, e2, NULL },
-#endif
- { "office phone", p_gecos, 0, 12, e2, NULL },
- { "home phone", p_gecos, 0, 10, e2, NULL },
- { "office location", p_gecos, 0, 15, e2, NULL },
- { "other information", p_gecos, 0, 11, e1, NULL },
- { "home directory", p_hdir, 1, 14, e1, NULL },
- { "shell", p_shell, 0, 5, e1, NULL },
- { NULL, NULL, 0, 0, NULL, NULL },
-};
diff --git a/chpass/util.c b/chpass/util.c
deleted file mode 100644
index 07d96e2..0000000
--- a/chpass/util.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*-
- * Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project by
- * ThinkSec AS and NAI Labs, the Security Research Division of Network
- * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * 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 University of
- * California, Berkeley and its contributors.
- * 4. 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 lint
-#if 0
-static char sccsid[] = "@(#)util.c 8.4 (Berkeley) 4/2/94";
-#endif
-#endif /* not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "chpass.h"
-
-static const char *months[] =
- { "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November",
- "December", NULL };
-
-char *
-ttoa(time_t tval)
-{
- struct tm *tp;
- static char tbuf[50];
-
- if (tval) {
- tp = localtime(&tval);
- (void)sprintf(tbuf, "%s %d, %d", months[tp->tm_mon],
- tp->tm_mday, tp->tm_year + 1900);
- }
- else
- *tbuf = '\0';
- return (tbuf);
-}
-
-int
-atot(char *p, time_t *store)
-{
- static struct tm *lt;
- char *t;
- const char **mp;
- time_t tval;
- int day, month, year;
-
- if (!*p) {
- *store = 0;
- return (0);
- }
- if (!lt) {
- unsetenv("TZ");
- (void)time(&tval);
- lt = localtime(&tval);
- }
- if (!(t = strtok(p, " \t")))
- goto bad;
- if (isdigit(*t)) {
- month = atoi(t);
- } else {
- for (mp = months;; ++mp) {
- if (!*mp)
- goto bad;
- if (!strncasecmp(*mp, t, 3)) {
- month = mp - months + 1;
- break;
- }
- }
- }
- if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t))
- goto bad;
- day = atoi(t);
- if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t))
- goto bad;
- year = atoi(t);
- if (day < 1 || day > 31 || month < 1 || month > 12)
- goto bad;
- /* Allow two digit years 1969-2068 */
- if (year < 69)
- year += 2000;
- else if (year < 100)
- year += 1900;
- if (year < 1969)
-bad: return (1);
- lt->tm_year = year - 1900;
- lt->tm_mon = month - 1;
- lt->tm_mday = day;
- lt->tm_hour = 0;
- lt->tm_min = 0;
- lt->tm_sec = 0;
- lt->tm_isdst = -1;
- if ((tval = mktime(lt)) < 0)
- return (1);
- *store = tval;
- return (0);
-}
-
-int
-ok_shell(char *name)
-{
- char *p, *sh;
-
- setusershell();
- while ((sh = getusershell())) {
- if (!strcmp(name, sh)) {
- endusershell();
- return (1);
- }
- /* allow just shell name, but use "real" path */
- if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
- endusershell();
- return (1);
- }
- }
- endusershell();
- return (0);
-}
-
-char *
-dup_shell(char *name)
-{
- char *p, *sh, *ret;
-
- setusershell();
- while ((sh = getusershell())) {
- if (!strcmp(name, sh)) {
- endusershell();
- return (strdup(name));
- }
- /* allow just shell name, but use "real" path */
- if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
- ret = strdup(sh);
- endusershell();
- return (ret);
- }
- }
- endusershell();
- return (NULL);
-}
diff --git a/libc/gen/pw_scan.c b/libc/gen/pw_scan.c
deleted file mode 100644
index 24e8225..0000000
--- a/libc/gen/pw_scan.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*-
- * 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.
- * 4. 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 defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * This module is used to "verify" password entries by chpass(1) and
- * pwd_mkdb(8).
- */
-
-#include <sys/param.h>
-
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "pw_scan.h"
-
-/*
- * Some software assumes that IDs are short. We should emit warnings
- * for id's which cannot be stored in a short, but we are more liberal
- * by default, warning for IDs greater than USHRT_MAX.
- *
- * If pw_big_ids_warning is -1 on entry to pw_scan(), it will be set based
- * on the existence of PW_SCAN_BIG_IDS in the environment.
- *
- * It is believed all baseline system software that can not handle the
- * normal ID sizes is now gone so pw_big_ids_warning is disabled for now.
- * But the code has been left in place in case end-users want to re-enable
- * it and/or for the next time the ID sizes get bigger but pieces of the
- * system lag behind.
- */
-static int pw_big_ids_warning = 0;
-
-int
-__pw_scan(char *bp, struct passwd *pw, int flags)
-{
- uid_t id;
- int root;
- char *ep, *p, *sh;
- unsigned long temp;
-
- if (pw_big_ids_warning == -1)
- pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0;
-
- pw->pw_fields = 0;
- if (!(pw->pw_name = strsep(&bp, ":"))) /* login */
- goto fmt;
- root = !strcmp(pw->pw_name, "root");
- if (pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0'))
- pw->pw_fields |= _PWF_NAME;
-
- if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */
- goto fmt;
- if (pw->pw_passwd[0])
- pw->pw_fields |= _PWF_PASSWD;
-
- if (!(p = strsep(&bp, ":"))) /* uid */
- goto fmt;
- if (p[0])
- pw->pw_fields |= _PWF_UID;
- else {
- if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
- if (flags & _PWSCAN_WARN)
- warnx("no uid for user %s", pw->pw_name);
- return (0);
- }
- }
- errno = 0;
- temp = strtoul(p, &ep, 10);
- if ((temp == ULONG_MAX && errno == ERANGE) || temp > UID_MAX) {
- if (flags & _PWSCAN_WARN)
- warnx("%s > max uid value (%u)", p, UID_MAX);
- return (0);
- }
- id = temp;
- if (*ep != '\0') {
- if (flags & _PWSCAN_WARN)
- warnx("%s uid is incorrect", p);
- return (0);
- }
- if (root && id) {
- if (flags & _PWSCAN_WARN)
- warnx("root uid should be 0");
- return (0);
- }
- if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
- warnx("%s > recommended max uid value (%u)", p, USHRT_MAX);
- /*return (0);*/ /* THIS SHOULD NOT BE FATAL! */
- }
- pw->pw_uid = id;
-
- if (!(p = strsep(&bp, ":"))) /* gid */
- goto fmt;
- if (p[0])
- pw->pw_fields |= _PWF_GID;
- else {
- if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
- if (flags & _PWSCAN_WARN)
- warnx("no gid for user %s", pw->pw_name);
- return (0);
- }
- }
- errno = 0;
- temp = strtoul(p, &ep, 10);
- if ((temp == ULONG_MAX && errno == ERANGE) || temp > GID_MAX) {
- if (flags & _PWSCAN_WARN)
- warnx("%s > max gid value (%u)", p, GID_MAX);
- return (0);
- }
- id = temp;
- if (*ep != '\0') {
- if (flags & _PWSCAN_WARN)
- warnx("%s gid is incorrect", p);
- return (0);
- }
- if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
- warnx("%s > recommended max gid value (%u)", p, USHRT_MAX);
- /* return (0); This should not be fatal! */
- }
- pw->pw_gid = id;
-
- if (flags & _PWSCAN_MASTER ) {
- if (!(pw->pw_class = strsep(&bp, ":"))) /* class */
- goto fmt;
- if (pw->pw_class[0])
- pw->pw_fields |= _PWF_CLASS;
-
- if (!(p = strsep(&bp, ":"))) /* change */
- goto fmt;
- if (p[0])
- pw->pw_fields |= _PWF_CHANGE;
- pw->pw_change = atol(p);
-
- if (!(p = strsep(&bp, ":"))) /* expire */
- goto fmt;
- if (p[0])
- pw->pw_fields |= _PWF_EXPIRE;
- pw->pw_expire = atol(p);
- }
- if (!(pw->pw_gecos = strsep(&bp, ":"))) /* gecos */
- goto fmt;
- if (pw->pw_gecos[0])
- pw->pw_fields |= _PWF_GECOS;
-
- if (!(pw->pw_dir = strsep(&bp, ":"))) /* directory */
- goto fmt;
- if (pw->pw_dir[0])
- pw->pw_fields |= _PWF_DIR;
-
- if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */
- goto fmt;
-
- p = pw->pw_shell;
- if (root && *p) { /* empty == /bin/sh */
- for (setusershell();;) {
- if (!(sh = getusershell())) {
- if (flags & _PWSCAN_WARN)
- warnx("warning, unknown root shell");
- break;
- }
- if (!strcmp(p, sh))
- break;
- }
- endusershell();
- }
- if (p[0])
- pw->pw_fields |= _PWF_SHELL;
-
- if ((p = strsep(&bp, ":"))) { /* too many */
-fmt:
- if (flags & _PWSCAN_WARN)
- warnx("corrupted entry");
- return (0);
- }
- return (1);
-}
diff --git a/libc/gen/pw_scan.h b/libc/gen/pw_scan.h
deleted file mode 100644
index 468096c..0000000
--- a/libc/gen/pw_scan.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)pw_scan.h 8.1 (Berkeley) 4/1/94
- * $FreeBSD$
- */
-
-#define _PWSCAN_MASTER 0x01
-#define _PWSCAN_WARN 0x02
-
-extern int __pw_scan(char *, struct passwd *, int);
diff --git a/libc/stdlib/strtonum.c b/libc/stdlib/strtonum.c
deleted file mode 100644
index 6dccd97..0000000
--- a/libc/stdlib/strtonum.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-
- * Copyright (c) 2004 Ted Unangst and Todd Miller
- * All rights reserved.
- *
- * 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.
- *
- * $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-
-#define INVALID 1
-#define TOOSMALL 2
-#define TOOLARGE 3
-
-long long
-strtonum(const char *numstr, long long minval, long long maxval,
- const char **errstrp)
-{
- long long ll = 0;
- char *ep;
- int error = 0;
- struct errval {
- const char *errstr;
- int err;
- } ev[4] = {
- { NULL, 0 },
- { "invalid", EINVAL },
- { "too small", ERANGE },
- { "too large", ERANGE },
- };
-
- ev[0].err = errno;
- errno = 0;
- if (minval > maxval)
- error = INVALID;
- else {
- ll = strtoll(numstr, &ep, 10);
- if (errno == EINVAL || numstr == ep || *ep != '\0')
- error = INVALID;
- else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
- error = TOOSMALL;
- else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
- error = TOOLARGE;
- }
- if (errstrp != NULL)
- *errstrp = ev[error].errstr;
- errno = ev[error].err;
- if (error)
- ll = 0;
-
- return (ll);
-}
diff --git a/libutil/_secure_path.c b/libutil/_secure_path.c
deleted file mode 100644
index 363378b..0000000
--- a/libutil/_secure_path.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*-
- * Based on code copyright (c) 1995,1997 by
- * Berkeley Software Design, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, is permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice immediately at the beginning of the file, without modification,
- * 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. This work was done expressly for inclusion into FreeBSD. Other use
- * is permitted provided this notation is included.
- * 4. Absolutely no warranty of function or purpose is made by the authors.
- * 5. Modifications may be freely made to this file providing the above
- * conditions are met.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <libutil.h>
-#include <stddef.h>
-#include <syslog.h>
-
-/*
- * Check for common security problems on a given path
- * It must be:
- * 1. A regular file, and exists
- * 2. Owned and writable only by root (or given owner)
- * 3. Group ownership is given group or is non-group writable
- *
- * Returns: -2 if file does not exist,
- * -1 if security test failure
- * 0 otherwise
- */
-
-int
-_secure_path(const char *path, uid_t uid, gid_t gid)
-{
- int r = -1;
- struct stat sb;
- const char *msg = NULL;
-
- if (lstat(path, &sb) < 0) {
- if (errno == ENOENT) /* special case */
- r = -2; /* if it is just missing, skip the log entry */
- else
- msg = "%s: cannot stat %s: %m";
- }
- else if (!S_ISREG(sb.st_mode))
- msg = "%s: %s is not a regular file";
- else if (sb.st_mode & S_IWOTH)
- msg = "%s: %s is world writable";
- else if ((int)uid != -1 && sb.st_uid != uid && sb.st_uid != 0) {
- if (uid == 0)
- msg = "%s: %s is not owned by root";
- else
- msg = "%s: %s is not owned by uid %d";
- } else if ((int)gid != -1 && sb.st_gid != gid && (sb.st_mode & S_IWGRP))
- msg = "%s: %s is group writeable by non-authorised groups";
- else
- r = 0;
- if (msg != NULL)
- syslog(LOG_ERR, msg, "_secure_path", path, uid);
- return r;
-}
diff --git a/libutil/flopen.c b/libutil/flopen.c
deleted file mode 100644
index 754c9c0..0000000
--- a/libutil/flopen.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-
- * Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
- * 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
- * in this position and unchanged.
- * 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 AUTHOR 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 AUTHOR 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>
-__FBSDID("$FreeBSD$");
-
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <stdarg.h>
-#include <unistd.h>
-
-#include <libutil.h>
-
-int
-flopen(const char *path, int flags, ...)
-{
- int fd, operation, serrno, trunc;
- struct stat sb, fsb;
- mode_t mode;
-
-#ifdef O_EXLOCK
- flags &= ~O_EXLOCK;
-#endif
-
- mode = 0;
- if (flags & O_CREAT) {
- va_list ap;
-
- va_start(ap, flags);
- mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */
- va_end(ap);
- }
-
- operation = LOCK_EX;
- if (flags & O_NONBLOCK)
- operation |= LOCK_NB;
-
- trunc = (flags & O_TRUNC);
- flags &= ~O_TRUNC;
-
- for (;;) {
- if ((fd = open(path, flags, mode)) == -1)
- /* non-existent or no access */
- return (-1);
- if (flock(fd, operation) == -1) {
- /* unsupported or interrupted */
- serrno = errno;
- (void)close(fd);
- errno = serrno;
- return (-1);
- }
- if (stat(path, &sb) == -1) {
- /* disappeared from under our feet */
- (void)close(fd);
- continue;
- }
- if (fstat(fd, &fsb) == -1) {
- /* can't happen [tm] */
- serrno = errno;
- (void)close(fd);
- errno = serrno;
- return (-1);
- }
- if (sb.st_dev != fsb.st_dev ||
- sb.st_ino != fsb.st_ino) {
- /* changed under our feet */
- (void)close(fd);
- continue;
- }
- if (trunc && ftruncate(fd, 0) != 0) {
- /* can't happen [tm] */
- serrno = errno;
- (void)close(fd);
- errno = serrno;
- return (-1);
- }
- return (fd);
- }
-}
diff --git a/libutil/gr_util.c b/libutil/gr_util.c
deleted file mode 100644
index 633f435..0000000
--- a/libutil/gr_util.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*-
- * Copyright (c) 2008 Sean C. Farley <scf@FreeBSD.org>
- * 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,
- * without modification, immediately at the beginning of the file.
- * 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 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>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-
-#include <grp.h>
-#include <inttypes.h>
-#include <libutil.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-struct group_storage {
- struct group gr;
- char *members[];
-};
-
-static const char group_line_format[] = "%s:%s:%ju:";
-
-/*
- * Compares two struct group's.
- */
-int
-gr_equal(const struct group *gr1, const struct group *gr2)
-{
- int gr1_ndx;
- int gr2_ndx;
- bool found;
-
- /* Check that the non-member information is the same. */
- if (gr1->gr_name == NULL || gr2->gr_name == NULL) {
- if (gr1->gr_name != gr2->gr_name)
- return (false);
- } else if (strcmp(gr1->gr_name, gr2->gr_name) != 0)
- return (false);
- if (gr1->gr_passwd == NULL || gr2->gr_passwd == NULL) {
- if (gr1->gr_passwd != gr2->gr_passwd)
- return (false);
- } else if (strcmp(gr1->gr_passwd, gr2->gr_passwd) != 0)
- return (false);
- if (gr1->gr_gid != gr2->gr_gid)
- return (false);
-
- /* Check all members in both groups. */
- if (gr1->gr_mem == NULL || gr2->gr_mem == NULL) {
- if (gr1->gr_mem != gr2->gr_mem)
- return (false);
- } else {
- for (found = false, gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL;
- gr1_ndx++) {
- for (gr2_ndx = 0; gr2->gr_mem[gr2_ndx] != NULL;
- gr2_ndx++)
- if (strcmp(gr1->gr_mem[gr1_ndx],
- gr2->gr_mem[gr2_ndx]) == 0) {
- found = true;
- break;
- }
- if (!found)
- return (false);
- }
-
- /* Check that group2 does not have more members than group1. */
- if (gr2->gr_mem[gr1_ndx] != NULL)
- return (false);
- }
-
- return (true);
-}
-
-/*
- * Make a group line out of a struct group.
- */
-char *
-gr_make(const struct group *gr)
-{
- char *line;
- size_t line_size;
- int ndx;
-
- /* Calculate the length of the group line. */
- line_size = snprintf(NULL, 0, group_line_format, gr->gr_name,
- gr->gr_passwd, (uintmax_t)gr->gr_gid) + 1;
- if (gr->gr_mem != NULL) {
- for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++)
- line_size += strlen(gr->gr_mem[ndx]) + 1;
- if (ndx > 0)
- line_size--;
- }
-
- /* Create the group line and fill it. */
- if ((line = malloc(line_size)) == NULL)
- return (NULL);
- snprintf(line, line_size, group_line_format, gr->gr_name, gr->gr_passwd,
- (uintmax_t)gr->gr_gid);
- if (gr->gr_mem != NULL)
- for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) {
- strcat(line, gr->gr_mem[ndx]);
- if (gr->gr_mem[ndx + 1] != NULL)
- strcat(line, ",");
- }
-
- return (line);
-}
-
-/*
- * Duplicate a struct group.
- */
-struct group *
-gr_dup(const struct group *gr)
-{
- char *dst;
- size_t len;
- struct group_storage *gs;
- int ndx;
- int num_mem;
-
- /* Calculate size of the group. */
- len = sizeof(*gs);
- if (gr->gr_name != NULL)
- len += strlen(gr->gr_name) + 1;
- if (gr->gr_passwd != NULL)
- len += strlen(gr->gr_passwd) + 1;
- if (gr->gr_mem != NULL) {
- for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++)
- len += strlen(gr->gr_mem[num_mem]) + 1;
- len += (num_mem + 1) * sizeof(*gr->gr_mem);
- } else
- num_mem = -1;
-
- /* Create new group and copy old group into it. */
- if ((gs = calloc(1, len)) == NULL)
- return (NULL);
- dst = (char *)&gs->members[num_mem + 1];
- if (gr->gr_name != NULL) {
- gs->gr.gr_name = dst;
- dst = stpcpy(gs->gr.gr_name, gr->gr_name) + 1;
- }
- if (gr->gr_passwd != NULL) {
- gs->gr.gr_passwd = dst;
- dst = stpcpy(gs->gr.gr_passwd, gr->gr_passwd) + 1;
- }
- gs->gr.gr_gid = gr->gr_gid;
- if (gr->gr_mem != NULL) {
- gs->gr.gr_mem = gs->members;
- for (ndx = 0; ndx < num_mem; ndx++) {
- gs->gr.gr_mem[ndx] = dst;
- dst = stpcpy(gs->gr.gr_mem[ndx], gr->gr_mem[ndx]) + 1;
- }
- gs->gr.gr_mem[ndx] = NULL;
- }
-
- return (&gs->gr);
-}
-
-/*
- * Scan a line and place it into a group structure.
- */
-static bool
-__gr_scan(char *line, struct group *gr)
-{
- char *loc;
- int ndx;
-
- /* Assign non-member information to structure. */
- gr->gr_name = line;
- if ((loc = strchr(line, ':')) == NULL)
- return (false);
- *loc = '\0';
- gr->gr_passwd = loc + 1;
- if (*gr->gr_passwd == ':')
- *gr->gr_passwd = '\0';
- else {
- if ((loc = strchr(loc + 1, ':')) == NULL)
- return (false);
- *loc = '\0';
- }
- if (sscanf(loc + 1, "%u", &gr->gr_gid) != 1)
- return (false);
-
- /* Assign member information to structure. */
- if ((loc = strchr(loc + 1, ':')) == NULL)
- return (false);
- line = loc + 1;
- gr->gr_mem = NULL;
- ndx = 0;
- do {
- gr->gr_mem = reallocf(gr->gr_mem, sizeof(*gr->gr_mem) *
- (ndx + 1));
- if (gr->gr_mem == NULL)
- return (false);
-
- /* Skip locations without members (i.e., empty string). */
- do {
- gr->gr_mem[ndx] = strsep(&line, ",");
- } while (gr->gr_mem[ndx] != NULL && *gr->gr_mem[ndx] == '\0');
- } while (gr->gr_mem[ndx++] != NULL);
-
- return (true);
-}
-
-/*
- * Create a struct group from a line.
- */
-struct group *
-gr_scan(const char *line)
-{
- struct group gr;
- char *line_copy;
- struct group *new_gr;
-
- if ((line_copy = strdup(line)) == NULL)
- return (NULL);
- if (!__gr_scan(line_copy, &gr)) {
- free(line_copy);
- return (NULL);
- }
- new_gr = gr_dup(&gr);
- free(line_copy);
- if (gr.gr_mem != NULL)
- free(gr.gr_mem);
-
- return (new_gr);
-}
diff --git a/libutil/libutil.h b/libutil/libutil.h
deleted file mode 100644
index 4c2ee3b..0000000
--- a/libutil/libutil.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 1996 Peter Wemm <peter@FreeBSD.org>.
- * All rights reserved.
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project by
- * ThinkSec AS and NAI Labs, the Security Research Division of Network
- * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, is 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. 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 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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _LIBUTIL_H_
-#define _LIBUTIL_H_
-
-#include <sys/cdefs.h>
-#include <sys/_types.h>
-
-#ifndef _GID_T_DECLARED
-typedef __gid_t gid_t;
-#define _GID_T_DECLARED
-#endif
-
-#ifndef _INT64_T_DECLARED
-typedef __int64_t int64_t;
-#define _INT64_T_DECLARED
-#endif
-
-#ifndef _PID_T_DECLARED
-typedef __pid_t pid_t;
-#define _PID_T_DECLARED
-#endif
-
-#ifndef _SIZE_T_DECLARED
-typedef __size_t size_t;
-#define _SIZE_T_DECLARED
-#endif
-
-#ifndef _UID_T_DECLARED
-typedef __uid_t uid_t;
-#define _UID_T_DECLARED
-#endif
-
-#define PROPERTY_MAX_NAME 64
-#define PROPERTY_MAX_VALUE 512
-
-/* for properties.c */
-typedef struct _property {
- struct _property *next;
- char *name;
- char *value;
-} *properties;
-
-#ifdef _SYS_PARAM_H_
-/* for pidfile.c */
-struct pidfh {
- int pf_fd;
- char pf_path[MAXPATHLEN + 1];
- __dev_t pf_dev;
- ino_t pf_ino;
-};
-#endif
-
-/* Avoid pulling in all the include files for no need */
-struct termios;
-struct winsize;
-struct in_addr;
-struct kinfo_file;
-struct kinfo_vmentry;
-
-__BEGIN_DECLS
-void clean_environment(const char * const *_white,
- const char * const *_more_white);
-int extattr_namespace_to_string(int _attrnamespace, char **_string);
-int extattr_string_to_namespace(const char *_string, int *_attrnamespace);
-int flopen(const char *_path, int _flags, ...);
-void hexdump(const void *ptr, int length, const char *hdr, int flags);
-int login_tty(int _fd);
-void trimdomain(char *_fullhost, int _hostsize);
-int openpty(int *_amaster, int *_aslave, char *_name,
- struct termios *_termp, struct winsize *_winp);
-int forkpty(int *_amaster, char *_name,
- struct termios *_termp, struct winsize *_winp);
-int humanize_number(char *_buf, size_t _len, int64_t _number,
- const char *_suffix, int _scale, int _flags);
-int expand_number(const char *_buf, int64_t *_num);
-const char *uu_lockerr(int _uu_lockresult);
-int uu_lock(const char *_ttyname);
-int uu_unlock(const char *_ttyname);
-int uu_lock_txfr(const char *_ttyname, pid_t _pid);
-int _secure_path(const char *_path, uid_t _uid, gid_t _gid);
-properties properties_read(int fd);
-void properties_free(properties list);
-char *property_find(properties list, const char *name);
-char *auth_getval(const char *name);
-int realhostname(char *host, size_t hsize, const struct in_addr *ip);
-struct sockaddr;
-int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr,
- int addrlen);
-
-int kld_isloaded(const char *name);
-int kld_load(const char *name);
-struct kinfo_file *
- kinfo_getfile(pid_t _pid, int *_cntp);
-struct kinfo_vmentry *
- kinfo_getvmmap(pid_t _pid, int *_cntp);
-
-#ifdef _STDIO_H_ /* avoid adding new includes */
-char *fparseln(FILE *, size_t *, size_t *, const char[3], int);
-#endif
-
-#ifdef _PWD_H_
-int pw_copy(int _ffd, int _tfd, const struct passwd *_pw, struct passwd *_old_pw);
-struct passwd *pw_dup(const struct passwd *_pw);
-int pw_edit(int _notsetuid);
-int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2);
-void pw_fini(void);
-int pw_init(const char *_dir, const char *_master);
-char *pw_make(const struct passwd *_pw);
-int pw_mkdb(const char *_user);
-int pw_lock(void);
-struct passwd *pw_scan(const char *_line, int _flags);
-const char *pw_tempname(void);
-int pw_tmp(int _mfd);
-#endif
-
-#ifdef _GRP_H_
-int gr_equal(const struct group *gr1, const struct group *gr2);
-char *gr_make(const struct group *gr);
-struct group *gr_dup(const struct group *gr);
-struct group *gr_scan(const char *line);
-#endif
-
-#ifdef _SYS_PARAM_H_
-struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
-int pidfile_write(struct pidfh *pfh);
-int pidfile_close(struct pidfh *pfh);
-int pidfile_remove(struct pidfh *pfh);
-#endif
-
-__END_DECLS
-
-#define UU_LOCK_INUSE (1)
-#define UU_LOCK_OK (0)
-#define UU_LOCK_OPEN_ERR (-1)
-#define UU_LOCK_READ_ERR (-2)
-#define UU_LOCK_CREAT_ERR (-3)
-#define UU_LOCK_WRITE_ERR (-4)
-#define UU_LOCK_LINK_ERR (-5)
-#define UU_LOCK_TRY_ERR (-6)
-#define UU_LOCK_OWNER_ERR (-7)
-
-/* return values from realhostname() */
-#define HOSTNAME_FOUND (0)
-#define HOSTNAME_INCORRECTNAME (1)
-#define HOSTNAME_INVALIDADDR (2)
-#define HOSTNAME_INVALIDNAME (3)
-
-/* fparseln(3) */
-#define FPARSELN_UNESCESC 0x01
-#define FPARSELN_UNESCCONT 0x02
-#define FPARSELN_UNESCCOMM 0x04
-#define FPARSELN_UNESCREST 0x08
-#define FPARSELN_UNESCALL 0x0f
-
-/* pw_scan() */
-#define PWSCAN_MASTER 0x01
-#define PWSCAN_WARN 0x02
-
-/* humanize_number(3) */
-#define HN_DECIMAL 0x01
-#define HN_NOSPACE 0x02
-#define HN_B 0x04
-#define HN_DIVISOR_1000 0x08
-
-#define HN_GETSCALE 0x10
-#define HN_AUTOSCALE 0x20
-
-/* hexdump(3) */
-#define HD_COLUMN_MASK 0xff
-#define HD_DELIM_MASK 0xff00
-#define HD_OMIT_COUNT (1 << 16)
-#define HD_OMIT_HEX (1 << 17)
-#define HD_OMIT_CHARS (1 << 18)
-
-#endif /* !_LIBUTIL_H_ */
diff --git a/libutil/login_cap.c b/libutil/login_cap.c
deleted file mode 100644
index 8fee760..0000000
--- a/libutil/login_cap.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/*-
- * Copyright (c) 1996 by
- * Sean Eric Fagan <sef@kithrup.com>
- * David Nugent <davidn@blaze.net.au>
- * All rights reserved.
- *
- * Portions copyright (c) 1995,1997
- * Berkeley Software Design, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, is permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice immediately at the beginning of the file, without modification,
- * 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. This work was done expressly for inclusion into FreeBSD. Other use
- * is permitted provided this notation is included.
- * 4. Absolutely no warranty of function or purpose is made by the authors.
- * 5. Modifications may be freely made to this file providing the above
- * conditions are met.
- *
- * Low-level routines relating to the user capabilities database
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/param.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libutil.h>
-#include <login_cap.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-/*
- * allocstr()
- * Manage a single static pointer for handling a local char* buffer,
- * resizing as necessary to contain the string.
- *
- * allocarray()
- * Manage a static array for handling a group of strings, resizing
- * when necessary.
- */
-
-static int lc_object_count = 0;
-
-static size_t internal_stringsz = 0;
-static char * internal_string = NULL;
-static size_t internal_arraysz = 0;
-static const char ** internal_array = NULL;
-
-static char path_login_conf[] = _PATH_LOGIN_CONF;
-
-static char *
-allocstr(const char *str)
-{
- char *p;
-
- size_t sz = strlen(str) + 1; /* realloc() only if necessary */
- if (sz <= internal_stringsz)
- p = strcpy(internal_string, str);
- else if ((p = realloc(internal_string, sz)) != NULL) {
- internal_stringsz = sz;
- internal_string = strcpy(p, str);
- }
- return p;
-}
-
-
-static const char **
-allocarray(size_t sz)
-{
- static const char **p;
-
- if (sz <= internal_arraysz)
- p = internal_array;
- else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) {
- internal_arraysz = sz;
- internal_array = p;
- }
- return p;
-}
-
-
-/*
- * arrayize()
- * Turn a simple string <str> separated by any of
- * the set of <chars> into an array. The last element
- * of the array will be NULL, as is proper.
- * Free using freearraystr()
- */
-
-static const char **
-arrayize(const char *str, const char *chars, int *size)
-{
- int i;
- char *ptr;
- const char *cptr;
- const char **res = NULL;
-
- /* count the sub-strings */
- for (i = 0, cptr = str; *cptr; i++) {
- int count = strcspn(cptr, chars);
- cptr += count;
- if (*cptr)
- ++cptr;
- }
-
- /* alloc the array */
- if ((ptr = allocstr(str)) != NULL) {
- if ((res = allocarray(++i)) == NULL)
- free((void *)(uintptr_t)(const void *)str);
- else {
- /* now split the string */
- i = 0;
- while (*ptr) {
- int count = strcspn(ptr, chars);
- res[i++] = ptr;
- ptr += count;
- if (*ptr)
- *ptr++ = '\0';
- }
- res[i] = NULL;
- }
- }
-
- if (size)
- *size = i;
-
- return res;
-}
-
-
-/*
- * login_close()
- * Frees up all resources relating to a login class
- *
- */
-
-void
-login_close(login_cap_t * lc)
-{
- if (lc) {
- free(lc->lc_style);
- free(lc->lc_class);
- free(lc->lc_cap);
- free(lc);
- if (--lc_object_count == 0) {
- free(internal_string);
- free(internal_array);
- internal_array = NULL;
- internal_arraysz = 0;
- internal_string = NULL;
- internal_stringsz = 0;
- cgetclose();
- }
- }
-}
-
-
-/*
- * login_getclassbyname()
- * Get the login class by its name.
- * If the name given is NULL or empty, the default class
- * LOGIN_DEFCLASS (i.e., "default") is fetched.
- * If the name given is LOGIN_MECLASS and
- * 'pwd' argument is non-NULL and contains an non-NULL
- * dir entry, then the file _FILE_LOGIN_CONF is picked
- * up from that directory and used before the system
- * login database. In that case the system login database
- * is looked up using LOGIN_MECLASS, too, which is a bug.
- * Return a filled-out login_cap_t structure, including
- * class name, and the capability record buffer.
- */
-
-login_cap_t *
-login_getclassbyname(char const *name, const struct passwd *pwd)
-{
- login_cap_t *lc;
-
- if ((lc = malloc(sizeof(login_cap_t))) != NULL) {
- int r, me, i = 0;
- uid_t euid = 0;
- gid_t egid = 0;
- const char *msg = NULL;
- const char *dir;
- char userpath[MAXPATHLEN];
-
- static char *login_dbarray[] = { NULL, NULL, NULL };
-
- me = (name != NULL && strcmp(name, LOGIN_MECLASS) == 0);
- dir = (!me || pwd == NULL) ? NULL : pwd->pw_dir;
- /*
- * Switch to user mode before checking/reading its ~/.login_conf
- * - some NFSes have root read access disabled.
- *
- * XXX: This fails to configure additional groups.
- */
- if (dir) {
- euid = geteuid();
- egid = getegid();
- (void)setegid(pwd->pw_gid);
- (void)seteuid(pwd->pw_uid);
- }
-
- if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir,
- _FILE_LOGIN_CONF) < MAXPATHLEN) {
- if (_secure_path(userpath, pwd->pw_uid, pwd->pw_gid) != -1)
- login_dbarray[i++] = userpath;
- }
- /*
- * XXX: Why to add the system database if the class is `me'?
- */
- if (_secure_path(path_login_conf, 0, 0) != -1)
- login_dbarray[i++] = path_login_conf;
- login_dbarray[i] = NULL;
-
- memset(lc, 0, sizeof(login_cap_t));
- lc->lc_cap = lc->lc_class = lc->lc_style = NULL;
-
- if (name == NULL || *name == '\0')
- name = LOGIN_DEFCLASS;
-
- switch (cgetent(&lc->lc_cap, login_dbarray, name)) {
- case -1: /* Failed, entry does not exist */
- if (me)
- break; /* Don't retry default on 'me' */
- if (i == 0)
- r = -1;
- else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0)
- close(r);
- /*
- * If there's at least one login class database,
- * and we aren't searching for a default class
- * then complain about a non-existent class.
- */
- if (r >= 0 || strcmp(name, LOGIN_DEFCLASS) != 0)
- syslog(LOG_ERR, "login_getclass: unknown class '%s'", name);
- /* fall-back to default class */
- name = LOGIN_DEFCLASS;
- msg = "%s: no default/fallback class '%s'";
- if (cgetent(&lc->lc_cap, login_dbarray, name) != 0 && r >= 0)
- break;
- /* FALLTHROUGH - just return system defaults */
- case 0: /* success! */
- if ((lc->lc_class = strdup(name)) != NULL) {
- if (dir) {
- (void)seteuid(euid);
- (void)setegid(egid);
- }
- ++lc_object_count;
- return lc;
- }
- msg = "%s: strdup: %m";
- break;
- case -2:
- msg = "%s: retrieving class information: %m";
- break;
- case -3:
- msg = "%s: 'tc=' reference loop '%s'";
- break;
- case 1:
- msg = "couldn't resolve 'tc=' reference in '%s'";
- break;
- default:
- msg = "%s: unexpected cgetent() error '%s': %m";
- break;
- }
- if (dir) {
- (void)seteuid(euid);
- (void)setegid(egid);
- }
- if (msg != NULL)
- syslog(LOG_ERR, msg, "login_getclass", name);
- free(lc);
- }
-
- return NULL;
-}
-
-
-
-/*
- * login_getclass()
- * Get the login class for the system (only) login class database.
- * Return a filled-out login_cap_t structure, including
- * class name, and the capability record buffer.
- */
-
-login_cap_t *
-login_getclass(const char *cls)
-{
- return login_getclassbyname(cls, NULL);
-}
-
-
-/*
- * login_getpwclass()
- * Get the login class for a given password entry from
- * the system (only) login class database.
- * If the password entry's class field is not set, or
- * the class specified does not exist, then use the
- * default of LOGIN_DEFCLASS (i.e., "default") for an unprivileged
- * user or that of LOGIN_DEFROOTCLASS (i.e., "root") for a super-user.
- * Return a filled-out login_cap_t structure, including
- * class name, and the capability record buffer.
- */
-
-login_cap_t *
-login_getpwclass(const struct passwd *pwd)
-{
- const char *cls = NULL;
-
- if (pwd != NULL) {
- cls = pwd->pw_class;
- if (cls == NULL || *cls == '\0')
- cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
- }
- /*
- * XXX: pwd should be unused by login_getclassbyname() unless cls is `me',
- * so NULL can be passed instead of pwd for more safety.
- */
- return login_getclassbyname(cls, pwd);
-}
-
-
-/*
- * login_getuserclass()
- * Get the `me' login class, allowing user overrides via ~/.login_conf.
- * Note that user overrides are allowed only in the `me' class.
- */
-
-login_cap_t *
-login_getuserclass(const struct passwd *pwd)
-{
- return login_getclassbyname(LOGIN_MECLASS, pwd);
-}
-
-
-/*
- * login_getcapstr()
- * Given a login_cap entry, and a capability name, return the
- * value defined for that capability, a default if not found, or
- * an error string on error.
- */
-
-const char *
-login_getcapstr(login_cap_t *lc, const char *cap, const char *def, const char *error)
-{
- char *res;
- int ret;
-
- if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0')
- return def;
-
- if ((ret = cgetstr(lc->lc_cap, cap, &res)) == -1)
- return def;
- return (ret >= 0) ? res : error;
-}
-
-
-/*
- * login_getcaplist()
- * Given a login_cap entry, and a capability name, return the
- * value defined for that capability split into an array of
- * strings.
- */
-
-const char **
-login_getcaplist(login_cap_t *lc, const char *cap, const char *chars)
-{
- const char *lstring;
-
- if (chars == NULL)
- chars = ", \t";
- if ((lstring = login_getcapstr(lc, cap, NULL, NULL)) != NULL)
- return arrayize(lstring, chars, NULL);
- return NULL;
-}
-
-
-/*
- * login_getpath()
- * From the login_cap_t <lc>, get the capability <cap> which is
- * formatted as either a space or comma delimited list of paths
- * and append them all into a string and separate by semicolons.
- * If there is an error of any kind, return <error>.
- */
-
-const char *
-login_getpath(login_cap_t *lc, const char *cap, const char *error)
-{
- const char *str;
- char *ptr;
- int count;
-
- str = login_getcapstr(lc, cap, NULL, NULL);
- if (str == NULL)
- return error;
- ptr = __DECONST(char *, str); /* XXXX Yes, very dodgy */
- while (*ptr) {
- count = strcspn(ptr, ", \t");
- ptr += count;
- if (*ptr)
- *ptr++ = ':';
- }
- return str;
-}
-
-
-static int
-isinfinite(const char *s)
-{
- static const char *infs[] = {
- "infinity",
- "inf",
- "unlimited",
- "unlimit",
- "-1",
- NULL
- };
- const char **i = &infs[0];
-
- while (*i != NULL) {
- if (strcasecmp(s, *i) == 0)
- return 1;
- ++i;
- }
- return 0;
-}
-
-
-static u_quad_t
-rmultiply(u_quad_t n1, u_quad_t n2)
-{
- u_quad_t m, r;
- int b1, b2;
-
- static int bpw = 0;
-
- /* Handle 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);
-}
-
-
-/*
- * login_getcaptime()
- * From the login_cap_t <lc>, get the capability <cap>, which is
- * formatted as a time (e.g., "<cap>=10h3m2s"). If <cap> is not
- * present in <lc>, return <def>; if there is an error of some kind,
- * return <error>.
- */
-
-rlim_t
-login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
-{
- char *res, *ep, *oval;
- int r;
- rlim_t tot;
-
- errno = 0;
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
-
- /*
- * Look for <cap> in lc_cap.
- * If it's not there (-1), return <def>.
- * If there's an error, return <error>.
- */
-
- if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1)
- return def;
- else if (r < 0) {
- errno = ERANGE;
- return error;
- }
-
- /* "inf" and "infinity" are special cases */
- if (isinfinite(res))
- return RLIM_INFINITY;
-
- /*
- * Now go through the string, turning something like 1h2m3s into
- * an integral value. Whee.
- */
-
- errno = 0;
- tot = 0;
- oval = res;
- while (*res) {
- rlim_t tim = strtoq(res, &ep, 0);
- rlim_t mult = 1;
-
- if (ep == NULL || ep == res || errno != 0) {
- invalid:
- syslog(LOG_WARNING, "login_getcaptime: class '%s' bad value %s=%s",
- lc->lc_class, cap, oval);
- errno = ERANGE;
- return error;
- }
- /* Look for suffixes */
- switch (*ep++) {
- case 0:
- ep--;
- break; /* end of string */
- case 's': case 'S': /* seconds */
- break;
- case 'm': case 'M': /* minutes */
- mult = 60;
- break;
- case 'h': case 'H': /* hours */
- mult = 60L * 60L;
- break;
- case 'd': case 'D': /* days */
- mult = 60L * 60L * 24L;
- break;
- case 'w': case 'W': /* weeks */
- mult = 60L * 60L * 24L * 7L;
- break;
- case 'y': case 'Y': /* 365-day years */
- mult = 60L * 60L * 24L * 365L;
- break;
- default:
- goto invalid;
- }
- res = ep;
- tot += rmultiply(tim, mult);
- if (errno)
- goto invalid;
- }
-
- return tot;
-}
-
-
-/*
- * login_getcapnum()
- * From the login_cap_t <lc>, extract the numerical value <cap>.
- * If it is not present, return <def> for a default, and return
- * <error> if there is an error.
- * Like login_getcaptime(), only it only converts to a number, not
- * to a time; "infinity" and "inf" are 'special.'
- */
-
-rlim_t
-login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
-{
- char *ep, *res;
- int r;
- rlim_t val;
-
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
-
- /*
- * For BSDI compatibility, try for the tag=<val> first
- */
- if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) {
- long lval;
- /* string capability not present, so try for tag#<val> as numeric */
- if ((r = cgetnum(lc->lc_cap, cap, &lval)) == -1)
- return def; /* Not there, so return default */
- else if (r >= 0)
- return (rlim_t)lval;
- }
-
- if (r < 0) {
- errno = ERANGE;
- return error;
- }
-
- if (isinfinite(res))
- return RLIM_INFINITY;
-
- errno = 0;
- val = strtoq(res, &ep, 0);
- if (ep == NULL || ep == res || errno != 0) {
- syslog(LOG_WARNING, "login_getcapnum: class '%s' bad value %s=%s",
- lc->lc_class, cap, res);
- errno = ERANGE;
- return error;
- }
-
- return val;
-}
-
-
-
-/*
- * login_getcapsize()
- * From the login_cap_t <lc>, extract the capability <cap>, which is
- * formatted as a size (e.g., "<cap>=10M"); it can also be "infinity".
- * If not present, return <def>, or <error> if there is an error of
- * some sort.
- */
-
-rlim_t
-login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
-{
- char *ep, *res, *oval;
- int r;
- rlim_t tot;
-
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
-
- if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1)
- return def;
- else if (r < 0) {
- errno = ERANGE;
- return error;
- }
-
- if (isinfinite(res))
- return RLIM_INFINITY;
-
- errno = 0;
- tot = 0;
- oval = res;
- while (*res) {
- rlim_t siz = strtoq(res, &ep, 0);
- rlim_t mult = 1;
-
- if (ep == NULL || ep == res || errno != 0) {
- invalid:
- syslog(LOG_WARNING, "login_getcapsize: class '%s' bad value %s=%s",
- lc->lc_class, cap, oval);
- errno = ERANGE;
- return error;
- }
- switch (*ep++) {
- case 0: /* end of string */
- ep--;
- break;
- case 'b': case 'B': /* 512-byte blocks */
- mult = 512;
- break;
- case 'k': case 'K': /* 1024-byte Kilobytes */
- mult = 1024;
- break;
- case 'm': case 'M': /* 1024-k kbytes */
- mult = 1024 * 1024;
- break;
- case 'g': case 'G': /* 1Gbyte */
- mult = 1024 * 1024 * 1024;
- break;
- case 't': case 'T': /* 1TBte */
- mult = 1024LL * 1024LL * 1024LL * 1024LL;
- break;
- default:
- goto invalid;
- }
- res = ep;
- tot += rmultiply(siz, mult);
- if (errno)
- goto invalid;
- }
-
- return tot;
-}
-
-
-/*
- * login_getcapbool()
- * From the login_cap_t <lc>, check for the existance of the capability
- * of <cap>. Return <def> if <lc>->lc_cap is NULL, otherwise return
- * the whether or not <cap> exists there.
- */
-
-int
-login_getcapbool(login_cap_t *lc, const char *cap, int def)
-{
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
- return (cgetcap(lc->lc_cap, cap, ':') != NULL);
-}
-
-
-/*
- * login_getstyle()
- * Given a login_cap entry <lc>, and optionally a type of auth <auth>,
- * and optionally a style <style>, find the style that best suits these
- * rules:
- * 1. If <auth> is non-null, look for an "auth-<auth>=" string
- * in the capability; if not present, default to "auth=".
- * 2. If there is no auth list found from (1), default to
- * "passwd" as an authorization list.
- * 3. If <style> is non-null, look for <style> in the list of
- * authorization methods found from (2); if <style> is NULL, default
- * to LOGIN_DEFSTYLE ("passwd").
- * 4. If the chosen style is found in the chosen list of authorization
- * methods, return that; otherwise, return NULL.
- * E.g.:
- * login_getstyle(lc, NULL, "ftp");
- * login_getstyle(lc, "login", NULL);
- * login_getstyle(lc, "skey", "network");
- */
-
-const char *
-login_getstyle(login_cap_t *lc, const char *style, const char *auth)
-{
- int i;
- const char **authtypes = NULL;
- char *auths= NULL;
- char realauth[64];
-
- static const char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
-
- if (auth != NULL && *auth != '\0') {
- if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < (int)sizeof(realauth))
- authtypes = login_getcaplist(lc, realauth, NULL);
- }
-
- if (authtypes == NULL)
- authtypes = login_getcaplist(lc, "auth", NULL);
-
- if (authtypes == NULL)
- authtypes = defauthtypes;
-
- /*
- * We have at least one authtype now; auths is a comma-separated
- * (or space-separated) list of authentication types. We have to
- * convert from this to an array of char*'s; authtypes then gets this.
- */
- i = 0;
- if (style != NULL && *style != '\0') {
- while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0)
- i++;
- }
-
- lc->lc_style = NULL;
- if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL)
- lc->lc_style = auths;
-
- if (lc->lc_style != NULL)
- lc->lc_style = strdup(lc->lc_style);
-
- return lc->lc_style;
-}
diff --git a/libutil/login_cap.h b/libutil/login_cap.h
deleted file mode 100644
index 082e34b..0000000
--- a/libutil/login_cap.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*-
- * Copyright (c) 1996 by
- * Sean Eric Fagan <sef@kithrup.com>
- * David Nugent <davidn@blaze.net.au>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, is permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice immediately at the beginning of the file, without modification,
- * 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. This work was done expressly for inclusion into FreeBSD. Other use
- * is permitted provided this notation is included.
- * 4. Absolutely no warranty of function or purpose is made by the authors.
- * 5. Modifications may be freely made to this file providing the above
- * conditions are met.
- *
- * Low-level routines relating to the user capabilities database
- *
- * Was login_cap.h,v 1.9 1997/05/07 20:00:01 eivind Exp
- * $FreeBSD$
- */
-
-#ifndef _LOGIN_CAP_H_
-#define _LOGIN_CAP_H_
-
-#define LOGIN_DEFCLASS "default"
-#define LOGIN_DEFROOTCLASS "root"
-#define LOGIN_MECLASS "me"
-#define LOGIN_DEFSTYLE "passwd"
-#define LOGIN_DEFSERVICE "login"
-#define LOGIN_DEFUMASK 022
-#define LOGIN_DEFPRI 0
-#define _PATH_LOGIN_CONF "/etc/login.conf"
-#define _FILE_LOGIN_CONF ".login_conf"
-#define _PATH_AUTHPROG "/usr/libexec/login_"
-
-#define LOGIN_SETGROUP 0x0001 /* set group */
-#define LOGIN_SETLOGIN 0x0002 /* set login (via setlogin) */
-#define LOGIN_SETPATH 0x0004 /* set path */
-#define LOGIN_SETPRIORITY 0x0008 /* set priority */
-#define LOGIN_SETRESOURCES 0x0010 /* set resources (cputime, etc.) */
-#define LOGIN_SETUMASK 0x0020 /* set umask, obviously */
-#define LOGIN_SETUSER 0x0040 /* set user (via setuid) */
-#define LOGIN_SETENV 0x0080 /* set user environment */
-#define LOGIN_SETMAC 0x0100 /* set user default MAC label */
-#define LOGIN_SETCPUMASK 0x0200 /* set user cpumask */
-#define LOGIN_SETALL 0x03ff /* set everything */
-
-#define BI_AUTH "authorize" /* accepted authentication */
-#define BI_REJECT "reject" /* rejected authentication */
-#define BI_CHALLENG "reject challenge" /* reject with a challenge */
-#define BI_SILENT "reject silent" /* reject silently */
-#define BI_REMOVE "remove" /* remove file on error */
-#define BI_ROOTOKAY "authorize root" /* root authenticated */
-#define BI_SECURE "authorize secure" /* okay on non-secure line */
-#define BI_SETENV "setenv" /* set environment variable */
-#define BI_VALUE "value" /* set local variable */
-
-#define AUTH_OKAY 0x01 /* user authenticated */
-#define AUTH_ROOTOKAY 0x02 /* root login okay */
-#define AUTH_SECURE 0x04 /* secure login */
-#define AUTH_SILENT 0x08 /* silent rejection */
-#define AUTH_CHALLENGE 0x10 /* a chellenge was given */
-
-#define AUTH_ALLOW (AUTH_OKAY | AUTH_ROOTOKAY | AUTH_SECURE)
-
-typedef struct login_cap {
- char *lc_class;
- char *lc_cap;
- char *lc_style;
-} login_cap_t;
-
-typedef struct login_time {
- u_short lt_start; /* Start time */
- u_short lt_end; /* End time */
-#define LTM_NONE 0x00
-#define LTM_SUN 0x01
-#define LTM_MON 0x02
-#define LTM_TUE 0x04
-#define LTM_WED 0x08
-#define LTM_THU 0x10
-#define LTM_FRI 0x20
-#define LTM_SAT 0x40
-#define LTM_ANY 0x7F
-#define LTM_WK 0x3E
-#define LTM_WD 0x41
- u_char lt_dow; /* Days of week */
-} login_time_t;
-
-#define LC_MAXTIMES 64
-
-#include <sys/cdefs.h>
-__BEGIN_DECLS
-struct passwd;
-
-void login_close(login_cap_t *);
-login_cap_t *login_getclassbyname(const char *, const struct passwd *);
-login_cap_t *login_getclass(const char *);
-login_cap_t *login_getpwclass(const struct passwd *);
-login_cap_t *login_getuserclass(const struct passwd *);
-
-const char *login_getcapstr(login_cap_t *, const char *, const char *,
- const char *);
-const char **login_getcaplist(login_cap_t *, const char *, const char *);
-const char *login_getstyle(login_cap_t *, const char *, const char *);
-rlim_t login_getcaptime(login_cap_t *, const char *, rlim_t, rlim_t);
-rlim_t login_getcapnum(login_cap_t *, const char *, rlim_t, rlim_t);
-rlim_t login_getcapsize(login_cap_t *, const char *, rlim_t, rlim_t);
-const char *login_getpath(login_cap_t *, const char *, const char *);
-int login_getcapbool(login_cap_t *, const char *, int);
-const char *login_setcryptfmt(login_cap_t *, const char *, const char *);
-
-int setclasscontext(const char *, unsigned int);
-void setclasscpumask(login_cap_t *);
-int setusercontext(login_cap_t *, const struct passwd *, uid_t, unsigned int);
-void setclassresources(login_cap_t *);
-void setclassenvironment(login_cap_t *, const struct passwd *, int);
-
-/* Most of these functions are deprecated */
-int auth_approve(login_cap_t *, const char *, const char *);
-int auth_check(const char *, const char *, const char *, const char *, int *);
-void auth_env(void);
-char *auth_mkvalue(const char *);
-int auth_response(const char *, const char *, const char *, const char *, int *,
- const char *, const char *);
-void auth_rmfiles(void);
-int auth_scan(int);
-int auth_script(const char *, ...);
-int auth_script_data(const char *, int, const char *, ...);
-char *auth_valud(const char *);
-int auth_setopt(const char *, const char *);
-void auth_clropts(void);
-
-void auth_checknologin(login_cap_t *);
-int auth_cat(const char *);
-
-int auth_ttyok(login_cap_t *, const char *);
-int auth_hostok(login_cap_t *, const char *, char const *);
-int auth_timeok(login_cap_t *, time_t);
-
-struct tm;
-
-login_time_t parse_lt(const char *);
-int in_lt(const login_time_t *, time_t *);
-int in_ltm(const login_time_t *, struct tm *, time_t *);
-int in_ltms(const login_time_t *, struct tm *, time_t *);
-int in_lts(const login_time_t *, time_t *);
-
-/* helper functions */
-
-int login_strinlist(const char **, char const *, int);
-int login_str2inlist(const char **, const char *, const char *, int);
-login_time_t * login_timelist(login_cap_t *, char const *, int *,
- login_time_t **);
-int login_ttyok(login_cap_t *, const char *, const char *, const char *);
-int login_hostok(login_cap_t *, const char *, const char *, const char *,
- const char *);
-
-__END_DECLS
-
-#endif /* _LOGIN_CAP_H_ */
diff --git a/libutil/login_crypt.c b/libutil/login_crypt.c
deleted file mode 100644
index c65fc9b..0000000
--- a/libutil/login_crypt.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-
- * Copyright (c) 2000 Brian Fundakowski Feldman
- * 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 AUTHOR 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 AUTHOR 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>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-
-#include <login_cap.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-const char *
-login_setcryptfmt(login_cap_t *lc, const char *def, const char *error) {
- const char *cipher;
-
- cipher = login_getcapstr(lc, "passwd_format", def, NULL);
- if (getenv("CRYPT_DEBUG") != NULL)
- fprintf(stderr, "login_setcryptfmt: "
- "passwd_format = %s\n", cipher);
- if (cipher == NULL)
- return (error);
- if (!crypt_set_format(cipher))
- return (error);
- return (cipher);
-}
diff --git a/libutil/pw_util.c b/libutil/pw_util.c
deleted file mode 100644
index 75459e3..0000000
--- a/libutil/pw_util.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project by
- * ThinkSec AS and NAI Labs, the Security Research Division of Network
- * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
- * ("CBOSS"), as part of the DARPA CHATS research program.
- *
- * 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.
- * 4. 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 lint
-#if 0
-static const char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-/*
- * This file is used by all the "password" programs; vipw(8), chpass(1),
- * and passwd(1).
- */
-
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <libgen.h>
-#include <paths.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <libutil.h>
-
-static pid_t editpid = -1;
-static int lockfd = -1;
-static char masterpasswd[PATH_MAX];
-static char passwd_dir[PATH_MAX];
-static char tempname[PATH_MAX];
-static int initialized;
-
-#if 0
-void
-pw_cont(int sig)
-{
-
- if (editpid != -1)
- kill(editpid, sig);
-}
-#endif
-
-/*
- * Initialize statics and set limits, signals & umask to try to avoid
- * interruptions, crashes etc. that might expose passord data.
- */
-int
-pw_init(const char *dir, const char *master)
-{
-#if 0
- struct rlimit rlim;
-#endif
-
- if (dir == NULL) {
- strcpy(passwd_dir, _PATH_ETC);
- } else {
- if (strlen(dir) >= sizeof(passwd_dir)) {
- errno = ENAMETOOLONG;
- return (-1);
- }
- strcpy(passwd_dir, dir);
- }
-
- if (master == NULL) {
- if (dir == NULL) {
- strcpy(masterpasswd, _PATH_MASTERPASSWD);
- } else if (snprintf(masterpasswd, sizeof(masterpasswd), "%s/%s",
- passwd_dir, _MASTERPASSWD) > (int)sizeof(masterpasswd)) {
- errno = ENAMETOOLONG;
- return (-1);
- }
- } else {
- if (strlen(master) >= sizeof(masterpasswd)) {
- errno = ENAMETOOLONG;
- return (-1);
- }
- strcpy(masterpasswd, master);
- }
-
- /*
- * The code that follows is extremely disruptive to the calling
- * process, and is therefore disabled until someone can conceive
- * of a realistic scenario where it would fend off a compromise.
- * Race conditions concerning the temporary files can be guarded
- * against in other ways than masking signals (by checking stat(2)
- * results after creation).
- */
-#if 0
- /* 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);
-
- /* 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);
-
- /* Create with exact permissions. */
- (void)umask(0);
-#endif
- initialized = 1;
- return (0);
-}
-
-/*
- * Lock the master password file.
- */
-int
-pw_lock(void)
-{
-
- if (*masterpasswd == '\0')
- return (-1);
-
- /*
- * If the master password file doesn't exist, the system is hosed.
- * Might as well try to build one. Set the close-on-exec bit so
- * that users can't get at the encrypted passwords while editing.
- * Open should allow flock'ing the file; see 4.4BSD. XXX
- */
- for (;;) {
- struct stat st;
-
- lockfd = open(masterpasswd, O_RDONLY, 0);
- if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
- err(1, "%s", masterpasswd);
- /* XXX vulnerable to race conditions */
- if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
- if (errno == EWOULDBLOCK) {
- errx(1, "the password db file is busy");
- } else {
- err(1, "could not lock the passwd file: ");
- }
- }
-
- /*
- * If the password file was replaced while we were trying to
- * get the lock, our hardlink count will be 0 and we have to
- * close and retry.
- */
- if (fstat(lockfd, &st) == -1)
- err(1, "fstat() failed: ");
- if (st.st_nlink != 0)
- break;
- close(lockfd);
- lockfd = -1;
- }
- return (lockfd);
-}
-
-/*
- * Create and open a presumably safe temp file for editing the password
- * data, and copy the master password file into it.
- */
-int
-pw_tmp(int mfd)
-{
- char buf[8192];
- ssize_t nr;
- const char *p;
- int tfd;
-
- if (*masterpasswd == '\0')
- return (-1);
- if ((p = strrchr(masterpasswd, '/')))
- ++p;
- else
- p = masterpasswd;
- if (snprintf(tempname, sizeof(tempname), "%.*spw.XXXXXX",
- (int)(p - masterpasswd), masterpasswd) >= (int)sizeof(tempname)) {
- errno = ENAMETOOLONG;
- return (-1);
- }
- if ((tfd = mkstemp(tempname)) == -1)
- return (-1);
- if (mfd != -1) {
- while ((nr = read(mfd, buf, sizeof(buf))) > 0)
- if (write(tfd, buf, (size_t)nr) != nr)
- break;
- if (nr != 0) {
- unlink(tempname);
- *tempname = '\0';
- close(tfd);
- return (-1);
- }
- }
- return (tfd);
-}
-
-/*
- * Regenerate the password database.
- */
-int
-pw_mkdb(const char *user)
-{
- int pstat;
- pid_t pid;
-
- (void)fflush(stderr);
- switch ((pid = fork())) {
- case -1:
- return (-1);
- case 0:
- /* child */
- if (user == NULL)
- execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
- "-d", passwd_dir, tempname, (char *)NULL);
- else
- execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
- "-d", passwd_dir, "-u", user, tempname,
- (char *)NULL);
- _exit(1);
- /* NOTREACHED */
- default:
- /* parent */
- break;
- }
- if (waitpid(pid, &pstat, 0) == -1)
- return (-1);
- if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
- return (0);
- errno = 0;
- return (-1);
-}
-
-/*
- * Edit the temp file. Return -1 on error, >0 if the file was modified, 0
- * if it was not.
- */
-int
-pw_edit(int notsetuid)
-{
- struct sigaction sa, sa_int, sa_quit;
- sigset_t oldsigset, nsigset;
- struct stat st1, st2;
- const char *editor;
- int pstat;
-
- if ((editor = getenv("EDITOR")) == NULL)
- editor = _PATH_VI;
- if (stat(tempname, &st1) == -1)
- return (-1);
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(SIGINT, &sa, &sa_int);
- sigaction(SIGQUIT, &sa, &sa_quit);
- sigemptyset(&nsigset);
- sigaddset(&nsigset, SIGCHLD);
- sigprocmask(SIG_BLOCK, &nsigset, &oldsigset);
- switch ((editpid = fork())) {
- case -1:
- return (-1);
- case 0:
- sigaction(SIGINT, &sa_int, NULL);
- sigaction(SIGQUIT, &sa_quit, NULL);
- sigprocmask(SIG_SETMASK, &oldsigset, NULL);
- if (notsetuid) {
- (void)setgid(getgid());
- (void)setuid(getuid());
- }
- errno = 0;
- execlp(editor, basename(editor), tempname, (char *)NULL);
- _exit(errno);
- default:
- /* parent */
- break;
- }
- for (;;) {
- if (waitpid(editpid, &pstat, WUNTRACED) == -1) {
- if (errno == EINTR)
- continue;
- unlink(tempname);
- editpid = -1;
- break;
- } else if (WIFSTOPPED(pstat)) {
- raise(WSTOPSIG(pstat));
- } else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0) {
- editpid = -1;
- break;
- } else {
- unlink(tempname);
- editpid = -1;
- break;
- }
- }
- sigaction(SIGINT, &sa_int, NULL);
- sigaction(SIGQUIT, &sa_quit, NULL);
- sigprocmask(SIG_SETMASK, &oldsigset, NULL);
- if (stat(tempname, &st2) == -1)
- return (-1);
- return (st1.st_mtime != st2.st_mtime);
-}
-
-/*
- * Clean up. Preserve errno for the caller's convenience.
- */
-void
-pw_fini(void)
-{
- int serrno, status;
-
- if (!initialized)
- return;
- initialized = 0;
- serrno = errno;
- if (editpid != -1) {
- kill(editpid, SIGTERM);
- kill(editpid, SIGCONT);
- waitpid(editpid, &status, 0);
- editpid = -1;
- }
- if (*tempname != '\0') {
- unlink(tempname);
- *tempname = '\0';
- }
- if (lockfd != -1)
- close(lockfd);
- errno = serrno;
-}
-
-/*
- * Compares two struct pwds.
- */
-int
-pw_equal(const struct passwd *pw1, const struct passwd *pw2)
-{
- return (strcmp(pw1->pw_name, pw2->pw_name) == 0 &&
- pw1->pw_uid == pw2->pw_uid &&
- pw1->pw_gid == pw2->pw_gid &&
- strcmp(pw1->pw_class, pw2->pw_class) == 0 &&
- pw1->pw_change == pw2->pw_change &&
- pw1->pw_expire == pw2->pw_expire &&
- strcmp(pw1->pw_gecos, pw2->pw_gecos) == 0 &&
- strcmp(pw1->pw_dir, pw2->pw_dir) == 0 &&
- strcmp(pw1->pw_shell, pw2->pw_shell) == 0);
-}
-
-/*
- * Make a passwd line out of a struct passwd.
- */
-char *
-pw_make(const struct passwd *pw)
-{
- char *line;
-
- asprintf(&line, "%s:%s:%ju:%ju:%s:%ju:%ju:%s:%s:%s", pw->pw_name,
- pw->pw_passwd, (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
- pw->pw_class, (uintmax_t)pw->pw_change, (uintmax_t)pw->pw_expire,
- pw->pw_gecos, pw->pw_dir, pw->pw_shell);
- return line;
-}
-
-/*
- * Copy password file from one descriptor to another, replacing or adding
- * a single record on the way.
- */
-int
-pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
-{
- char buf[8192], *end, *line, *p, *q, *r, t;
- struct passwd *fpw;
- size_t len;
- int eof, readlen;
-
- if ((line = pw_make(pw)) == NULL)
- return (-1);
-
- eof = 0;
- len = 0;
- p = q = end = buf;
- for (;;) {
- /* find the end of the current line */
- for (p = q; q < end && *q != '\0'; ++q)
- if (*q == '\n')
- break;
-
- /* if we don't have a complete line, fill up the buffer */
- if (q >= end) {
- if (eof)
- break;
- if ((size_t)(q - p) >= sizeof(buf)) {
- warnx("passwd line too long");
- errno = EINVAL; /* hack */
- goto err;
- }
- if (p < end) {
- q = memmove(buf, p, end - p);
- end -= p - buf;
- } else {
- p = q = end = buf;
- }
- readlen = read(ffd, end, sizeof(buf) - (end - buf));
- if (readlen == -1)
- goto err;
- else
- len = (size_t)readlen;
- if (len == 0 && p == buf)
- break;
- end += len;
- len = end - buf;
- if (len < (ssize_t)sizeof(buf)) {
- eof = 1;
- if (len > 0 && buf[len - 1] != '\n')
- ++len, *end++ = '\n';
- }
- continue;
- }
-
- /* is it a blank line or a comment? */
- for (r = p; r < q && isspace(*r); ++r)
- /* nothing */ ;
- if (r == q || *r == '#') {
- /* yep */
- if (write(tfd, p, q - p + 1) != q - p + 1)
- goto err;
- ++q;
- continue;
- }
-
- /* is it the one we're looking for? */
-
- t = *q;
- *q = '\0';
-
- fpw = pw_scan(r, PWSCAN_MASTER);
-
- /*
- * fpw is either the struct passwd for the current line,
- * or NULL if the line is malformed.
- */
-
- *q = t;
- if (fpw == NULL || strcmp(fpw->pw_name, pw->pw_name) != 0) {
- /* nope */
- if (fpw != NULL)
- free(fpw);
- if (write(tfd, p, q - p + 1) != q - p + 1)
- goto err;
- ++q;
- continue;
- }
- if (old_pw && !pw_equal(fpw, old_pw)) {
- warnx("entry inconsistent");
- free(fpw);
- errno = EINVAL; /* hack */
- goto err;
- }
- free(fpw);
-
- /* it is, replace it */
- len = strlen(line);
- if (write(tfd, line, len) != (int)len)
- goto err;
-
- /* we're done, just copy the rest over */
- for (;;) {
- if (write(tfd, q, end - q) != end - q)
- goto err;
- q = buf;
- readlen = read(ffd, buf, sizeof(buf));
- if (readlen == 0)
- break;
- else
- len = (size_t)readlen;
- if (readlen == -1)
- goto err;
- end = buf + len;
- }
- goto done;
- }
-
- /* if we got here, we have a new entry */
- len = strlen(line);
- if ((size_t)write(tfd, line, len) != len ||
- write(tfd, "\n", 1) != 1)
- goto err;
- done:
- free(line);
- return (0);
- err:
- free(line);
- return (-1);
-}
-
-/*
- * Return the current value of tempname.
- */
-const char *
-pw_tempname(void)
-{
-
- return (tempname);
-}
-
-/*
- * Duplicate a struct passwd.
- */
-struct passwd *
-pw_dup(const struct passwd *pw)
-{
- struct passwd *npw;
- ssize_t len;
-
- len = sizeof(*npw) +
- (pw->pw_name ? strlen(pw->pw_name) + 1 : 0) +
- (pw->pw_passwd ? strlen(pw->pw_passwd) + 1 : 0) +
- (pw->pw_class ? strlen(pw->pw_class) + 1 : 0) +
- (pw->pw_gecos ? strlen(pw->pw_gecos) + 1 : 0) +
- (pw->pw_dir ? strlen(pw->pw_dir) + 1 : 0) +
- (pw->pw_shell ? strlen(pw->pw_shell) + 1 : 0);
- if ((npw = malloc((size_t)len)) == NULL)
- return (NULL);
- memcpy(npw, pw, sizeof(*npw));
- len = sizeof(*npw);
- if (pw->pw_name) {
- npw->pw_name = ((char *)npw) + len;
- len += sprintf(npw->pw_name, "%s", pw->pw_name) + 1;
- }
- if (pw->pw_passwd) {
- npw->pw_passwd = ((char *)npw) + len;
- len += sprintf(npw->pw_passwd, "%s", pw->pw_passwd) + 1;
- }
- if (pw->pw_class) {
- npw->pw_class = ((char *)npw) + len;
- len += sprintf(npw->pw_class, "%s", pw->pw_class) + 1;
- }
- if (pw->pw_gecos) {
- npw->pw_gecos = ((char *)npw) + len;
- len += sprintf(npw->pw_gecos, "%s", pw->pw_gecos) + 1;
- }
- if (pw->pw_dir) {
- npw->pw_dir = ((char *)npw) + len;
- len += sprintf(npw->pw_dir, "%s", pw->pw_dir) + 1;
- }
- if (pw->pw_shell) {
- npw->pw_shell = ((char *)npw) + len;
- len += sprintf(npw->pw_shell, "%s", pw->pw_shell) + 1;
- }
- return (npw);
-}
-
-#include "pw_scan.h"
-
-/*
- * Wrapper around an internal libc function
- */
-struct passwd *
-pw_scan(const char *line, int flags)
-{
- struct passwd pw, *ret;
- char *bp;
-
- if ((bp = strdup(line)) == NULL)
- return (NULL);
- if (!__pw_scan(bp, &pw, flags)) {
- free(bp);
- return (NULL);
- }
- ret = pw_dup(&pw);
- free(bp);
- return (ret);
-}
diff --git a/pw/Makefile b/pw/Makefile
deleted file mode 100644
index ae0023c..0000000
--- a/pw/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# $FreeBSD$
-
-PROG= pw
-MAN= pw.conf.5 pw.8
-SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \
- grupd.c pwupd.c fileupd.c edgroup.c psdate.c \
- bitmap.c cpdir.c rm_r.c
-
-WARNS?= 1
-
-DPADD= ${LIBCRYPT} ${LIBUTIL}
-LDADD= -lcrypt -lutil
-
-.include <bsd.prog.mk>
diff --git a/pw/README b/pw/README
deleted file mode 100644
index bbb1539..0000000
--- a/pw/README
+++ /dev/null
@@ -1,22 +0,0 @@
-
-pw is a command-line driven passwd/group editor utility that provides
-an easy and safe means of modifying of any/all fields in the system
-password files, and has an add, modify and delete mode for user and
-group records. Command line options have been fashioned to be similar
-to those used by the Sun/shadow commands: useradd, usermod, userdel,
-groupadd, groupmod, groupdel, but combines all operations within the
-single command `pw'.
-
-User add mode also provides a means of easily setting system useradd
-defaults (see pw.conf.5), so that adding a user is as easy as issuing
-the command "pw useradd <loginid>". Creation of a unique primary
-group for each user and automatic membership in secondary groups
-is fully supported.
-
-This program may be FreeBSD specific, but should be trivial to port to
-other bsd4.4 variants.
-
-Author and maintainer: David L. Nugent, <davidn@blaze.net.au>
-
-$FreeBSD$
-
diff --git a/pw/bitmap.c b/pw/bitmap.c
deleted file mode 100644
index bcfea7e..0000000
--- a/pw/bitmap.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "bitmap.h"
-
-struct bitmap
-bm_alloc(int size)
-{
- struct bitmap bm;
- int szmap = (size / 8) + !!(size % 8);
-
- bm.size = size;
- bm.map = malloc(szmap);
- if (bm.map)
- memset(bm.map, 0, szmap);
- return bm;
-}
-
-void
-bm_dealloc(struct bitmap * bm)
-{
- if (bm->map)
- free(bm->map);
-}
-
-static void
-bm_getmask(int *pos, unsigned char *bmask)
-{
- *bmask = (unsigned char) (1 << (*pos % 8));
- *pos /= 8;
-}
-
-void
-bm_setbit(struct bitmap * bm, int pos)
-{
- unsigned char bmask;
-
- bm_getmask(&pos, &bmask);
- bm->map[pos] |= bmask;
-}
-
-void
-bm_clrbit(struct bitmap * bm, int pos)
-{
- unsigned char bmask;
-
- bm_getmask(&pos, &bmask);
- bm->map[pos] &= ~bmask;
-}
-
-int
-bm_isset(struct bitmap * bm, int pos)
-{
- unsigned char bmask;
-
- bm_getmask(&pos, &bmask);
- return !!(bm->map[pos] & bmask);
-}
-
-int
-bm_firstunset(struct bitmap * bm)
-{
- int szmap = (bm->size / 8) + !!(bm->size % 8);
- int at = 0;
- int pos = 0;
-
- while (pos < szmap) {
- unsigned char bmv = bm->map[pos++];
- unsigned char bmask = 1;
-
- while (bmask & 0xff) {
- if ((bmv & bmask) == 0)
- return at;
- bmask <<= 1;
- ++at;
- }
- }
- return at;
-}
-
-int
-bm_lastset(struct bitmap * bm)
-{
- int szmap = (bm->size / 8) + !!(bm->size % 8);
- int at = 0;
- int pos = 0;
- int ofs = 0;
-
- while (pos < szmap) {
- unsigned char bmv = bm->map[pos++];
- unsigned char bmask = 1;
-
- while (bmask & 0xff) {
- if ((bmv & bmask) != 0)
- ofs = at;
- bmask <<= 1;
- ++at;
- }
- }
- return ofs;
-}
diff --git a/pw/bitmap.h b/pw/bitmap.h
deleted file mode 100644
index 4d6cfe4..0000000
--- a/pw/bitmap.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _BITMAP_H_
-#define _BITMAP_H_
-
-#include <sys/cdefs.h>
-
-struct bitmap
-{
- int size;
- unsigned char *map;
-};
-
-__BEGIN_DECLS
-struct bitmap bm_alloc(int size);
-void bm_dealloc(struct bitmap * bm);
-void bm_setbit(struct bitmap * bm, int pos);
-void bm_clrbit(struct bitmap * bm, int pos);
-int bm_isset(struct bitmap * bm, int pos);
-int bm_firstunset(struct bitmap * bm);
-int bm_lastset(struct bitmap * bm);
-__END_DECLS
-
-#endif /* !_BITMAP_H */
diff --git a/pw/cpdir.c b/pw/cpdir.c
deleted file mode 100644
index f370421..0000000
--- a/pw/cpdir.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <dirent.h>
-
-#include "pwupd.h"
-
-void
-copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid)
-{
- char src[MAXPATHLEN];
- char dst[MAXPATHLEN];
- char lnk[MAXPATHLEN];
- int len;
-
- if (mkdir(dir, mode) != 0 && errno != EEXIST) {
- warn("mkdir(%s)", dir);
- } else {
- int infd, outfd;
- struct stat st;
-
- static char counter = 0;
- static char *copybuf = NULL;
-
- ++counter;
- chown(dir, uid, gid);
- if (skel != NULL && *skel != '\0') {
- DIR *d = opendir(skel);
-
- if (d != NULL) {
- struct dirent *e;
-
- while ((e = readdir(d)) != NULL) {
- char *p = e->d_name;
-
- if (snprintf(src, sizeof(src), "%s/%s", skel, p) >= (int)sizeof(src))
- warn("warning: pathname too long '%s/%s' (skel not copied)", skel, p);
- else if (lstat(src, &st) == 0) {
- if (strncmp(p, "dot.", 4) == 0) /* Conversion */
- p += 3;
- if (snprintf(dst, sizeof(dst), "%s/%s", dir, p) >= (int)sizeof(dst))
- warn("warning: path too long '%s/%s' (skel file skipped)", dir, p);
- else {
- if (S_ISDIR(st.st_mode)) { /* Recurse for this */
- if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0)
- copymkdir(dst, src, (st.st_mode & 0777), uid, gid);
- chflags(dst, st.st_flags); /* propogate flags */
- } else if (S_ISLNK(st.st_mode) && (len = readlink(src, lnk, sizeof(lnk))) != -1) {
- lnk[len] = '\0';
- symlink(lnk, dst);
- lchown(dst, uid, gid);
- /*
- * Note: don't propogate special attributes
- * but do propogate file flags
- */
- } else if (S_ISREG(st.st_mode) && (outfd = open(dst, O_RDWR | O_CREAT | O_EXCL, st.st_mode)) != -1) {
- if ((infd = open(src, O_RDONLY)) == -1) {
- close(outfd);
- remove(dst);
- } else {
- int b;
-
- /*
- * Allocate our copy buffer if we need to
- */
- if (copybuf == NULL)
- copybuf = malloc(4096);
- while ((b = read(infd, copybuf, 4096)) > 0)
- write(outfd, copybuf, b);
- close(infd);
- /*
- * Propogate special filesystem flags
- */
- fchown(outfd, uid, gid);
- fchflags(outfd, st.st_flags);
- close(outfd);
- chown(dst, uid, gid);
- }
- }
- }
- }
- }
- closedir(d);
- }
- }
- if (--counter == 0 && copybuf != NULL) {
- free(copybuf);
- copybuf = NULL;
- }
- }
-}
-
diff --git a/pw/edgroup.c b/pw/edgroup.c
deleted file mode 100644
index 1cc46b4..0000000
--- a/pw/edgroup.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <pwd.h>
-#include <grp.h>
-#include <fcntl.h>
-#include <sys/param.h>
-#include <ctype.h>
-
-#include "pwupd.h"
-
-static int
-isingroup(char const * name, char **mem)
-{
- int i;
-
- for (i = 0; mem[i] != NULL; i++)
- if (strcmp(name, mem[i]) == 0)
- return i;
- return -1;
-}
-
-int
-editgroups(char *name, char **groups)
-{
- int rc = 0;
- int infd;
- char groupfile[MAXPATHLEN];
- char grouptmp[MAXPATHLEN];
-
- strncpy(groupfile, getgrpath(_GROUP), MAXPATHLEN - 5);
- groupfile[MAXPATHLEN - 5] = '\0';
- strcpy(grouptmp, groupfile);
- strcat(grouptmp, ".new");
-
- if ((infd = open(groupfile, O_RDWR | O_CREAT | O_EXLOCK, 0644)) != -1) {
- FILE *infp;
-
- if ((infp = fdopen(infd, "r+")) == NULL)
- close(infd);
- else {
- int outfd;
-
- if ((outfd = open(grouptmp, O_RDWR | O_CREAT | O_TRUNC, 0644)) != -1) {
- FILE *outfp;
-
- if ((outfp = fdopen(outfd, "w+")) == NULL)
- close(outfd);
- else {
- int linelen = PWBUFSZ;
- int outlen = PWBUFSZ;
- int memlen = 200; /* Arbitrary */
- char *line = malloc(linelen);
- char *outl = malloc(outlen);
- char **mems = malloc(memlen * sizeof(char *));
- int namlen = strlen(name);
-
- if (line == NULL || outl == NULL || mems == NULL) {
- mem_abort:
- rc = 0;
- } else {
- while (fgets(line, linelen, infp) != NULL) {
- char *p;
- int l;
-
- while ((p = strchr(line, '\n')) == NULL)
- {
- if (extendline(&line, &linelen, linelen + PWBUFSZ) == -1) {
- goto mem_abort;
- }
- l = strlen(line);
- if (fgets(line + l, linelen - l, infp) == NULL)
- break; /* No newline terminator on last line */
- }
- l = strlen(line) + namlen + 1;
- if (extendline(&outl, &outlen, l) == -1) {
- goto mem_abort;
- }
- if (*line == '#')
- strcpy(outl, line);
- else if (*line == '\n')
- *outl = '\0';
- else {
- int i,
- mno = 0;
- char *cp = line;
- char const *sep = ":\n";
- struct group grp;
-
- memset(&grp, 0, sizeof grp);
- for (i = 0; (p = strsep(&cp, sep)) != NULL; i++) {
- switch (i) {
- case 0: /* Group name */
- grp.gr_name = p;
- break;
- case 1: /* Group password */
- grp.gr_passwd = p;
- break;
- case 2: /* Group id */
- grp.gr_gid = atoi(p);
- break;
- case 3: /* Member list */
- cp = p;
- sep = ",\n";
- break;
- default: /* Individual members */
- if (*p) {
- if (extendarray(&mems, &memlen, mno + 2) == -1) {
- goto mem_abort;
- }
- mems[mno++] = p;
- }
- break;
- }
- }
- if (i < 2) /* Bail out - insufficient fields */
- continue;
-
- grp.gr_mem = mems;
- for (i = mno; i < memlen; i++)
- mems[i] = NULL;
-
- /*
- * Delete from group, or add to group?
- */
- if (groups == NULL || isingroup(grp.gr_name, groups) == -1) { /* Delete */
- int idx;
-
- while ((idx = isingroup(name, mems)) != -1) {
- for (i = idx; i < (memlen - 1); i++)
- mems[i] = mems[i + 1];
- mems[i] = NULL;
- --mno;
- }
- /*
- * Special case - deleting user and group may be user's own
- */
- if (groups == NULL && mems[0] == NULL && strcmp(name, grp.gr_name) == 0) {
- /*
- * First, make _sure_ we don't have other members
- */
- struct passwd *pwd;
-
- SETPWENT();
- while ((pwd = GETPWENT()) != NULL && (gid_t)pwd->pw_gid != (gid_t)grp.gr_gid);
- ENDPWENT();
- if (pwd == NULL) /* No members at all */
- continue; /* Drop the group */
- }
- } else if (isingroup(name, mems) == -1) {
- if (extendarray(&mems, &memlen, mno + 2) == -1) {
- goto mem_abort;
- }
- grp.gr_mem = mems; /* May have realloced() */
- mems[mno++] = name;
- mems[mno ] = NULL;
- }
- fmtgrentry(&outl, &outlen, &grp, PWF_GROUP);
- }
- fputs(outl, outfp);
- }
- if (fflush(outfp) != EOF) {
- rc = 1;
-
- /*
- * Copy data back into the original file and truncate
- */
- rewind(infp);
- rewind(outfp);
- while (fgets(outl, outlen, outfp) != NULL)
- fputs(outl, infp);
-
- /*
- * This is a gross hack, but we may have corrupted the
- * original file.
- */
- if (fflush(infp) == EOF || ferror(infp))
- rc = rename(grouptmp, groupfile) == 0;
- else
- ftruncate(infd, ftell(infp));
- }
- }
- free(mems);
- free(outl);
- free(line);
- fclose(outfp);
- }
- remove(grouptmp);
- }
- fclose(infp);
- }
- }
- return rc;
-}
diff --git a/pw/fileupd.c b/pw/fileupd.c
deleted file mode 100644
index b88f4fa..0000000
--- a/pw/fileupd.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "pwupd.h"
-
-int
-extendline(char **buf, int * buflen, int needed)
-{
- if (needed > *buflen) {
- char *tmp = realloc(*buf, needed);
- if (tmp == NULL)
- return -1;
- *buf = tmp;
- *buflen = needed;
- }
- return *buflen;
-}
-
-int
-extendarray(char ***buf, int * buflen, int needed)
-{
- if (needed > *buflen) {
- char **tmp = realloc(*buf, needed * sizeof(char *));
- if (tmp == NULL)
- return -1;
- *buf = tmp;
- *buflen = needed;
- }
- return *buflen;
-}
-
-
-int
-fileupdate(char const * filename, mode_t fmode, char const * newline, char const * prefix, int pfxlen, int updmode)
-{
- int rc = 0;
-
- if (pfxlen <= 1)
- rc = EINVAL;
- else {
- int infd = open(filename, O_RDWR | O_CREAT | O_EXLOCK, fmode);
-
- if (infd == -1)
- rc = errno;
- else {
- FILE *infp = fdopen(infd, "r+");
-
- if (infp == NULL) {
- rc = errno; /* Assumes fopen(3) sets errno from open(2) */
- close(infd);
- } else {
- int outfd;
- char file[MAXPATHLEN];
-
- strcpy(file, filename);
- strcat(file, ".new");
- outfd = open(file, O_RDWR | O_CREAT | O_TRUNC, fmode);
- if (outfd == -1)
- rc = errno;
- else {
- FILE *outfp = fdopen(outfd, "w+");
-
- if (outfp == NULL) {
- rc = errno;
- close(outfd);
- } else {
- int updated = UPD_CREATE;
- int linesize = PWBUFSZ;
- char *line = malloc(linesize);
-
- nextline:
- while (fgets(line, linesize, infp) != NULL) {
- char *p = strchr(line, '\n');
-
- while ((p = strchr(line, '\n')) == NULL) {
- int l;
- if (extendline(&line, &linesize, linesize + PWBUFSZ) == -1) {
- int ch;
- fputs(line, outfp);
- while ((ch = fgetc(infp)) != EOF) {
- fputc(ch, outfp);
- if (ch == '\n')
- break;
- }
- goto nextline;
- }
- l = strlen(line);
- if (fgets(line + l, linesize - l, infp) == NULL)
- break;
- }
- if (*line != '#' && *line != '\n') {
- if (!updated && strncmp(line, prefix, pfxlen) == 0) {
- updated = updmode == UPD_REPLACE ? UPD_REPLACE : UPD_DELETE;
-
- /*
- * Only actually write changes if updating
- */
- if (updmode == UPD_REPLACE)
- strcpy(line, newline);
- else if (updmode == UPD_DELETE)
- continue;
- }
- }
- fputs(line, outfp);
- }
-
- /*
- * Now, we need to decide what to do: If we are in
- * update mode, and no record was updated, then error If
- * we are in insert mode, and record already exists,
- * then error
- */
- if (updmode != updated)
- /* -1 return means:
- * update,delete=no user entry
- * create=entry exists
- */
- rc = -1;
- else {
-
- /*
- * If adding a new record, append it to the end
- */
- if (updmode == UPD_CREATE)
- fputs(newline, outfp);
-
- /*
- * Flush the file and check for the result
- */
- if (fflush(outfp) == EOF)
- rc = errno; /* Failed to update */
- else {
- /*
- * Copy data back into the
- * original file and truncate
- */
- rewind(infp);
- rewind(outfp);
- while (fgets(line, linesize, outfp) != NULL)
- fputs(line, infp);
-
- /*
- * If there was a problem with copying
- * we will just rename 'file.new'
- * to 'file'.
- * This is a gross hack, but we may have
- * corrupted the original file
- */
- if (fflush(infp) == EOF || ferror(infp))
- rename(file, filename);
- else
- ftruncate(infd, ftell(infp));
- }
- }
- free(line);
- fclose(outfp);
- }
- remove(file);
- }
- fclose(infp);
- }
- }
- }
- return rc;
-}
diff --git a/pw/grupd.c b/pw/grupd.c
deleted file mode 100644
index edff76d..0000000
--- a/pw/grupd.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-
-#include "pwupd.h"
-
-static char * grpath = _PATH_PWD;
-
-int
-setgrdir(const char * dir)
-{
- if (dir == NULL)
- return -1;
- else {
- char * d = malloc(strlen(dir)+1);
- if (d == NULL)
- return -1;
- grpath = strcpy(d, dir);
- }
- return 0;
-}
-
-char *
-getgrpath(const char * file)
-{
- static char pathbuf[MAXPATHLEN];
-
- snprintf(pathbuf, sizeof pathbuf, "%s/%s", grpath, file);
- return pathbuf;
-}
-
-int
-grdb(char *arg,...)
-{
- /*
- * This is a stub for now, but maybe eventually be functional
- * if ever an indexed version of /etc/groups is implemented.
- */
- arg=arg;
- return 0;
-}
-
-int
-fmtgrentry(char **buf, int * buflen, struct group * grp, int type)
-{
- int i, l;
-
- /*
- * Since a group line is of arbitrary length,
- * we need to calculate up-front just how long
- * it will need to be...
- */
- /* groupname : password : gid : */
- l = strlen(grp->gr_name) + 1 + strlen(grp->gr_passwd) + 1 + 5 + 1;
- /* group members + comma separator */
- for (i = 0; grp->gr_mem[i] != NULL; i++) {
- l += strlen(grp->gr_mem[i]) + 1;
- }
- l += 2; /* For newline & NUL */
- if (extendline(buf, buflen, l) == -1)
- l = -1;
- else{
- /*
- * Now we can safely format
- */
- if (type == PWF_STANDARD)
- l = sprintf(*buf, "%s:*:%ld:", grp->gr_name, (long) grp->gr_gid);
- else
- l = sprintf(*buf, "%s:%s:%ld:", grp->gr_name, grp->gr_passwd, (long) grp->gr_gid);
-
- /*
- * List members
- */
- for (i = 0; grp->gr_mem[i] != NULL; i++) {
- l += sprintf(*buf + l, "%s%s", i ? "," : "", grp->gr_mem[i]);
- }
-
- (*buf)[l++] = '\n';
- (*buf)[l] = '\0';
- }
- return l;
-}
-
-
-int
-fmtgrent(char **buf, int * buflen, struct group * grp)
-{
- return fmtgrentry(buf, buflen, grp, PWF_STANDARD);
-}
-
-
-static int
-gr_update(struct group * grp, char const * group, int mode)
-{
- int l;
- char pfx[64];
- int grbuflen = 0;
- char *grbuf = NULL;
-
- ENDGRENT();
- l = snprintf(pfx, sizeof pfx, "%s:", group);
-
- /*
- * Update the group file
- */
- if (grp != NULL && fmtgrentry(&grbuf, &grbuflen, grp, PWF_PASSWD) == -1)
- l = -1;
- else {
- l = fileupdate(getgrpath(_GROUP), 0644, grbuf, pfx, l, mode);
- if (l == 0)
- l = grdb(NULL);
- }
- if (grbuf != NULL)
- free(grbuf);
- return l;
-}
-
-
-int
-addgrent(struct group * grp)
-{
- return gr_update(grp, grp->gr_name, UPD_CREATE);
-}
-
-int
-chggrent(char const * login, struct group * grp)
-{
- return gr_update(grp, login, UPD_REPLACE);
-}
-
-int
-delgrent(struct group * grp)
-{
- return gr_update(NULL, grp->gr_name, UPD_DELETE);
-}
diff --git a/pw/psdate.c b/pw/psdate.c
deleted file mode 100644
index 3f4c010..0000000
--- a/pw/psdate.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "psdate.h"
-
-
-static int
-a2i(char const ** str)
-{
- int i = 0;
- char const *s = *str;
-
- if (isdigit((unsigned char)*s)) {
- i = atoi(s);
- while (isdigit((unsigned char)*s))
- ++s;
- *str = s;
- }
- return i;
-}
-
-static int
-numerics(char const * str)
-{
- int rc = isdigit((unsigned char)*str);
-
- if (rc)
- while (isdigit((unsigned char)*str) || *str == 'x')
- ++str;
- return rc && !*str;
-}
-
-static int
-aindex(char const * arr[], char const ** str, int len)
-{
- int l, i;
- char mystr[32];
-
- mystr[len] = '\0';
- l = strlen(strncpy(mystr, *str, len));
- for (i = 0; i < l; i++)
- mystr[i] = (char) tolower((unsigned char)mystr[i]);
- for (i = 0; arr[i] && strcmp(mystr, arr[i]) != 0; i++);
- if (arr[i] == NULL)
- i = -1;
- else { /* Skip past it */
- while (**str && isalpha((unsigned char)**str))
- ++(*str);
- /* And any following whitespace */
- while (**str && (**str == ',' || isspace((unsigned char)**str)))
- ++(*str);
- } /* Return index */
- return i;
-}
-
-static int
-weekday(char const ** str)
-{
- static char const *days[] =
- {"sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL};
-
- return aindex(days, str, 3);
-}
-
-static int
-month(char const ** str)
-{
- static char const *months[] =
- {"jan", "feb", "mar", "apr", "may", "jun", "jul",
- "aug", "sep", "oct", "nov", "dec", NULL};
-
- return aindex(months, str, 3);
-}
-
-static void
-parse_time(char const * str, int *hour, int *min, int *sec)
-{
- *hour = a2i(&str);
- if ((str = strchr(str, ':')) == NULL)
- *min = *sec = 0;
- else {
- ++str;
- *min = a2i(&str);
- *sec = ((str = strchr(str, ':')) == NULL) ? 0 : atoi(++str);
- }
-}
-
-
-static void
-parse_datesub(char const * str, int *day, int *mon, int *year)
-{
- int i;
-
- static char const nchrs[] = "0123456789 \t,/-.";
-
- if ((i = month(&str)) != -1) {
- *mon = i;
- if ((i = a2i(&str)) != 0)
- *day = i;
- } else if ((i = a2i(&str)) != 0) {
- *day = i;
- while (*str && strchr(nchrs + 10, *str) != NULL)
- ++str;
- if ((i = month(&str)) != -1)
- *mon = i;
- else if ((i = a2i(&str)) != 0)
- *mon = i - 1;
- } else
- return;
-
- while (*str && strchr(nchrs + 10, *str) != NULL)
- ++str;
- if (isdigit((unsigned char)*str)) {
- *year = atoi(str);
- if (*year > 1900)
- *year -= 1900;
- else if (*year < 32)
- *year += 100;
- }
-}
-
-
-/*-
- * Parse time must be flexible, it handles the following formats:
- * nnnnnnnnnnn UNIX timestamp (all numeric), 0 = now
- * 0xnnnnnnnn UNIX timestamp in hexadecimal
- * 0nnnnnnnnn UNIX timestamp in octal
- * 0 Given time
- * +nnnn[smhdwoy] Given time + nnnn hours, mins, days, weeks, months or years
- * -nnnn[smhdwoy] Given time - nnnn hours, mins, days, weeks, months or years
- * dd[ ./-]mmm[ ./-]yy Date }
- * hh:mm:ss Time } May be combined
- */
-
-time_t
-parse_date(time_t dt, char const * str)
-{
- char *p;
- int i;
- long val;
- struct tm *T;
-
- if (dt == 0)
- dt = time(NULL);
-
- while (*str && isspace((unsigned char)*str))
- ++str;
-
- if (numerics(str)) {
- dt = strtol(str, &p, 0);
- } else if (*str == '+' || *str == '-') {
- val = strtol(str, &p, 0);
- switch (*p) {
- case 'h':
- case 'H': /* hours */
- dt += (val * 3600L);
- break;
- case '\0':
- case 'm':
- case 'M': /* minutes */
- dt += (val * 60L);
- break;
- case 's':
- case 'S': /* seconds */
- dt += val;
- break;
- case 'd':
- case 'D': /* days */
- dt += (val * 86400L);
- break;
- case 'w':
- case 'W': /* weeks */
- dt += (val * 604800L);
- break;
- case 'o':
- case 'O': /* months */
- T = localtime(&dt);
- T->tm_mon += (int) val;
- i = T->tm_mday;
- goto fixday;
- case 'y':
- case 'Y': /* years */
- T = localtime(&dt);
- T->tm_year += (int) val;
- i = T->tm_mday;
- fixday:
- dt = mktime(T);
- T = localtime(&dt);
- if (T->tm_mday != i) {
- T->tm_mday = 1;
- dt = mktime(T);
- dt -= (time_t) 86400L;
- }
- default: /* unknown */
- break; /* leave untouched */
- }
- } else {
- char *q, tmp[64];
-
- /*
- * Skip past any weekday prefix
- */
- weekday(&str);
- strlcpy(tmp, str, sizeof(tmp));
- str = tmp;
- T = localtime(&dt);
-
- /*
- * See if we can break off any timezone
- */
- while ((q = strrchr(tmp, ' ')) != NULL) {
- if (strchr("(+-", q[1]) != NULL)
- *q = '\0';
- else {
- int j = 1;
-
- while (q[j] && isupper((unsigned char)q[j]))
- ++j;
- if (q[j] == '\0')
- *q = '\0';
- else
- break;
- }
- }
-
- /*
- * See if there is a time hh:mm[:ss]
- */
- if ((p = strchr(tmp, ':')) == NULL) {
-
- /*
- * No time string involved
- */
- T->tm_hour = T->tm_min = T->tm_sec = 0;
- parse_datesub(tmp, &T->tm_mday, &T->tm_mon, &T->tm_year);
- } else {
- char datestr[64], timestr[64];
-
- /*
- * Let's chip off the time string
- */
- if ((q = strpbrk(p, " \t")) != NULL) { /* Time first? */
- int l = q - str;
-
- strlcpy(timestr, str, l + 1);
- strlcpy(datestr, q + 1, sizeof(datestr));
- parse_time(timestr, &T->tm_hour, &T->tm_min, &T->tm_sec);
- parse_datesub(datestr, &T->tm_mday, &T->tm_mon, &T->tm_year);
- } else if ((q = strrchr(tmp, ' ')) != NULL) { /* Time last */
- int l = q - tmp;
-
- strlcpy(timestr, q + 1, sizeof(timestr));
- strlcpy(datestr, tmp, l + 1);
- } else /* Bail out */
- return dt;
- parse_time(timestr, &T->tm_hour, &T->tm_min, &T->tm_sec);
- parse_datesub(datestr, &T->tm_mday, &T->tm_mon, &T->tm_year);
- }
- dt = mktime(T);
- }
- return dt;
-}
diff --git a/pw/psdate.h b/pw/psdate.h
deleted file mode 100644
index a1e99d4..0000000
--- a/pw/psdate.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _PSDATE_H_
-#define _PSDATE_H_
-
-#include <time.h>
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-time_t parse_date(time_t dt, char const * str);
-void print_date(char *buf, time_t t, int dotime);
-__END_DECLS
-
-#endif /* !_PSDATE_H_ */
diff --git a/pw/pw.8 b/pw/pw.8
deleted file mode 100644
index 4287055..0000000
--- a/pw/pw.8
+++ /dev/null
@@ -1,1001 +0,0 @@
-.\" Copyright (C) 1996
-.\" David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd March 30, 2007
-.Dt PW 8
-.Os
-.Sh NAME
-.Nm pw
-.Nd create, remove, modify & display system users and groups
-.Sh SYNOPSIS
-.Nm
-.Op Fl V Ar etcdir
-.Ar useradd
-.Op name|uid
-.Op Fl C Ar config
-.Op Fl q
-.Op Fl n Ar name
-.Op Fl u Ar uid
-.Op Fl c Ar comment
-.Op Fl d Ar dir
-.Op Fl e Ar date
-.Op Fl p Ar date
-.Op Fl g Ar group
-.Op Fl G Ar grouplist
-.Op Fl m
-.Op Fl M Ar mode
-.Op Fl k Ar dir
-.Op Fl w Ar method
-.Op Fl s Ar shell
-.Op Fl o
-.Op Fl L Ar class
-.Op Fl h Ar fd | Fl H Ar fd
-.Op Fl N
-.Op Fl P
-.Op Fl Y
-.Nm
-.Op Fl V Ar etcdir
-.Ar useradd
-.Op name|uid
-.Fl D
-.Op Fl C Ar config
-.Op Fl q
-.Op Fl b Ar dir
-.Op Fl e Ar days
-.Op Fl p Ar days
-.Op Fl g Ar group
-.Op Fl G Ar grouplist
-.Op Fl k Ar dir
-.Op Fl M Ar mode
-.Op Fl u Ar min , Ns Ar max
-.Op Fl i Ar min , Ns Ar max
-.Op Fl w Ar method
-.Op Fl s Ar shell
-.Op Fl y Ar path
-.Nm
-.Op Fl V Ar etcdir
-.Ar userdel
-.Op name|uid
-.Op Fl n Ar name
-.Op Fl u Ar uid
-.Op Fl r
-.Op Fl Y
-.Nm
-.Op Fl V Ar etcdir
-.Ar usermod
-.Op name|uid
-.Op Fl C Ar config
-.Op Fl q
-.Op Fl n Ar name
-.Op Fl u Ar uid
-.Op Fl c Ar comment
-.Op Fl d Ar dir
-.Op Fl e Ar date
-.Op Fl p Ar date
-.Op Fl g Ar group
-.Op Fl G Ar grouplist
-.Op Fl l Ar name
-.Op Fl m
-.Op Fl M Ar mode
-.Op Fl k Ar dir
-.Op Fl w Ar method
-.Op Fl s Ar shell
-.Op Fl L Ar class
-.Op Fl h Ar fd | Fl H Ar fd
-.Op Fl N
-.Op Fl P
-.Op Fl Y
-.Nm
-.Op Fl V Ar etcdir
-.Ar usershow
-.Op name|uid
-.Op Fl n Ar name
-.Op Fl u Ar uid
-.Op Fl F
-.Op Fl P
-.Op Fl 7
-.Op Fl a
-.Nm
-.Op Fl V Ar etcdir
-.Ar usernext
-.Op Fl C Ar config
-.Op Fl q
-.Nm
-.Op Fl V Ar etcdir
-.Ar groupadd
-.Op group|gid
-.Op Fl C Ar config
-.Op Fl q
-.Op Fl n Ar group
-.Op Fl g Ar gid
-.Op Fl M Ar members
-.Op Fl o
-.Op Fl h Ar fd | Fl H Ar fd
-.Op Fl N
-.Op Fl P
-.Op Fl Y
-.Nm
-.Op Fl V Ar etcdir
-.Ar groupdel
-.Op group|gid
-.Op Fl n Ar name
-.Op Fl g Ar gid
-.Op Fl Y
-.Nm
-.Op Fl V Ar etcdir
-.Ar groupmod
-.Op group|gid
-.Op Fl C Ar config
-.Op Fl q
-.Op Fl n Ar name
-.Op Fl g Ar gid
-.Op Fl l Ar name
-.Op Fl M Ar members
-.Op Fl m Ar newmembers
-.Op Fl d Ar oldmembers
-.Op Fl h Ar fd | Fl H Ar fd
-.Op Fl N
-.Op Fl P
-.Op Fl Y
-.Nm
-.Op Fl V Ar etcdir
-.Ar groupshow
-.Op group|gid
-.Op Fl n Ar name
-.Op Fl g Ar gid
-.Op Fl F
-.Op Fl P
-.Op Fl a
-.Nm
-.Op Fl V Ar etcdir
-.Ar groupnext
-.Op Fl C Ar config
-.Op Fl q
-.Nm
-.Op Fl V Ar etcdir
-.Ar lock
-.Op name|uid
-.Op Fl C Ar config
-.Op Fl q
-.Nm
-.Op Fl V Ar etcdir
-.Ar unlock
-.Op name|uid
-.Op Fl C Ar config
-.Op Fl q
-.Sh DESCRIPTION
-The
-.Nm
-utility is a command-line based editor for the system
-.Ar user
-and
-.Ar group
-files, allowing the superuser an easy to use and standardized way of adding,
-modifying and removing users and groups.
-Note that
-.Nm
-only operates on the local user and group files.
-.Tn NIS
-users and groups must be
-maintained on the
-.Tn NIS
-server.
-The
-.Nm
-utility handles updating the
-.Pa passwd ,
-.Pa master.passwd ,
-.Pa group
-and the secure and insecure
-password database files, and must be run as root.
-.Pp
-The first one or two keywords provided to
-.Nm
-on the command line provide the context for the remainder of the arguments.
-The keywords
-.Ar user
-and
-.Ar group
-may be combined with
-.Ar add ,
-.Ar del ,
-.Ar mod ,
-.Ar show ,
-or
-.Ar next
-in any order.
-(For example,
-.Ar showuser ,
-.Ar usershow ,
-.Ar show user ,
-and
-.Ar user show
-all mean the same thing.)
-This flexibility is useful for interactive scripts calling
-.Nm
-for user and group database manipulation.
-Following these keywords, you may optionally specify the user or group name or numeric
-id as an alternative to using the
-.Fl n Ar name ,
-.Fl u Ar uid ,
-.Fl g Ar gid
-options.
-.Pp
-The following flags are common to most or all modes of operation:
-.Pp
-.Bl -tag -width "-G grouplist"
-.It Fl V Ar etcdir
-This flag sets an alternate location for the password, group and configuration files,
-and may be used to maintain a user/group database in an alternate location.
-If this switch is specified, the system
-.Pa /etc/pw.conf
-will not be sourced for default configuration data, but the file pw.conf in the
-specified directory will be used instead (or none, if it does not exist).
-The
-.Fl C
-flag may be used to override this behaviour.
-As an exception to the general rule where options must follow the operation
-type, the
-.Fl V
-flag may be used on the command line before the operation keyword.
-.It Fl C Ar config
-By default,
-.Nm
-reads the file
-.Pa /etc/pw.conf
-to obtain policy information on how new user accounts and groups are to be created.
-The
-.Fl C
-option specifies a different configuration file.
-While most of the contents of the configuration file may be overridden via
-command-line options, it may be more convenient to keep standard information in a
-configuration file.
-.It Fl q
-Use of this option causes
-.Nm
-to suppress error messages, which may be useful in interactive environments where it
-is preferable to interpret status codes returned by
-.Nm
-rather than messing up a carefully formatted display.
-.It Fl N
-This option is available in
-.Ar add
-and
-.Ar modify
-operations, and tells
-.Nm
-to output the result of the operation without updating the user or group
-databases.
-You may use the
-.Fl P
-option to switch between standard passwd and readable formats.
-.It Fl Y
-Using this option with any of the update modes causes
-.Nm
-to run
-.Xr make 1
-after changing to the directory
-.Pa /var/yp .
-This is intended to allow automatic updating of
-.Tn NIS
-database files.
-If separate passwd and group files are being used by
-.Tn NIS ,
-then use the
-.Fl y Ar path
-option to specify the location of the
-.Tn NIS
-passwd database so that
-.Nm
-will concurrently update it with the system password
-databases.
-.El
-.Sh USER OPTIONS
-The following options apply to the
-.Ar useradd
-and
-.Ar usermod
-commands:
-.Pp
-.Bl -tag -width "-G grouplist"
-.It Fl n Ar name
-Specify the user/account name.
-.It Fl u Ar uid
-Specify the user/account numeric id.
-.Pp
-Usually, you only need to provide one or the other of these options, as the account
-name will imply the uid, or vice versa.
-However, there are times when you need to provide both.
-For example, when changing the uid of an existing user with
-.Ar usermod ,
-or overriding the default uid when creating a new account.
-If you wish
-.Nm
-to automatically allocate the uid to a new user with
-.Ar useradd ,
-then you should
-.Em not
-use the
-.Fl u
-option.
-You may also provide either the account or userid immediately after the
-.Ar useradd ,
-.Ar userdel ,
-.Ar usermod
-or
-.Ar usershow
-keywords on the command line without using the
-.Fl n
-or
-.Fl u
-options.
-.El
-.Pp
-.Bl -tag -width "-G grouplist"
-.It Fl c Ar comment
-This field sets the contents of the passwd GECOS field, which normally contains up
-to four comma-separated fields containing the user's full name, office or location,
-and work and home phone numbers.
-These sub-fields are used by convention only, however, and are optional.
-If this field is to contain spaces, you need to quote the comment itself with double
-quotes
-.Ql \&" .
-Avoid using commas in this field as these are used as sub-field separators, and the
-colon
-.Ql \&:
-character also cannot be used as this is the field separator for the passwd
-file itself.
-.It Fl d Ar dir
-This option sets the account's home directory.
-Normally, you will only use this if the home directory is to be different from the
-default determined from
-.Pa /etc/pw.conf
-- normally
-.Pa /home
-with the account name as a subdirectory.
-.It Fl e Ar date
-Set the account's expiration date.
-Format of the date is either a UNIX time in decimal, or a date in
-.Ql dd-mmm-yy[yy]
-format, where dd is the day, mmm is the month, either in numeric or alphabetic format
-('Jan', 'Feb', etc) and year is either a two or four digit year.
-This option also accepts a relative date in the form
-.Ql \&+n[mhdwoy]
-where
-.Ql \&n
-is a decimal, octal (leading 0) or hexadecimal (leading 0x) digit followed by the
-number of Minutes, Hours, Days, Weeks, Months or Years from the current date at
-which the expiration date is to be set.
-.It Fl p Ar date
-Set the account's password expiration date.
-This field is similar to the account expiration date option, except that it
-applies to forced password changes.
-This is set in the same manner as the
-.Fl e
-option.
-.It Fl g Ar group
-Set the account's primary group to the given group.
-.Ar group
-may be defined by either its name or group number.
-.It Fl G Ar grouplist
-Set additional group memberships for an account.
-.Ar grouplist
-is a comma, space or tab-separated list of group names or group numbers.
-The user's name is added to the group lists in
-.Pa /etc/group ,
-and
-removed from any groups not specified in
-.Ar grouplist .
-Note: a user should not be added to their primary group with
-.Ar grouplist .
-Also, group membership changes do not take effect for current user login
-sessions, requiring the user to reconnect to be affected by the changes.
-.It Fl L Ar class
-This option sets the login class for the user being created.
-See
-.Xr login.conf 5
-and
-.Xr passwd 5
-for more information on user login classes.
-.It Fl m
-This option instructs
-.Nm
-to attempt to create the user's home directory.
-While primarily useful when adding a new account with
-.Ar useradd ,
-this may also be of use when moving an existing user's home directory elsewhere on
-the file system.
-The new home directory is populated with the contents of the
-.Ar skeleton
-directory, which typically contains a set of shell configuration files that the
-user may personalize to taste.
-Files in this directory are usually named
-.Pa dot . Ns Aq Ar config
-where the
-.Pa dot
-prefix will be stripped.
-When
-.Fl m
-is used on an account with
-.Ar usermod ,
-existing configuration files in the user's home directory are
-.Em not
-overwritten from the skeleton files.
-.Pp
-When a user's home directory is created, it will by default be a subdirectory of the
-.Ar basehome
-directory as specified by the
-.Fl b
-option (see below), bearing the name of the new account.
-This can be overridden by the
-.Fl d
-option on the command line, if desired.
-.It Fl M Ar mode
-Create the user's home directory with the specified
-.Ar mode ,
-modified by the current
-.Xr umask 2 .
-If omitted, it is derived from the parent process'
-.Xr umask 2 .
-This option is only useful in combination with the
-.Fl m
-flag.
-.It Fl k Ar dir
-Set the
-.Ar skeleton
-directory, from which basic startup and configuration files are copied when
-the user's home directory is created.
-This option only has meaning when used with the
-.Fl d
-or
-.Fl m
-flags.
-.It Fl s Ar shell
-Set or changes the user's login shell to
-.Ar shell .
-If the path to the shell program is omitted,
-.Nm
-searches the
-.Ar shellpath
-specified in
-.Pa /etc/pw.conf
-and fills it in as appropriate.
-Note that unless you have a specific reason to do so, you should avoid
-specifying the path - this will allow
-.Nm
-to validate that the program exists and is executable.
-Specifying a full path (or supplying a blank "" shell) avoids this check
-and allows for such entries as
-.Pa /nonexistent
-that should be set for accounts not intended for interactive login.
-.It Fl h Ar fd
-This option provides a special interface by which interactive scripts can
-set an account password using
-.Nm .
-Because the command line and environment are fundamentally insecure mechanisms
-by which programs can accept information,
-.Nm
-will only allow setting of account and group passwords via a file descriptor
-(usually a pipe between an interactive script and the program).
-.Ar sh ,
-.Ar bash ,
-.Ar ksh
-and
-.Ar perl
-all possess mechanisms by which this can be done.
-Alternatively,
-.Nm
-will prompt for the user's password if
-.Fl h Ar 0
-is given, nominating
-.Em stdin
-as the file descriptor on which to read the password.
-Note that this password will be read only once and is intended
-for use by a script rather than for interactive use.
-If you wish to have new password confirmation along the lines of
-.Xr passwd 1 ,
-this must be implemented as part of an interactive script that calls
-.Nm .
-.Pp
-If a value of
-.Ql \&-
-is given as the argument
-.Ar fd ,
-then the password will be set to
-.Ql \&* ,
-rendering the account inaccessible via password-based login.
-.It Fl H Ar fd
-Read an encrypted password string from the specified file descriptor.
-This is like
-.Fl h ,
-but the password should be supplied already encrypted in a form
-suitable for writing directly to the password database.
-.El
-.Pp
-It is possible to use
-.Ar useradd
-to create a new account that duplicates an existing user id.
-While this is normally considered an error and will be rejected, the
-.Fl o
-option overrides the check for duplicates and allows the duplication of
-the user id.
-This may be useful if you allow the same user to login under
-different contexts (different group allocations, different home
-directory, different shell) while providing basically the same
-permissions for access to the user's files in each account.
-.Pp
-The
-.Ar useradd
-command also has the ability to set new user and group defaults by using the
-.Fl D
-option.
-Instead of adding a new user,
-.Nm
-writes a new set of defaults to its configuration file,
-.Pa /etc/pw.conf .
-When using the
-.Fl D
-option, you must not use either
-.Fl n Ar name
-or
-.Fl u Ar uid
-or an error will result.
-Use of
-.Fl D
-changes the meaning of several command line switches in the
-.Ar useradd
-command.
-These are:
-.Bl -tag -width "-G grouplist"
-.It Fl D
-Set default values in
-.Pa /etc/pw.conf
-configuration file, or a different named configuration file if the
-.Fl C Ar config
-option is used.
-.It Fl b Ar dir
-Set the root directory in which user home directories are created.
-The default value for this is
-.Pa /home ,
-but it may be set elsewhere as desired.
-.It Fl e Ar days
-Set the default account expiration period in days.
-Unlike use without
-.Fl D ,
-the argument must be numeric, which specifies the number of days after creation when
-the account is to expire.
-A value of 0 suppresses automatic calculation of the expiry date.
-.It Fl p Ar days
-Set the default password expiration period in days.
-.It Fl g Ar group
-Set the default group for new users.
-If a blank group is specified using
-.Fl g Ar \&"" ,
-then new users will be allocated their own private primary group
-with the same name as their login name.
-If a group is supplied, either its name or uid may be given as an argument.
-.It Fl G Ar grouplist
-Set the default groups in which new users are granted membership.
-This is a separate set of groups from the primary group, and you should avoid
-nominating the same group as both primary and extra groups.
-In other words, these extra groups determine membership in groups
-.Em other than
-the primary group.
-.Ar grouplist
-is a comma-separated list of group names or ids, and are always
-stored in
-.Pa /etc/pw.conf
-by their symbolic names.
-.It Fl L Ar class
-This option sets the default login class for new users.
-.It Fl k Ar dir
-Set the default
-.Em skeleton
-directory, from which prototype shell and other initialization files are copied when
-.Nm
-creates a user's home directory.
-See description of
-.Fl k
-for naming conventions of these files.
-.It Xo
-.Fl u Ar min , Ns Ar max ,
-.Fl i Ar min , Ns Ar max
-.Xc
-These options set the minimum and maximum user and group ids allocated for new accounts
-and groups created by
-.Nm .
-The default values for each is 1000 minimum and 32000 maximum.
-.Ar min
-and
-.Ar max
-are both numbers, where max must be greater than min, and both must be between 0
-and 32767.
-In general, user and group ids less than 100 are reserved for use by the system,
-and numbers greater than 32000 may also be reserved for special purposes (used by
-some system daemons).
-.It Fl w Ar method
-The
-.Fl w
-option sets the default method used to set passwords for newly created user accounts.
-.Ar method
-is one of:
-.Pp
-.Bl -tag -width random -offset indent -compact
-.It no
-disable login on newly created accounts
-.It yes
-force the password to be the account name
-.It none
-force a blank password
-.It random
-generate a random password
-.El
-.Pp
-The
-.Ql \&random
-or
-.Ql \&no
-methods are the most secure; in the former case,
-.Nm
-generates a password and prints it to stdout, which is suitable where you issue
-users with passwords to access their accounts rather than having the user nominate
-their own (possibly poorly chosen) password.
-The
-.Ql \&no
-method requires that the superuser use
-.Xr passwd 1
-to render the account accessible with a password.
-.It Fl y Ar path
-This sets the pathname of the database used by
-.Tn NIS
-if you are not sharing
-the information from
-.Pa /etc/master.passwd
-directly with
-.Tn NIS .
-You should only set this option for
-.Tn NIS
-servers.
-.El
-.Pp
-The
-.Ar userdel
-command has only three valid options.
-The
-.Fl n Ar name
-and
-.Fl u Ar uid
-options have already been covered above.
-The additional option is:
-.Bl -tag -width "-G grouplist"
-.It Fl r
-This tells
-.Nm
-to remove the user's home directory and all of its contents.
-The
-.Nm
-utility errs on the side of caution when removing files from the system.
-Firstly, it will not do so if the uid of the account being removed is also used by
-another account on the system, and the 'home' directory in the password file is
-a valid path that commences with the character
-.Ql \&/ .
-Secondly, it will only remove files and directories that are actually owned by
-the user, or symbolic links owned by anyone under the user's home directory.
-Finally, after deleting all contents owned by the user only empty directories
-will be removed.
-If any additional cleanup work is required, this is left to the administrator.
-.El
-.Pp
-Mail spool files and crontabs are always removed when an account is deleted as these
-are unconditionally attached to the user name.
-Jobs queued for processing by
-.Ar at
-are also removed if the user's uid is unique and not also used by another account on the
-system.
-.Pp
-The
-.Ar usershow
-command allows viewing of an account in one of two formats.
-By default, the format is identical to the format used in
-.Pa /etc/master.passwd
-with the password field replaced with a
-.Ql \&* .
-If the
-.Fl P
-option is used, then
-.Nm
-outputs the account details in a more human readable form.
-If the
-.Fl 7
-option is used, the account details are shown in v7 format.
-The
-.Fl a
-option lists all users currently on file.
-Using
-.Fl F
-forces
-.Nm
-to print the details of an account even if it does not exist.
-.Pp
-The command
-.Ar usernext
-returns the next available user and group ids separated by a colon.
-This is normally of interest only to interactive scripts or front-ends
-that use
-.Nm .
-.Sh GROUP OPTIONS
-The
-.Fl C
-and
-.Fl q
-options (explained at the start of the previous section) are available
-with the group manipulation commands.
-Other common options to all group-related commands are:
-.Bl -tag -width "-m newmembers"
-.It Fl n Ar name
-Specify the group name.
-.It Fl g Ar gid
-Specify the group numeric id.
-.Pp
-As with the account name and id fields, you will usually only need
-to supply one of these, as the group name implies the uid and vice
-versa.
-You will only need to use both when setting a specific group id
-against a new group or when changing the uid of an existing group.
-.It Fl M Ar memberlist
-This option provides an alternative way to add existing users to a
-new group (in groupadd) or replace an existing membership list (in
-groupmod).
-.Ar memberlist
-is a comma separated list of valid and existing user names or uids.
-.It Fl m Ar newmembers
-Similar to
-.Fl M ,
-this option allows the
-.Em addition
-of existing users to a group without replacing the existing list of
-members.
-Login names or user ids may be used, and duplicate users are
-silently eliminated.
-.It Fl d Ar oldmembers
-Similar to
-.Fl M ,
-this option allows the
-.Em deletion
-of existing users from a group without replacing the existing list of
-members.
-Login names or user ids may be used, and duplicate users are
-silently eliminated.
-.El
-.Pp
-.Ar groupadd
-also has a
-.Fl o
-option that allows allocation of an existing group id to a new group.
-The default action is to reject an attempt to add a group, and this option overrides
-the check for duplicate group ids.
-There is rarely any need to duplicate a group id.
-.Pp
-The
-.Ar groupmod
-command adds one additional option:
-.Pp
-.Bl -tag -width "-m newmembers"
-.It Fl l Ar name
-This option allows changing of an existing group name to
-.Ql \&name .
-The new name must not already exist, and any attempt to duplicate an existing group
-name will be rejected.
-.El
-.Pp
-Options for
-.Ar groupshow
-are the same as for
-.Ar usershow ,
-with the
-.Fl g Ar gid
-replacing
-.Fl u Ar uid
-to specify the group id.
-The
-.Fl 7
-option does not apply to the
-.Ar groupshow
-command.
-.Pp
-The command
-.Ar groupnext
-returns the next available group id on standard output.
-.Sh USER LOCKING
-The
-.Nm
-utility
-supports a simple password locking mechanism for users; it works by
-prepending the string
-.Ql *LOCKED*
-to the beginning of the password field in
-.Pa master.passwd
-to prevent successful authentication.
-.Pp
-The
-.Ar lock
-and
-.Ar unlock
-commands take a user name or uid of the account to lock or unlock,
-respectively.
-The
-.Fl V ,
-.Fl C ,
-and
-.Fl q
-options as described above are accepted by these commands.
-.Sh NOTES
-For a summary of options available with each command, you can use
-.Dl pw [command] help
-For example,
-.Dl pw useradd help
-lists all available options for the useradd operation.
-.Pp
-The
-.Nm
-utility allows 8-bit characters in the passwd GECOS field (user's full name,
-office, work and home phone number subfields), but disallows them in
-user login and group names.
-Use 8-bit characters with caution, as connection to the Internet will
-require that your mail transport program supports 8BITMIME, and will
-convert headers containing 8-bit characters to 7-bit quoted-printable
-format.
-.Xr sendmail 8
-does support this.
-Use of 8-bit characters in the GECOS field should be used in
-conjunction with the user's default locale and character set
-and should not be implemented without their use.
-Using 8-bit characters may also affect other
-programs that transmit the contents of the GECOS field over the
-Internet, such as
-.Xr fingerd 8 ,
-and a small number of TCP/IP clients, such as IRC, where full names
-specified in the passwd file may be used by default.
-.Pp
-The
-.Nm
-utility writes a log to the
-.Pa /var/log/userlog
-file when actions such as user or group additions or deletions occur.
-The location of this logfile can be changed in
-.Xr pw.conf 5 .
-.Sh FILES
-.Bl -tag -width /etc/master.passwd.new -compact
-.It Pa /etc/master.passwd
-The user database
-.It Pa /etc/passwd
-A Version 7 format password file
-.It Pa /etc/login.conf
-The user capabilities database
-.It Pa /etc/group
-The group database
-.It Pa /etc/master.passwd.new
-Temporary copy of the master password file
-.It Pa /etc/passwd.new
-Temporary copy of the Version 7 password file
-.It Pa /etc/group.new
-Temporary copy of the group file
-.It Pa /etc/pw.conf
-Pw default options file
-.It Pa /var/log/userlog
-User/group modification logfile
-.El
-.Sh EXIT STATUS
-The
-.Nm
-utility returns EXIT_SUCCESS on successful operation, otherwise
-.Nm
-returns one of the
-following exit codes defined by
-.Xr sysexits 3
-as follows:
-.Bl -tag -width xxxx
-.It EX_USAGE
-.Bl -bullet -compact
-.It
-Command line syntax errors (invalid keyword, unknown option).
-.El
-.It EX_NOPERM
-.Bl -bullet -compact
-.It
-Attempting to run one of the update modes as non-root.
-.El
-.It EX_OSERR
-.Bl -bullet -compact
-.It
-Memory allocation error.
-.It
-Read error from password file descriptor.
-.El
-.It EX_DATAERR
-.Bl -bullet -compact
-.It
-Bad or invalid data provided or missing on the command line or
-via the password file descriptor.
-.It
-Attempted to remove, rename root account or change its uid.
-.El
-.It EX_OSFILE
-.Bl -bullet -compact
-.It
-Skeleton directory is invalid or does not exist.
-.It
-Base home directory is invalid or does not exist.
-.It
-Invalid or non-existent shell specified.
-.El
-.It EX_NOUSER
-.Bl -bullet -compact
-.It
-User, user id, group or group id specified does not exist.
-.It
-User or group recorded, added, or modified unexpectedly disappeared.
-.El
-.It EX_SOFTWARE
-.Bl -bullet -compact
-.It
-No more group or user ids available within specified range.
-.El
-.It EX_IOERR
-.Bl -bullet -compact
-.It
-Unable to rewrite configuration file.
-.It
-Error updating group or user database files.
-.It
-Update error for passwd or group database files.
-.El
-.It EX_CONFIG
-.Bl -bullet -compact
-.It
-No base home directory configured.
-.El
-.El
-.Sh SEE ALSO
-.Xr chpass 1 ,
-.Xr passwd 1 ,
-.Xr umask 2 ,
-.Xr group 5 ,
-.Xr login.conf 5 ,
-.Xr passwd 5 ,
-.Xr pw.conf 5 ,
-.Xr pwd_mkdb 8 ,
-.Xr vipw 8
-.Sh HISTORY
-The
-.Nm
-utility was written to mimic many of the options used in the SYSV
-.Em shadow
-support suite, but is modified for passwd and group fields specific to
-the
-.Bx 4.4
-operating system, and combines all of the major elements
-into a single command.
diff --git a/pw/pw.c b/pw/pw.c
deleted file mode 100644
index e9d9363..0000000
--- a/pw/pw.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <err.h>
-#include <fcntl.h>
-#include <locale.h>
-#include <paths.h>
-#include <sys/wait.h>
-#include "pw.h"
-
-#if !defined(_PATH_YP)
-#define _PATH_YP "/var/yp/"
-#endif
-const char *Modes[] = {
- "add", "del", "mod", "show", "next",
- NULL};
-const char *Which[] = {"user", "group", NULL};
-static const char *Combo1[] = {
- "useradd", "userdel", "usermod", "usershow", "usernext",
- "lock", "unlock",
- "groupadd", "groupdel", "groupmod", "groupshow", "groupnext",
- NULL};
-static const char *Combo2[] = {
- "adduser", "deluser", "moduser", "showuser", "nextuser",
- "lock", "unlock",
- "addgroup", "delgroup", "modgroup", "showgroup", "nextgroup",
- NULL};
-
-struct pwf PWF =
-{
- 0,
- setpwent,
- endpwent,
- getpwent,
- getpwuid,
- getpwnam,
- pwdb,
- setgrent,
- endgrent,
- getgrent,
- getgrgid,
- getgrnam,
- grdb
-
-};
-struct pwf VPWF =
-{
- 1,
- vsetpwent,
- vendpwent,
- vgetpwent,
- vgetpwuid,
- vgetpwnam,
- vpwdb,
- vsetgrent,
- vendgrent,
- vgetgrent,
- vgetgrgid,
- vgetgrnam,
- vgrdb
-};
-
-static struct cargs arglist;
-
-static int getindex(const char *words[], const char *word);
-static void cmdhelp(int mode, int which);
-
-
-int
-main(int argc, char *argv[])
-{
- int ch;
- int mode = -1;
- int which = -1;
- char *config = NULL;
- struct userconf *cnf;
-
- static const char *opts[W_NUM][M_NUM] =
- {
- { /* user */
- "V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y",
- "V:C:qn:u:rY",
- "V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY",
- "V:C:qn:u:FPa7",
- "V:C:q",
- "V:C:q",
- "V:C:q"
- },
- { /* grp */
- "V:C:qn:g:h:H:M:opNPY",
- "V:C:qn:g:Y",
- "V:C:qn:d:g:l:h:H:FM:m:NPY",
- "V:C:qn:g:FPa",
- "V:C:q"
- }
- };
-
- static int (*funcs[W_NUM]) (struct userconf * _cnf, int _mode, struct cargs * _args) =
- { /* Request handlers */
- pw_user,
- pw_group
- };
-
- LIST_INIT(&arglist);
-
- (void)setlocale(LC_ALL, "");
-
- /*
- * Break off the first couple of words to determine what exactly
- * we're being asked to do
- */
- while (argc > 1) {
- int tmp;
-
- if (*argv[1] == '-') {
- /*
- * Special case, allow pw -V<dir> <operation> [args] for scripts etc.
- */
- if (argv[1][1] == 'V') {
- optarg = &argv[1][2];
- if (*optarg == '\0') {
- optarg = argv[2];
- ++argv;
- --argc;
- }
- addarg(&arglist, 'V', optarg);
- } else
- break;
- }
- else if (mode == -1 && (tmp = getindex(Modes, argv[1])) != -1)
- mode = tmp;
- else if (which == -1 && (tmp = getindex(Which, argv[1])) != -1)
- which = tmp;
- else if ((mode == -1 && which == -1) &&
- ((tmp = getindex(Combo1, argv[1])) != -1 ||
- (tmp = getindex(Combo2, argv[1])) != -1)) {
- which = tmp / M_NUM;
- mode = tmp % M_NUM;
- } else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL)
- cmdhelp(mode, which);
- else if (which != -1 && mode != -1)
- addarg(&arglist, 'n', argv[1]);
- else
- errx(EX_USAGE, "unknown keyword `%s'", argv[1]);
- ++argv;
- --argc;
- }
-
- /*
- * Bail out unless the user is specific!
- */
- if (mode == -1 || which == -1)
- cmdhelp(mode, which);
-
- /*
- * We know which mode we're in and what we're about to do, so now
- * let's dispatch the remaining command line args in a genric way.
- */
- optarg = NULL;
-
- while ((ch = getopt(argc, argv, opts[which][mode])) != -1) {
- if (ch == '?')
- errx(EX_USAGE, "unknown switch");
- else
- addarg(&arglist, ch, optarg);
- optarg = NULL;
- }
-
- /*
- * Must be root to attempt an update
- */
- if (geteuid() != 0 && mode != M_PRINT && mode != M_NEXT && getarg(&arglist, 'N')==NULL)
- errx(EX_NOPERM, "you must be root to run this program");
-
- /*
- * We should immediately look for the -q 'quiet' switch so that we
- * don't bother with extraneous errors
- */
- if (getarg(&arglist, 'q') != NULL)
- freopen(_PATH_DEVNULL, "w", stderr);
-
- /*
- * Set our base working path if not overridden
- */
-
- config = getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL;
-
- if (getarg(&arglist, 'V') != NULL) {
- char * etcpath = getarg(&arglist, 'V')->val;
- if (*etcpath) {
- if (config == NULL) { /* Only override config location if -C not specified */
- config = malloc(MAXPATHLEN);
- snprintf(config, MAXPATHLEN, "%s/pw.conf", etcpath);
- }
- memcpy(&PWF, &VPWF, sizeof PWF);
- setpwdir(etcpath);
- setgrdir(etcpath);
- }
- }
-
- /*
- * Now, let's do the common initialisation
- */
- cnf = read_userconfig(config);
-
- ch = funcs[which] (cnf, mode, &arglist);
-
- /*
- * If everything went ok, and we've been asked to update
- * the NIS maps, then do it now
- */
- if (ch == EXIT_SUCCESS && getarg(&arglist, 'Y') != NULL) {
- pid_t pid;
-
- fflush(NULL);
- if (chdir(_PATH_YP) == -1)
- warn("chdir(" _PATH_YP ")");
- else if ((pid = fork()) == -1)
- warn("fork()");
- else if (pid == 0) {
- /* Is make anywhere else? */
- execlp("/usr/bin/make", "make", (char *)NULL);
- _exit(1);
- } else {
- int i;
- waitpid(pid, &i, 0);
- if ((i = WEXITSTATUS(i)) != 0)
- errx(ch, "make exited with status %d", i);
- else
- pw_log(cnf, mode, which, "NIS maps updated");
- }
- }
- return ch;
-}
-
-
-static int
-getindex(const char *words[], const char *word)
-{
- int i = 0;
-
- while (words[i]) {
- if (strcmp(words[i], word) == 0)
- return i;
- i++;
- }
- return -1;
-}
-
-
-/*
- * This is probably an overkill for a cmdline help system, but it reflects
- * the complexity of the command line.
- */
-
-static void
-cmdhelp(int mode, int which)
-{
- if (which == -1)
- fprintf(stderr, "usage:\n pw [user|group|lock|unlock] [add|del|mod|show|next] [help|switches/values]\n");
- else if (mode == -1)
- fprintf(stderr, "usage:\n pw %s [add|del|mod|show|next] [help|switches/values]\n", Which[which]);
- else {
-
- /*
- * We need to give mode specific help
- */
- static const char *help[W_NUM][M_NUM] =
- {
- {
- "usage: pw useradd [name] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n"
- " Adding users:\n"
- "\t-n name login name\n"
- "\t-u uid user id\n"
- "\t-c comment user name/comment\n"
- "\t-d directory home directory\n"
- "\t-e date account expiry date\n"
- "\t-p date password expiry date\n"
- "\t-g grp initial group\n"
- "\t-G grp1,grp2 additional groups\n"
- "\t-m [ -k dir ] create and set up home\n"
- "\t-M mode home directory permissions\n"
- "\t-s shell name of login shell\n"
- "\t-o duplicate uid ok\n"
- "\t-L class user class\n"
- "\t-h fd read password on fd\n"
- "\t-H fd read encrypted password on fd\n"
- "\t-Y update NIS maps\n"
- "\t-N no update\n"
- " Setting defaults:\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-D set user defaults\n"
- "\t-b dir default home root dir\n"
- "\t-e period default expiry period\n"
- "\t-p period default password change period\n"
- "\t-g group default group\n"
- "\t-G grp1,grp2 additional groups\n"
- "\t-L class default user class\n"
- "\t-k dir default home skeleton\n"
- "\t-M mode home directory permissions\n"
- "\t-u min,max set min,max uids\n"
- "\t-i min,max set min,max gids\n"
- "\t-w method set default password method\n"
- "\t-s shell default shell\n"
- "\t-y path set NIS passwd file path\n",
- "usage: pw userdel [uid|name] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-n name login name\n"
- "\t-u uid user id\n"
- "\t-Y update NIS maps\n"
- "\t-r remove home & contents\n",
- "usage: pw usermod [uid|name] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n"
- "\t-F force add if no user\n"
- "\t-n name login name\n"
- "\t-u uid user id\n"
- "\t-c comment user name/comment\n"
- "\t-d directory home directory\n"
- "\t-e date account expiry date\n"
- "\t-p date password expiry date\n"
- "\t-g grp initial group\n"
- "\t-G grp1,grp2 additional groups\n"
- "\t-l name new login name\n"
- "\t-L class user class\n"
- "\t-m [ -k dir ] create and set up home\n"
- "\t-M mode home directory permissions\n"
- "\t-s shell name of login shell\n"
- "\t-w method set new password using method\n"
- "\t-h fd read password on fd\n"
- "\t-H fd read encrypted password on fd\n"
- "\t-Y update NIS maps\n"
- "\t-N no update\n",
- "usage: pw usershow [uid|name] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-n name login name\n"
- "\t-u uid user id\n"
- "\t-F force print\n"
- "\t-P prettier format\n"
- "\t-a print all users\n"
- "\t-7 print in v7 format\n",
- "usage: pw usernext [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n",
- "usage pw: lock [switches]\n"
- "\t-V etcdir alternate /etc locations\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n",
- "usage pw: unlock [switches]\n"
- "\t-V etcdir alternate /etc locations\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n"
- },
- {
- "usage: pw groupadd [group|gid] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n"
- "\t-n group group name\n"
- "\t-g gid group id\n"
- "\t-M usr1,usr2 add users as group members\n"
- "\t-o duplicate gid ok\n"
- "\t-Y update NIS maps\n"
- "\t-N no update\n",
- "usage: pw groupdel [group|gid] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-n name group name\n"
- "\t-g gid group id\n"
- "\t-Y update NIS maps\n",
- "usage: pw groupmod [group|gid] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n"
- "\t-F force add if not exists\n"
- "\t-n name group name\n"
- "\t-g gid group id\n"
- "\t-M usr1,usr2 replaces users as group members\n"
- "\t-m usr1,usr2 add users as group members\n"
- "\t-d usr1,usr2 delete users as group members\n"
- "\t-l name new group name\n"
- "\t-Y update NIS maps\n"
- "\t-N no update\n",
- "usage: pw groupshow [group|gid] [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-n name group name\n"
- "\t-g gid group id\n"
- "\t-F force print\n"
- "\t-P prettier format\n"
- "\t-a print all accounting groups\n",
- "usage: pw groupnext [switches]\n"
- "\t-V etcdir alternate /etc location\n"
- "\t-C config configuration file\n"
- "\t-q quiet operation\n"
- }
- };
-
- fprintf(stderr, "%s", help[which][mode]);
- }
- exit(EXIT_FAILURE);
-}
-
-struct carg *
-getarg(struct cargs * _args, int ch)
-{
- struct carg *c = LIST_FIRST(_args);
-
- while (c != NULL && c->ch != ch)
- c = LIST_NEXT(c, list);
- return c;
-}
-
-struct carg *
-addarg(struct cargs * _args, int ch, char *argstr)
-{
- struct carg *ca = malloc(sizeof(struct carg));
-
- if (ca == NULL)
- errx(EX_OSERR, "out of memory");
- ca->ch = ch;
- ca->val = argstr;
- LIST_INSERT_HEAD(_args, ca, list);
- return ca;
-}
diff --git a/pw/pw.conf.5 b/pw/pw.conf.5
deleted file mode 100644
index 3f023aa..0000000
--- a/pw/pw.conf.5
+++ /dev/null
@@ -1,318 +0,0 @@
-.\" Copyright (C) 1996
-.\" David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd March 30, 2007
-.Dt PW.CONF 5
-.Os
-.Sh NAME
-.Nm pw.conf
-.Nd format of the pw.conf configuration file
-.Sh DESCRIPTION
-The file
-.In /etc/pw.conf
-contains configuration data for the
-.Xr pw 8
-utility.
-The
-.Xr pw 8
-utility is used for maintenance of the system password and group
-files, allowing users and groups to be added, deleted and changed.
-This file may be modified via the
-.Xr pw 8
-command using the
-.Ar useradd
-command and the
-.Fl D
-option, or by editing it directly with a text editor.
-.Pp
-Each line in
-.Pa /etc/pw.conf
-is treated either a comment or as configuration data;
-blank lines and lines commencing with a
-.Ql \&#
-character are considered comments, and any remaining lines are
-examined for a leading keyword, followed by corresponding data.
-.Pp
-Keywords recognized by
-.Xr pw 8
-are:
-.Bl -tag -width password_days -offset indent -compact
-.It defaultpasswd
-affect passwords generated for new users
-.It reuseuids
-reuse gaps in uid sequences
-.It reusegids
-reuse gaps in gid sequences
-.It nispasswd
-path to the
-.Tn NIS
-passwd database
-.It skeleton
-where to obtain default home contents
-.It newmail
-mail to send to new users
-.It logfile
-log user/group modifications to this file
-.It home
-root directory for home directories
-.It homemode
-permissions for home directory
-.It shellpath
-paths in which to locate shell programs
-.It shells
-list of valid shells (without path)
-.It defaultshell
-default shell (without path)
-.It defaultgroup
-default group
-.It extragroups
-add new users to this groups
-.It defaultclass
-place new users in this login class
-.It minuid
-.It maxuid
-range of valid default user ids
-.It mingid
-.It maxgid
-range of valid default group ids
-.It expire_days
-days after which account expires
-.It password_days
-days after which password expires
-.El
-.Pp
-Valid values for
-.Ar defaultpasswd
-are:
-.Bl -tag -width password_days -offset indent -compact
-.It no
-disable login on newly created accounts
-.It yes
-force the password to be the account name
-.It none
-force a blank password
-.It random
-generate a random password
-.El
-.Pp
-The second and third options are insecure and should be avoided if
-possible on a publicly accessible system.
-The first option requires that the superuser run
-.Xr passwd 1
-to set a password before the account may be used.
-This may also be useful for creating administrative accounts.
-The final option causes
-.Xr pw 8
-to respond by printing a randomly generated password on stdout.
-This is the preferred and most secure option.
-The
-.Xr pw 8
-utility also provides a method of setting a specific password for the new
-user via a filehandle (command lines are not secure).
-.Pp
-Both
-.Ar reuseuids
-and
-.Ar reusegids
-determine the method by which new user and group id numbers are
-generated.
-A
-.Ql \&yes
-in this field will cause
-.Xr pw 8
-to search for the first unused user or group id within the allowed
-range, whereas a
-.Ql \&no
-will ensure that no other existing user or group id within the range
-is numerically lower than the new one generated, and therefore avoids
-reusing gaps in the user or group id sequence that are caused by
-previous user or group deletions.
-Note that if the default group is not specified using the
-.Ar defaultgroup
-keyword,
-.Xr pw 8
-will create a new group for the user and attempt to keep the new
-user's uid and gid the same.
-If the new user's uid is currently in use as a group id, then the next
-available group id is chosen instead.
-.Pp
-On
-.Tn NIS
-servers which maintain a separate passwd database to
-.Pa /etc/master.passwd ,
-this option allows the additional file to be concurrently updated
-as user records are added, modified or removed.
-If blank or set to 'no', no additional database is updated.
-An absolute pathname must be used.
-.Pp
-The
-.Ar skeleton
-keyword nominates a directory from which the contents of a user's
-new home directory is constructed.
-This is
-.Pa /usr/share/skel
-by default.
-The
-.Xr pw 8 Ns 's
-.Fl m
-option causes the user's home directory to be created and populated
-using the files contained in the
-.Ar skeleton
-directory.
-.Pp
-To send an initial email to new users, the
-.Ar newmail
-keyword may be used to specify a path name to a file containing
-the message body of the message to be sent.
-To avoid sending mail when accounts are created, leave this entry
-blank or specify
-.Ql \&no .
-.Pp
-The
-.Ar logfile
-option allows logging of password file modifications into the
-nominated log file.
-To avoid creating or adding to such a logfile, then leave this
-field blank or specify
-.Ql \&no .
-.Pp
-The
-.Ar home
-keyword is mandatory.
-This specifies the location of the directory in which all new user
-home directories are created.
-.Pp
-The
-.Ar homemode
-keyword is optional.
-It specifies the creation mask of the user's home directory and is modified by
-.Xr umask 2 .
-.Pp
-The
-.Ar shellpath
-keyword specifies a list of directories - separated by colons
-.Ql \&:
-- which contain the programs used by the login shells.
-.Pp
-The
-.Ar shells
-keyword specifies a list of programs available for use as login
-shells.
-This list is a comma-separated list of shell names which should
-not contain a path.
-These shells must exist in one of the directories nominated by
-.Ar shellpath .
-.Pp
-The
-.Ar defaultshell
-keyword nominates which shell program to use for new users when
-none is specified on the
-.Xr pw 8
-command line.
-.Pp
-The
-.Ar defaultgroup
-keyword defines the primary group (the group id number in the
-password file) used for new accounts.
-If left blank, or the word
-.Ql \&no
-is used, then each new user will have a corresponding group of
-their own created automatically.
-This is the recommended procedure for new users as it best secures each
-user's files against interference by other users of the system
-irrespective of the
-.Em umask
-normally used by the user.
-.Pp
-The
-.Ar extragroups
-keyword provides an automatic means of placing new users into groups within
-the
-.Pa /etc/groups
-file.
-This is useful where all users share some resources, and is preferable
-to placing users into the same primary group.
-The effect of this keyword can be overridden using the
-.Fl G
-option on the
-.Xr pw 8
-command line.
-.Pp
-The
-.Ar defaultclass
-field determines the login class (See
-.Xr login.conf 5 )
-that new users will be allocated unless overwritten by
-.Xr pw 8 .
-.Pp
-The
-.Ar minuid ,
-.Ar maxuid ,
-.Ar mingid ,
-.Ar maxgid
-keywords determine the allowed ranges of automatically allocated user
-and group id numbers.
-The default values for both user and group ids are 1000 and 32000 as
-minimum and maximum respectively.
-The user and group id's actually used when creating an account with
-.Xr pw 8
-may be overridden using the
-.Fl u
-and
-.Fl g
-command line options.
-.Pp
-The
-.Ar expire_days
-and
-.Ar password_days
-are used to automatically calculate the number of days from the date
-on which an account is created when the account will expire or the
-user will be forced to change the account's password.
-A value of
-.Ql \&0
-in either field will disable the corresponding (account or password)
-expiration date.
-.Sh LIMITS
-The maximum line length of
-.Pa /etc/pw.conf
-is 1024 characters.
-Longer lines will be skipped and treated
-as comments.
-.Sh FILES
-.Bl -tag -width /etc/master.passwd -compact
-.It Pa /etc/pw.conf
-.It Pa /etc/passwd
-.It Pa /etc/master.passwd
-.It Pa /etc/group
-.El
-.Sh SEE ALSO
-.Xr passwd 1 ,
-.Xr umask 2 ,
-.Xr group 5 ,
-.Xr login.conf 5 ,
-.Xr passwd 5 ,
-.Xr pw 8
diff --git a/pw/pw.h b/pw/pw.h
deleted file mode 100644
index 7568c22..0000000
--- a/pw/pw.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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.
- *
- * $FreeBSD$
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/queue.h>
-#include <sysexits.h>
-
-#include "psdate.h"
-#include "pwupd.h"
-
-enum _mode
-{
- M_ADD,
- M_DELETE,
- M_UPDATE,
- M_PRINT,
- M_NEXT,
- M_LOCK,
- M_UNLOCK,
- M_NUM
-};
-
-enum _which
-{
- W_USER,
- W_GROUP,
- W_NUM
-};
-
-struct carg
-{
- int ch;
- char *val;
- LIST_ENTRY(carg) list;
-};
-
-LIST_HEAD(cargs, carg);
-
-struct userconf
-{
- int default_password; /* Default password for new users? */
- int reuse_uids; /* Reuse uids? */
- int reuse_gids; /* Reuse gids? */
- char *nispasswd; /* Path to NIS version of the passwd file */
- char *dotdir; /* Where to obtain skeleton files */
- char *newmail; /* Mail to send to new accounts */
- char *logfile; /* Where to log changes */
- char *home; /* Where to create home directory */
- mode_t homemode; /* Home directory permissions */
- char *shelldir; /* Where shells are located */
- char **shells; /* List of shells */
- char *shell_default; /* Default shell */
- char *default_group; /* Default group number */
- char **groups; /* Default (additional) groups */
- char *default_class; /* Default user class */
- uid_t min_uid, max_uid; /* Allowed range of uids */
- gid_t min_gid, max_gid; /* Allowed range of gids */
- int expire_days; /* Days to expiry */
- int password_days; /* Days to password expiry */
- int numgroups; /* (internal) size of default_group array */
-};
-
-#define _PATH_PW_CONF "/etc/pw.conf"
-#define _UC_MAXLINE 1024
-#define _UC_MAXSHELLS 32
-
-struct userconf *read_userconfig(char const * file);
-int write_userconfig(char const * file);
-struct carg *addarg(struct cargs * _args, int ch, char *argstr);
-struct carg *getarg(struct cargs * _args, int ch);
-
-int pw_user(struct userconf * cnf, int mode, struct cargs * _args);
-int pw_group(struct userconf * cnf, int mode, struct cargs * _args);
-char *pw_checkname(u_char *name, int gecos);
-
-int addpwent(struct passwd * pwd);
-int delpwent(struct passwd * pwd);
-int chgpwent(char const * login, struct passwd * pwd);
-int fmtpwent(char *buf, struct passwd * pwd);
-
-int addnispwent(const char *path, struct passwd *pwd);
-int delnispwent(const char *path, const char *login);
-int chgnispwent(const char *path, const char *login, struct passwd *pwd);
-
-int addgrent(struct group * grp);
-int delgrent(struct group * grp);
-int chggrent(char const * login, struct group * grp);
-
-int boolean_val(char const * str, int dflt);
-char const *boolean_str(int val);
-char *newstr(char const * p);
-
-void pw_log(struct userconf * cnf, int mode, int which, char const * fmt,...) __printflike(4, 5);
-char *pw_pwcrypt(char *password);
-
-extern const char *Modes[];
-extern const char *Which[];
diff --git a/pw/pw_conf.c b/pw/pw_conf.c
deleted file mode 100644
index 51672b9..0000000
--- a/pw/pw_conf.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
-
-#include "pw.h"
-
-#define debugging 0
-
-enum {
- _UC_NONE,
- _UC_DEFAULTPWD,
- _UC_REUSEUID,
- _UC_REUSEGID,
- _UC_NISPASSWD,
- _UC_DOTDIR,
- _UC_NEWMAIL,
- _UC_LOGFILE,
- _UC_HOMEROOT,
- _UC_HOMEMODE,
- _UC_SHELLPATH,
- _UC_SHELLS,
- _UC_DEFAULTSHELL,
- _UC_DEFAULTGROUP,
- _UC_EXTRAGROUPS,
- _UC_DEFAULTCLASS,
- _UC_MINUID,
- _UC_MAXUID,
- _UC_MINGID,
- _UC_MAXGID,
- _UC_EXPIRE,
- _UC_PASSWORD,
- _UC_FIELDS
-};
-
-static char bourne_shell[] = "sh";
-
-static char *system_shells[_UC_MAXSHELLS] =
-{
- bourne_shell,
- "csh",
- "tcsh"
-};
-
-static char const *booltrue[] =
-{
- "yes", "true", "1", "on", NULL
-};
-static char const *boolfalse[] =
-{
- "no", "false", "0", "off", NULL
-};
-
-static struct userconf config =
-{
- 0, /* Default password for new users? (nologin) */
- 0, /* Reuse uids? */
- 0, /* Reuse gids? */
- NULL, /* NIS version of the passwd file */
- "/usr/share/skel", /* Where to obtain skeleton files */
- NULL, /* Mail to send to new accounts */
- "/var/log/userlog", /* Where to log changes */
- "/home", /* Where to create home directory */
- 0777, /* Home directory perms, modified by umask */
- "/bin", /* Where shells are located */
- system_shells, /* List of shells (first is default) */
- bourne_shell, /* Default shell */
- NULL, /* Default group name */
- NULL, /* Default (additional) groups */
- NULL, /* Default login class */
- 1000, 32000, /* Allowed range of uids */
- 1000, 32000, /* Allowed range of gids */
- 0, /* Days until account expires */
- 0, /* Days until password expires */
- 0 /* size of default_group array */
-};
-
-static char const *comments[_UC_FIELDS] =
-{
- "#\n# pw.conf - user/group configuration defaults\n#\n",
- "\n# Password for new users? no=nologin yes=loginid none=blank random=random\n",
- "\n# Reuse gaps in uid sequence? (yes or no)\n",
- "\n# Reuse gaps in gid sequence? (yes or no)\n",
- "\n# Path to the NIS passwd file (blank or 'no' for none)\n",
- "\n# Obtain default dotfiles from this directory\n",
- "\n# Mail this file to new user (/etc/newuser.msg or no)\n",
- "\n# Log add/change/remove information in this file\n",
- "\n# Root directory in which $HOME directory is created\n",
- "\n# Mode for the new $HOME directory, will be modified by umask\n",
- "\n# Colon separated list of directories containing valid shells\n",
- "\n# Comma separated list of available shells (without paths)\n",
- "\n# Default shell (without path)\n",
- "\n# Default group (leave blank for new group per user)\n",
- "\n# Extra groups for new users\n",
- "\n# Default login class for new users\n",
- "\n# Range of valid default user ids\n",
- NULL,
- "\n# Range of valid default group ids\n",
- NULL,
- "\n# Days after which account expires (0=disabled)\n",
- "\n# Days after which password expires (0=disabled)\n"
-};
-
-static char const *kwds[] =
-{
- "",
- "defaultpasswd",
- "reuseuids",
- "reusegids",
- "nispasswd",
- "skeleton",
- "newmail",
- "logfile",
- "home",
- "homemode",
- "shellpath",
- "shells",
- "defaultshell",
- "defaultgroup",
- "extragroups",
- "defaultclass",
- "minuid",
- "maxuid",
- "mingid",
- "maxgid",
- "expire_days",
- "password_days",
- NULL
-};
-
-static char *
-unquote(char const * str)
-{
- if (str && (*str == '"' || *str == '\'')) {
- char *p = strchr(str + 1, *str);
-
- if (p != NULL)
- *p = '\0';
- return (char *) (*++str ? str : NULL);
- }
- return (char *) str;
-}
-
-int
-boolean_val(char const * str, int dflt)
-{
- if ((str = unquote(str)) != NULL) {
- int i;
-
- for (i = 0; booltrue[i]; i++)
- if (strcmp(str, booltrue[i]) == 0)
- return 1;
- for (i = 0; boolfalse[i]; i++)
- if (strcmp(str, boolfalse[i]) == 0)
- return 0;
-
- /*
- * Special cases for defaultpassword
- */
- if (strcmp(str, "random") == 0)
- return -1;
- if (strcmp(str, "none") == 0)
- return -2;
- }
- return dflt;
-}
-
-char const *
-boolean_str(int val)
-{
- if (val == -1)
- return "random";
- else if (val == -2)
- return "none";
- else
- return val ? booltrue[0] : boolfalse[0];
-}
-
-char *
-newstr(char const * p)
-{
- char *q = NULL;
-
- if ((p = unquote(p)) != NULL) {
- int l = strlen(p) + 1;
-
- if ((q = malloc(l)) != NULL)
- memcpy(q, p, l);
- }
- return q;
-}
-
-#define LNBUFSZ 1024
-
-
-struct userconf *
-read_userconfig(char const * file)
-{
- FILE *fp;
-
- extendarray(&config.groups, &config.numgroups, 200);
- memset(config.groups, 0, config.numgroups * sizeof(char *));
- if (file == NULL)
- file = _PATH_PW_CONF;
- if ((fp = fopen(file, "r")) != NULL) {
- int buflen = LNBUFSZ;
- char *buf = malloc(buflen);
-
- nextline:
- while (fgets(buf, buflen, fp) != NULL) {
- char *p;
-
- while ((p = strchr(buf, '\n')) == NULL) {
- int l;
- if (extendline(&buf, &buflen, buflen + LNBUFSZ) == -1) {
- int ch;
- while ((ch = fgetc(fp)) != '\n' && ch != EOF);
- goto nextline; /* Ignore it */
- }
- l = strlen(buf);
- if (fgets(buf + l, buflen - l, fp) == NULL)
- break; /* Unterminated last line */
- }
-
- if (p != NULL)
- *p = '\0';
-
- if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') {
- static char const toks[] = " \t\r\n,=";
- char *q = strtok(NULL, toks);
- int i = 0;
- mode_t *modeset;
-
- while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0)
- ++i;
-#if debugging
- if (i == _UC_FIELDS)
- printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : "");
- else
- printf("Got kwd[%s]=%s\n", p, q);
-#endif
- switch (i) {
- case _UC_DEFAULTPWD:
- config.default_password = boolean_val(q, 1);
- break;
- case _UC_REUSEUID:
- config.reuse_uids = boolean_val(q, 0);
- break;
- case _UC_REUSEGID:
- config.reuse_gids = boolean_val(q, 0);
- break;
- case _UC_NISPASSWD:
- config.nispasswd = (q == NULL || !boolean_val(q, 1))
- ? NULL : newstr(q);
- break;
- case _UC_DOTDIR:
- config.dotdir = (q == NULL || !boolean_val(q, 1))
- ? NULL : newstr(q);
- break;
- case _UC_NEWMAIL:
- config.newmail = (q == NULL || !boolean_val(q, 1))
- ? NULL : newstr(q);
- break;
- case _UC_LOGFILE:
- config.logfile = (q == NULL || !boolean_val(q, 1))
- ? NULL : newstr(q);
- break;
- case _UC_HOMEROOT:
- config.home = (q == NULL || !boolean_val(q, 1))
- ? "/home" : newstr(q);
- break;
- case _UC_HOMEMODE:
- modeset = setmode(q);
- config.homemode = (q == NULL || !boolean_val(q, 1))
- ? 0777 : getmode(modeset, 0777);
- free(modeset);
- break;
- case _UC_SHELLPATH:
- config.shelldir = (q == NULL || !boolean_val(q, 1))
- ? "/bin" : newstr(q);
- break;
- case _UC_SHELLS:
- for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks))
- system_shells[i] = newstr(q);
- if (i > 0)
- while (i < _UC_MAXSHELLS)
- system_shells[i++] = NULL;
- break;
- case _UC_DEFAULTSHELL:
- config.shell_default = (q == NULL || !boolean_val(q, 1))
- ? (char *) bourne_shell : newstr(q);
- break;
- case _UC_DEFAULTGROUP:
- q = unquote(q);
- config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL)
- ? NULL : newstr(q);
- break;
- case _UC_EXTRAGROUPS:
- for (i = 0; q != NULL; q = strtok(NULL, toks)) {
- if (extendarray(&config.groups, &config.numgroups, i + 2) != -1)
- config.groups[i++] = newstr(q);
- }
- if (i > 0)
- while (i < config.numgroups)
- config.groups[i++] = NULL;
- break;
- case _UC_DEFAULTCLASS:
- config.default_class = (q == NULL || !boolean_val(q, 1))
- ? NULL : newstr(q);
- break;
- case _UC_MINUID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.min_uid = (uid_t) atol(q);
- break;
- case _UC_MAXUID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.max_uid = (uid_t) atol(q);
- break;
- case _UC_MINGID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.min_gid = (gid_t) atol(q);
- break;
- case _UC_MAXGID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.max_gid = (gid_t) atol(q);
- break;
- case _UC_EXPIRE:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.expire_days = atoi(q);
- break;
- case _UC_PASSWORD:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.password_days = atoi(q);
- break;
- case _UC_FIELDS:
- case _UC_NONE:
- break;
- }
- }
- }
- free(buf);
- fclose(fp);
- }
- return &config;
-}
-
-
-int
-write_userconfig(char const * file)
-{
- int fd;
-
- if (file == NULL)
- file = _PATH_PW_CONF;
-
- if ((fd = open(file, O_CREAT | O_RDWR | O_TRUNC | O_EXLOCK, 0644)) != -1) {
- FILE *fp;
-
- if ((fp = fdopen(fd, "w")) == NULL)
- close(fd);
- else {
- int i, j, k;
- int len = LNBUFSZ;
- char *buf = malloc(len);
-
- for (i = _UC_NONE; i < _UC_FIELDS; i++) {
- int quote = 1;
- char const *val = buf;
-
- *buf = '\0';
- switch (i) {
- case _UC_DEFAULTPWD:
- val = boolean_str(config.default_password);
- break;
- case _UC_REUSEUID:
- val = boolean_str(config.reuse_uids);
- break;
- case _UC_REUSEGID:
- val = boolean_str(config.reuse_gids);
- break;
- case _UC_NISPASSWD:
- val = config.nispasswd ? config.nispasswd : "";
- quote = 0;
- break;
- case _UC_DOTDIR:
- val = config.dotdir ? config.dotdir : boolean_str(0);
- break;
- case _UC_NEWMAIL:
- val = config.newmail ? config.newmail : boolean_str(0);
- break;
- case _UC_LOGFILE:
- val = config.logfile ? config.logfile : boolean_str(0);
- break;
- case _UC_HOMEROOT:
- val = config.home;
- break;
- case _UC_HOMEMODE:
- sprintf(buf, "%04o", config.homemode);
- quote = 0;
- break;
- case _UC_SHELLPATH:
- val = config.shelldir;
- break;
- case _UC_SHELLS:
- for (j = k = 0; j < _UC_MAXSHELLS && system_shells[j] != NULL; j++) {
- char lbuf[64];
- int l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", system_shells[j]);
- if (l < 0)
- l = 0;
- if (l + k + 1 < len || extendline(&buf, &len, len + LNBUFSZ) != -1) {
- strcpy(buf + k, lbuf);
- k += l;
- }
- }
- quote = 0;
- break;
- case _UC_DEFAULTSHELL:
- val = config.shell_default ? config.shell_default : bourne_shell;
- break;
- case _UC_DEFAULTGROUP:
- val = config.default_group ? config.default_group : "";
- break;
- case _UC_EXTRAGROUPS:
- extendarray(&config.groups, &config.numgroups, 200);
- for (j = k = 0; j < config.numgroups && config.groups[j] != NULL; j++) {
- char lbuf[64];
- int l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", config.groups[j]);
- if (l < 0)
- l = 0;
- if (l + k + 1 < len || extendline(&buf, &len, len + 1024) != -1) {
- strcpy(buf + k, lbuf);
- k += l;
- }
- }
- quote = 0;
- break;
- case _UC_DEFAULTCLASS:
- val = config.default_class ? config.default_class : "";
- break;
- case _UC_MINUID:
- sprintf(buf, "%lu", (unsigned long) config.min_uid);
- quote = 0;
- break;
- case _UC_MAXUID:
- sprintf(buf, "%lu", (unsigned long) config.max_uid);
- quote = 0;
- break;
- case _UC_MINGID:
- sprintf(buf, "%lu", (unsigned long) config.min_gid);
- quote = 0;
- break;
- case _UC_MAXGID:
- sprintf(buf, "%lu", (unsigned long) config.max_gid);
- quote = 0;
- break;
- case _UC_EXPIRE:
- sprintf(buf, "%d", config.expire_days);
- quote = 0;
- break;
- case _UC_PASSWORD:
- sprintf(buf, "%d", config.password_days);
- quote = 0;
- break;
- case _UC_NONE:
- break;
- }
-
- if (comments[i])
- fputs(comments[i], fp);
-
- if (*kwds[i]) {
- if (quote)
- fprintf(fp, "%s = \"%s\"\n", kwds[i], val);
- else
- fprintf(fp, "%s = %s\n", kwds[i], val);
-#if debugging
- printf("WROTE: %s = %s\n", kwds[i], val);
-#endif
- }
- }
- free(buf);
- return fclose(fp) != EOF;
- }
- }
- return 0;
-}
diff --git a/pw/pw_group.c b/pw/pw_group.c
deleted file mode 100644
index a8f182c..0000000
--- a/pw/pw_group.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <ctype.h>
-#include <err.h>
-#include <termios.h>
-#include <stdbool.h>
-#include <unistd.h>
-
-#include "pw.h"
-#include "bitmap.h"
-
-
-static struct passwd *lookup_pwent(const char *user);
-static void delete_members(char ***members, int *grmembers, int *i,
- struct carg *arg, struct group *grp);
-static int print_group(struct group * grp, int pretty);
-static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args);
-
-int
-pw_group(struct userconf * cnf, int mode, struct cargs * args)
-{
- int rc;
- struct carg *a_name = getarg(args, 'n');
- struct carg *a_gid = getarg(args, 'g');
- struct carg *arg;
- struct group *grp = NULL;
- int grmembers = 0;
- char **members = NULL;
-
- static struct group fakegroup =
- {
- "nogroup",
- "*",
- -1,
- NULL
- };
-
- if (mode == M_LOCK || mode == M_UNLOCK)
- errx(EX_USAGE, "'lock' command is not available for groups");
-
- /*
- * With M_NEXT, we only need to return the
- * next gid to stdout
- */
- if (mode == M_NEXT) {
- gid_t next = gr_gidpolicy(cnf, args);
- if (getarg(args, 'q'))
- return next;
- printf("%ld\n", (long)next);
- return EXIT_SUCCESS;
- }
-
- if (mode == M_PRINT && getarg(args, 'a')) {
- int pretty = getarg(args, 'P') != NULL;
-
- SETGRENT();
- while ((grp = GETGRENT()) != NULL)
- print_group(grp, pretty);
- ENDGRENT();
- return EXIT_SUCCESS;
- }
- if (a_gid == NULL) {
- if (a_name == NULL)
- errx(EX_DATAERR, "group name or id required");
-
- if (mode != M_ADD && grp == NULL && isdigit((unsigned char)*a_name->val)) {
- (a_gid = a_name)->ch = 'g';
- a_name = NULL;
- }
- }
- grp = (a_name != NULL) ? GETGRNAM(a_name->val) : GETGRGID((gid_t) atoi(a_gid->val));
-
- if (mode == M_UPDATE || mode == M_DELETE || mode == M_PRINT) {
- if (a_name == NULL && grp == NULL) /* Try harder */
- grp = GETGRGID(atoi(a_gid->val));
-
- if (grp == NULL) {
- if (mode == M_PRINT && getarg(args, 'F')) {
- char *fmems[1];
- fmems[0] = NULL;
- fakegroup.gr_name = a_name ? a_name->val : "nogroup";
- fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : -1;
- fakegroup.gr_mem = fmems;
- return print_group(&fakegroup, getarg(args, 'P') != NULL);
- }
- errx(EX_DATAERR, "unknown group `%s'", a_name ? a_name->val : a_gid->val);
- }
- if (a_name == NULL) /* Needed later */
- a_name = addarg(args, 'n', grp->gr_name);
-
- /*
- * Handle deletions now
- */
- if (mode == M_DELETE) {
- gid_t gid = grp->gr_gid;
-
- rc = delgrent(grp);
- if (rc == -1)
- err(EX_IOERR, "group '%s' not available (NIS?)", grp->gr_name);
- else if (rc != 0) {
- warn("group update");
- return EX_IOERR;
- }
- pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", a_name->val, (long) gid);
- return EXIT_SUCCESS;
- } else if (mode == M_PRINT)
- return print_group(grp, getarg(args, 'P') != NULL);
-
- if (a_gid)
- grp->gr_gid = (gid_t) atoi(a_gid->val);
-
- if ((arg = getarg(args, 'l')) != NULL)
- grp->gr_name = pw_checkname((u_char *)arg->val, 0);
- } else {
- if (a_name == NULL) /* Required */
- errx(EX_DATAERR, "group name required");
- else if (grp != NULL) /* Exists */
- errx(EX_DATAERR, "group name `%s' already exists", a_name->val);
-
- extendarray(&members, &grmembers, 200);
- members[0] = NULL;
- grp = &fakegroup;
- grp->gr_name = pw_checkname((u_char *)a_name->val, 0);
- grp->gr_passwd = "*";
- grp->gr_gid = gr_gidpolicy(cnf, args);
- grp->gr_mem = members;
- }
-
- /*
- * This allows us to set a group password Group passwords is an
- * antique idea, rarely used and insecure (no secure database) Should
- * be discouraged, but it is apparently still supported by some
- * software.
- */
-
- if ((arg = getarg(args, 'h')) != NULL ||
- (arg = getarg(args, 'H')) != NULL) {
- if (strcmp(arg->val, "-") == 0)
- grp->gr_passwd = "*"; /* No access */
- else {
- int fd = atoi(arg->val);
- int precrypt = (arg->ch == 'H');
- int b;
- int istty = isatty(fd);
- struct termios t;
- char *p, line[256];
-
- if (istty) {
- if (tcgetattr(fd, &t) == -1)
- istty = 0;
- else {
- struct termios n = t;
-
- /* Disable echo */
- n.c_lflag &= ~(ECHO);
- tcsetattr(fd, TCSANOW, &n);
- printf("%sassword for group %s:", (mode == M_UPDATE) ? "New p" : "P", grp->gr_name);
- fflush(stdout);
- }
- }
- b = read(fd, line, sizeof(line) - 1);
- if (istty) { /* Restore state */
- tcsetattr(fd, TCSANOW, &t);
- fputc('\n', stdout);
- fflush(stdout);
- }
- if (b < 0) {
- warn("-h file descriptor");
- return EX_OSERR;
- }
- line[b] = '\0';
- if ((p = strpbrk(line, " \t\r\n")) != NULL)
- *p = '\0';
- if (!*line)
- errx(EX_DATAERR, "empty password read on file descriptor %d", fd);
- if (precrypt) {
- if (strchr(line, ':') != NULL)
- return EX_DATAERR;
- grp->gr_passwd = line;
- } else
- grp->gr_passwd = pw_pwcrypt(line);
- }
- }
-
- if (((arg = getarg(args, 'M')) != NULL ||
- (arg = getarg(args, 'd')) != NULL ||
- (arg = getarg(args, 'm')) != NULL) && arg->val) {
- int i = 0;
- char *p;
- struct passwd *pwd;
-
- /* Make sure this is not stay NULL with -M "" */
- extendarray(&members, &grmembers, 200);
- if (arg->ch == 'd')
- delete_members(&members, &grmembers, &i, arg, grp);
- else if (arg->ch == 'm') {
- int k = 0;
-
- while (grp->gr_mem[k] != NULL) {
- if (extendarray(&members, &grmembers, i + 2) != -1)
- members[i++] = grp->gr_mem[k];
- k++;
- }
- }
-
- if (arg->ch != 'd')
- for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
- int j;
-
- /*
- * Check for duplicates
- */
- pwd = lookup_pwent(p);
- for (j = 0; j < i && strcmp(members[j], pwd->pw_name) != 0; j++)
- ;
- if (j == i && extendarray(&members, &grmembers, i + 2) != -1)
- members[i++] = newstr(pwd->pw_name);
- }
- while (i < grmembers)
- members[i++] = NULL;
- grp->gr_mem = members;
- }
-
- if (getarg(args, 'N') != NULL)
- return print_group(grp, getarg(args, 'P') != NULL);
-
- if (mode == M_ADD && (rc = addgrent(grp)) != 0) {
- if (rc == -1)
- warnx("group '%s' already exists", grp->gr_name);
- else
- warn("group update");
- return EX_IOERR;
- } else if (mode == M_UPDATE && (rc = chggrent(a_name->val, grp)) != 0) {
- if (rc == -1)
- warnx("group '%s' not available (NIS?)", grp->gr_name);
- else
- warn("group update");
- return EX_IOERR;
- }
- /* grp may have been invalidated */
- if ((grp = GETGRNAM(a_name->val)) == NULL)
- errx(EX_SOFTWARE, "group disappeared during update");
-
- pw_log(cnf, mode, W_GROUP, "%s(%ld)", grp->gr_name, (long) grp->gr_gid);
-
- if (members)
- free(members);
-
- return EXIT_SUCCESS;
-}
-
-
-/*
- * Lookup a passwd entry using a name or UID.
- */
-static struct passwd *
-lookup_pwent(const char *user)
-{
- struct passwd *pwd;
-
- if ((pwd = GETPWNAM(user)) == NULL &&
- (!isdigit((unsigned char)*user) ||
- (pwd = getpwuid((uid_t) atoi(user))) == NULL))
- errx(EX_NOUSER, "user `%s' does not exist", user);
-
- return (pwd);
-}
-
-
-/*
- * Delete requested members from a group.
- */
-static void
-delete_members(char ***members, int *grmembers, int *i, struct carg *arg,
- struct group *grp)
-{
- bool matchFound;
- char *user;
- char *valueCopy;
- char *valuePtr;
- int k;
- struct passwd *pwd;
-
- k = 0;
- while (grp->gr_mem[k] != NULL) {
- matchFound = false;
- if ((valueCopy = strdup(arg->val)) == NULL)
- errx(EX_UNAVAILABLE, "out of memory");
- valuePtr = valueCopy;
- while ((user = strsep(&valuePtr, ", \t")) != NULL) {
- pwd = lookup_pwent(user);
- if (strcmp(grp->gr_mem[k], pwd->pw_name) == 0) {
- matchFound = true;
- break;
- }
- }
- free(valueCopy);
-
- if (!matchFound &&
- extendarray(members, grmembers, *i + 2) != -1)
- (*members)[(*i)++] = grp->gr_mem[k];
-
- k++;
- }
-
- return;
-}
-
-
-static gid_t
-gr_gidpolicy(struct userconf * cnf, struct cargs * args)
-{
- struct group *grp;
- gid_t gid = (gid_t) - 1;
- struct carg *a_gid = getarg(args, 'g');
-
- /*
- * Check the given gid, if any
- */
- if (a_gid != NULL) {
- gid = (gid_t) atol(a_gid->val);
-
- if ((grp = GETGRGID(gid)) != NULL && getarg(args, 'o') == NULL)
- errx(EX_DATAERR, "gid `%ld' has already been allocated", (long) grp->gr_gid);
- } else {
- struct bitmap bm;
-
- /*
- * We need to allocate the next available gid under one of
- * two policies a) Grab the first unused gid b) Grab the
- * highest possible unused gid
- */
- if (cnf->min_gid >= cnf->max_gid) { /* Sanity claus^H^H^H^Hheck */
- cnf->min_gid = 1000;
- cnf->max_gid = 32000;
- }
- bm = bm_alloc(cnf->max_gid - cnf->min_gid + 1);
-
- /*
- * Now, let's fill the bitmap from the password file
- */
- SETGRENT();
- while ((grp = GETGRENT()) != NULL)
- if ((gid_t)grp->gr_gid >= (gid_t)cnf->min_gid &&
- (gid_t)grp->gr_gid <= (gid_t)cnf->max_gid)
- bm_setbit(&bm, grp->gr_gid - cnf->min_gid);
- ENDGRENT();
-
- /*
- * Then apply the policy, with fallback to reuse if necessary
- */
- if (cnf->reuse_gids)
- gid = (gid_t) (bm_firstunset(&bm) + cnf->min_gid);
- else {
- gid = (gid_t) (bm_lastset(&bm) + 1);
- if (!bm_isset(&bm, gid))
- gid += cnf->min_gid;
- else
- gid = (gid_t) (bm_firstunset(&bm) + cnf->min_gid);
- }
-
- /*
- * Another sanity check
- */
- if (gid < cnf->min_gid || gid > cnf->max_gid)
- errx(EX_SOFTWARE, "unable to allocate a new gid - range fully used");
- bm_dealloc(&bm);
- }
- return gid;
-}
-
-
-static int
-print_group(struct group * grp, int pretty)
-{
- if (!pretty) {
- int buflen = 0;
- char *buf = NULL;
-
- fmtgrent(&buf, &buflen, grp);
- fputs(buf, stdout);
- free(buf);
- } else {
- int i;
-
- printf("Group Name: %-15s #%lu\n"
- " Members: ",
- grp->gr_name, (long) grp->gr_gid);
- for (i = 0; grp->gr_mem[i]; i++)
- printf("%s%s", i ? "," : "", grp->gr_mem[i]);
- fputs("\n\n", stdout);
- }
- return EXIT_SUCCESS;
-}
diff --git a/pw/pw_log.c b/pw/pw_log.c
deleted file mode 100644
index fc85828..0000000
--- a/pw/pw_log.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <fcntl.h>
-
-#include "pw.h"
-
-static FILE *logfile = NULL;
-
-void
-pw_log(struct userconf * cnf, int mode, int which, char const * fmt,...)
-{
- if (cnf->logfile && *cnf->logfile) {
- if (logfile == NULL) { /* With umask==0 we need to control file access modes on create */
- int fd = open(cnf->logfile, O_WRONLY | O_CREAT | O_APPEND, 0600);
-
- if (fd != -1)
- logfile = fdopen(fd, "a");
- }
- if (logfile != NULL) {
- va_list argp;
- int l;
- time_t now = time(NULL);
- struct tm *t = localtime(&now);
- char nfmt[256];
- char *name;
-
- if ((name = getenv("LOGNAME")) == NULL && (name = getenv("USER")) == NULL)
- name = "unknown";
- /* ISO 8601 International Standard Date format */
- strftime(nfmt, sizeof nfmt, "%Y-%m-%d %T ", t);
- l = strlen(nfmt);
- sprintf(nfmt + strlen(nfmt), "[%s:%s%s] %s\n", name, Which[which], Modes[mode], fmt);
- va_start(argp, fmt);
- vfprintf(logfile, nfmt, argp);
- va_end(argp);
- fflush(logfile);
- }
- }
-}
diff --git a/pw/pw_nis.c b/pw/pw_nis.c
deleted file mode 100644
index 74a3ed0..0000000
--- a/pw/pw_nis.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "pw.h"
-
-static int
-pw_nisupdate(const char * path, struct passwd * pwd, char const * user, int mode)
-{
- char pfx[32];
- char pwbuf[PWBUFSZ];
- int l = sprintf(pfx, "%s:", user);
-
- /*
- * Update the passwd file first
- */
- if (pwd == NULL)
- *pwbuf = '\0';
- else
- fmtpwentry(pwbuf, pwd, PWF_MASTER);
- return fileupdate(path, 0600, pwbuf, pfx, l, mode) != 0;
-}
-
-int
-addnispwent(const char *path, struct passwd * pwd)
-{
- return pw_nisupdate(path, pwd, pwd->pw_name, UPD_CREATE);
-}
-
-int
-chgnispwent(const char *path, char const * login, struct passwd * pwd)
-{
- return pw_nisupdate(path, pwd, login, UPD_REPLACE);
-}
-
-int
-delnispwent(const char *path, const char *login)
-{
- return pw_nisupdate(path, NULL, login, UPD_DELETE);
-}
diff --git a/pw/pw_user.c b/pw/pw_user.c
deleted file mode 100644
index c8364ca..0000000
--- a/pw/pw_user.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <ctype.h>
-#include <err.h>
-#include <fcntl.h>
-#include <sys/param.h>
-#include <dirent.h>
-#include <paths.h>
-#include <termios.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <unistd.h>
-#include <login_cap.h>
-#include "pw.h"
-#include "bitmap.h"
-
-#define LOGNAMESIZE (MAXLOGNAME-1)
-
-static char locked_str[] = "*LOCKED*";
-
-static int print_user(struct passwd * pwd, int pretty, int v7);
-static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args);
-static uid_t pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer);
-static time_t pw_pwdpolicy(struct userconf * cnf, struct cargs * args);
-static time_t pw_exppolicy(struct userconf * cnf, struct cargs * args);
-static char *pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user);
-static char *pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell);
-static char *pw_password(struct userconf * cnf, struct cargs * args, char const * user);
-static char *shell_path(char const * path, char *shells[], char *sh);
-static void rmat(uid_t uid);
-static void rmopie(char const * name);
-
-/*-
- * -C config configuration file
- * -q quiet operation
- * -n name login name
- * -u uid user id
- * -c comment user name/comment
- * -d directory home directory
- * -e date account expiry date
- * -p date password expiry date
- * -g grp primary group
- * -G grp1,grp2 additional groups
- * -m [ -k dir ] create and set up home
- * -s shell name of login shell
- * -o duplicate uid ok
- * -L class user class
- * -l name new login name
- * -h fd password filehandle
- * -H fd encrypted password filehandle
- * -F force print or add
- * Setting defaults:
- * -D set user defaults
- * -b dir default home root dir
- * -e period default expiry period
- * -p period default password change period
- * -g group default group
- * -G grp1,grp2.. default additional groups
- * -L class default login class
- * -k dir default home skeleton
- * -s shell default shell
- * -w method default password method
- */
-
-int
-pw_user(struct userconf * cnf, int mode, struct cargs * args)
-{
- int rc, edited = 0;
- char *p = NULL;
- char *passtmp;
- struct carg *a_name;
- struct carg *a_uid;
- struct carg *arg;
- struct passwd *pwd = NULL;
- struct group *grp;
- struct stat st;
- char line[_PASSWORD_LEN+1];
- FILE *fp;
- mode_t dmode;
- char *dmode_c;
- void *set = NULL;
-
- static struct passwd fakeuser =
- {
- NULL,
- "*",
- -1,
- -1,
- 0,
- "",
- "User &",
- "/nonexistent",
- "/bin/sh",
- 0
-#if defined(__FreeBSD__)
- ,0
-#endif
- };
-
-
- /*
- * With M_NEXT, we only need to return the
- * next uid to stdout
- */
- if (mode == M_NEXT)
- {
- uid_t next = pw_uidpolicy(cnf, args);
- if (getarg(args, 'q'))
- return next;
- printf("%ld:", (long)next);
- pw_group(cnf, mode, args);
- return EXIT_SUCCESS;
- }
-
- /*
- * We can do all of the common legwork here
- */
-
- if ((arg = getarg(args, 'b')) != NULL) {
- cnf->home = arg->val;
- }
-
- if ((arg = getarg(args, 'M')) != NULL) {
- dmode_c = arg->val;
- if ((set = setmode(dmode_c)) == NULL)
- errx(EX_DATAERR, "invalid directory creation mode '%s'",
- dmode_c);
- dmode = getmode(set, S_IRWXU | S_IRWXG | S_IRWXO);
- free(set);
- cnf->homemode = dmode;
- }
-
- /*
- * If we'll need to use it or we're updating it,
- * then create the base home directory if necessary
- */
- if (arg != NULL || getarg(args, 'm') != NULL) {
- int l = strlen(cnf->home);
-
- if (l > 1 && cnf->home[l-1] == '/') /* Shave off any trailing path delimiter */
- cnf->home[--l] = '\0';
-
- if (l < 2 || *cnf->home != '/') /* Check for absolute path name */
- errx(EX_DATAERR, "invalid base directory for home '%s'", cnf->home);
-
- if (stat(cnf->home, &st) == -1) {
- char dbuf[MAXPATHLEN];
-
- /*
- * This is a kludge especially for Joerg :)
- * If the home directory would be created in the root partition, then
- * we really create it under /usr which is likely to have more space.
- * But we create a symlink from cnf->home -> "/usr" -> cnf->home
- */
- if (strchr(cnf->home+1, '/') == NULL) {
- strcpy(dbuf, "/usr");
- strncat(dbuf, cnf->home, MAXPATHLEN-5);
- if (mkdir(dbuf, cnf->homemode) != -1 || errno == EEXIST) {
- chown(dbuf, 0, 0);
- /*
- * Skip first "/" and create symlink:
- * /home -> usr/home
- */
- symlink(dbuf+1, cnf->home);
- }
- /* If this falls, fall back to old method */
- }
- strlcpy(dbuf, cnf->home, sizeof(dbuf));
- p = dbuf;
- if (stat(dbuf, &st) == -1) {
- while ((p = strchr(++p, '/')) != NULL) {
- *p = '\0';
- if (stat(dbuf, &st) == -1) {
- if (mkdir(dbuf, cnf->homemode) == -1)
- goto direrr;
- chown(dbuf, 0, 0);
- } else if (!S_ISDIR(st.st_mode))
- errx(EX_OSFILE, "'%s' (root home parent) is not a directory", dbuf);
- *p = '/';
- }
- }
- if (stat(dbuf, &st) == -1) {
- if (mkdir(dbuf, cnf->homemode) == -1) {
- direrr: err(EX_OSFILE, "mkdir '%s'", dbuf);
- }
- chown(dbuf, 0, 0);
- }
- } else if (!S_ISDIR(st.st_mode))
- errx(EX_OSFILE, "root home `%s' is not a directory", cnf->home);
- }
-
- if ((arg = getarg(args, 'e')) != NULL)
- cnf->expire_days = atoi(arg->val);
-
- if ((arg = getarg(args, 'y')) != NULL)
- cnf->nispasswd = arg->val;
-
- if ((arg = getarg(args, 'p')) != NULL && arg->val)
- cnf->password_days = atoi(arg->val);
-
- if ((arg = getarg(args, 'g')) != NULL) {
- if (!*(p = arg->val)) /* Handle empty group list specially */
- cnf->default_group = "";
- else {
- if ((grp = GETGRNAM(p)) == NULL) {
- if (!isdigit((unsigned char)*p) || (grp = GETGRGID((gid_t) atoi(p))) == NULL)
- errx(EX_NOUSER, "group `%s' does not exist", p);
- }
- cnf->default_group = newstr(grp->gr_name);
- }
- }
- if ((arg = getarg(args, 'L')) != NULL)
- cnf->default_class = pw_checkname((u_char *)arg->val, 0);
-
- if ((arg = getarg(args, 'G')) != NULL && arg->val) {
- int i = 0;
-
- for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
- if ((grp = GETGRNAM(p)) == NULL) {
- if (!isdigit((unsigned char)*p) || (grp = GETGRGID((gid_t) atoi(p))) == NULL)
- errx(EX_NOUSER, "group `%s' does not exist", p);
- }
- if (extendarray(&cnf->groups, &cnf->numgroups, i + 2) != -1)
- cnf->groups[i++] = newstr(grp->gr_name);
- }
- while (i < cnf->numgroups)
- cnf->groups[i++] = NULL;
- }
-
- if ((arg = getarg(args, 'k')) != NULL) {
- if (stat(cnf->dotdir = arg->val, &st) == -1 || !S_ISDIR(st.st_mode))
- errx(EX_OSFILE, "skeleton `%s' is not a directory or does not exist", cnf->dotdir);
- }
-
- if ((arg = getarg(args, 's')) != NULL)
- cnf->shell_default = arg->val;
-
- if ((arg = getarg(args, 'w')) != NULL)
- cnf->default_password = boolean_val(arg->val, cnf->default_password);
- if (mode == M_ADD && getarg(args, 'D')) {
- if (getarg(args, 'n') != NULL)
- errx(EX_DATAERR, "can't combine `-D' with `-n name'");
- if ((arg = getarg(args, 'u')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) {
- if ((cnf->min_uid = (uid_t) atoi(p)) == 0)
- cnf->min_uid = 1000;
- if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_uid = (uid_t) atoi(p)) < cnf->min_uid)
- cnf->max_uid = 32000;
- }
- if ((arg = getarg(args, 'i')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) {
- if ((cnf->min_gid = (gid_t) atoi(p)) == 0)
- cnf->min_gid = 1000;
- if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_gid = (gid_t) atoi(p)) < cnf->min_gid)
- cnf->max_gid = 32000;
- }
-
- arg = getarg(args, 'C');
- if (write_userconfig(arg ? arg->val : NULL))
- return EXIT_SUCCESS;
- warn("config update");
- return EX_IOERR;
- }
-
- if (mode == M_PRINT && getarg(args, 'a')) {
- int pretty = getarg(args, 'P') != NULL;
- int v7 = getarg(args, '7') != NULL;
-
- SETPWENT();
- while ((pwd = GETPWENT()) != NULL)
- print_user(pwd, pretty, v7);
- ENDPWENT();
- return EXIT_SUCCESS;
- }
-
- if ((a_name = getarg(args, 'n')) != NULL)
- pwd = GETPWNAM(pw_checkname((u_char *)a_name->val, 0));
- a_uid = getarg(args, 'u');
-
- if (a_uid == NULL) {
- if (a_name == NULL)
- errx(EX_DATAERR, "user name or id required");
-
- /*
- * Determine whether 'n' switch is name or uid - we don't
- * really don't really care which we have, but we need to
- * know.
- */
- if (mode != M_ADD && pwd == NULL
- && strspn(a_name->val, "0123456789") == strlen(a_name->val)
- && atoi(a_name->val) > 0) { /* Assume uid */
- (a_uid = a_name)->ch = 'u';
- a_name = NULL;
- }
- }
-
- /*
- * Update, delete & print require that the user exists
- */
- if (mode == M_UPDATE || mode == M_DELETE ||
- mode == M_PRINT || mode == M_LOCK || mode == M_UNLOCK) {
-
- if (a_name == NULL && pwd == NULL) /* Try harder */
- pwd = GETPWUID(atoi(a_uid->val));
-
- if (pwd == NULL) {
- if (mode == M_PRINT && getarg(args, 'F')) {
- fakeuser.pw_name = a_name ? a_name->val : "nouser";
- fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : -1;
- return print_user(&fakeuser,
- getarg(args, 'P') != NULL,
- getarg(args, '7') != NULL);
- }
- if (a_name == NULL)
- errx(EX_NOUSER, "no such uid `%s'", a_uid->val);
- errx(EX_NOUSER, "no such user `%s'", a_name->val);
- }
-
- if (a_name == NULL) /* May be needed later */
- a_name = addarg(args, 'n', newstr(pwd->pw_name));
-
- /*
- * The M_LOCK and M_UNLOCK functions simply add or remove
- * a "*LOCKED*" prefix from in front of the password to
- * prevent it decoding correctly, and therefore prevents
- * access. Of course, this only prevents access via
- * password authentication (not ssh, kerberos or any
- * other method that does not use the UNIX password) but
- * that is a known limitation.
- */
-
- if (mode == M_LOCK) {
- if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str)-1) == 0)
- errx(EX_DATAERR, "user '%s' is already locked", pwd->pw_name);
- passtmp = malloc(strlen(pwd->pw_passwd) + sizeof(locked_str));
- if (passtmp == NULL) /* disaster */
- errx(EX_UNAVAILABLE, "out of memory");
- strcpy(passtmp, locked_str);
- strcat(passtmp, pwd->pw_passwd);
- pwd->pw_passwd = passtmp;
- edited = 1;
- } else if (mode == M_UNLOCK) {
- if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str)-1) != 0)
- errx(EX_DATAERR, "user '%s' is not locked", pwd->pw_name);
- pwd->pw_passwd += sizeof(locked_str)-1;
- edited = 1;
- } else if (mode == M_DELETE) {
- /*
- * Handle deletions now
- */
- char file[MAXPATHLEN];
- char home[MAXPATHLEN];
- uid_t uid = pwd->pw_uid;
-
- if (strcmp(pwd->pw_name, "root") == 0)
- errx(EX_DATAERR, "cannot remove user 'root'");
-
- if (!PWALTDIR()) {
- /*
- * Remove opie record from /etc/opiekeys
- */
-
- rmopie(pwd->pw_name);
-
- /*
- * Remove crontabs
- */
- sprintf(file, "/var/cron/tabs/%s", pwd->pw_name);
- if (access(file, F_OK) == 0) {
- sprintf(file, "crontab -u %s -r", pwd->pw_name);
- system(file);
- }
- }
- /*
- * Save these for later, since contents of pwd may be
- * invalidated by deletion
- */
- sprintf(file, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
- strlcpy(home, pwd->pw_dir, sizeof(home));
-
- rc = delpwent(pwd);
- if (rc == -1)
- err(EX_IOERR, "user '%s' does not exist", pwd->pw_name);
- else if (rc != 0) {
- warn("passwd update");
- return EX_IOERR;
- }
-
- if (cnf->nispasswd && *cnf->nispasswd=='/') {
- rc = delnispwent(cnf->nispasswd, a_name->val);
- if (rc == -1)
- warnx("WARNING: user '%s' does not exist in NIS passwd", pwd->pw_name);
- else if (rc != 0)
- warn("WARNING: NIS passwd update");
- /* non-fatal */
- }
-
- editgroups(a_name->val, NULL);
-
- pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid);
-
- if (!PWALTDIR()) {
- /*
- * Remove mail file
- */
- remove(file);
-
- /*
- * Remove at jobs
- */
- if (getpwuid(uid) == NULL)
- rmat(uid);
-
- /*
- * Remove home directory and contents
- */
- if (getarg(args, 'r') != NULL && *home == '/' && getpwuid(uid) == NULL) {
- if (stat(home, &st) != -1) {
- rm_r(home, uid);
- pw_log(cnf, mode, W_USER, "%s(%ld) home '%s' %sremoved",
- a_name->val, (long) uid, home,
- stat(home, &st) == -1 ? "" : "not completely ");
- }
- }
- }
- return EXIT_SUCCESS;
- } else if (mode == M_PRINT)
- return print_user(pwd,
- getarg(args, 'P') != NULL,
- getarg(args, '7') != NULL);
-
- /*
- * The rest is edit code
- */
- if ((arg = getarg(args, 'l')) != NULL) {
- if (strcmp(pwd->pw_name, "root") == 0)
- errx(EX_DATAERR, "can't rename `root' account");
- pwd->pw_name = pw_checkname((u_char *)arg->val, 0);
- edited = 1;
- }
-
- if ((arg = getarg(args, 'u')) != NULL && isdigit((unsigned char)*arg->val)) {
- pwd->pw_uid = (uid_t) atol(arg->val);
- edited = 1;
- if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0)
- errx(EX_DATAERR, "can't change uid of `root' account");
- if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
- warnx("WARNING: account `%s' will have a uid of 0 (superuser access!)", pwd->pw_name);
- }
-
- if ((arg = getarg(args, 'g')) != NULL && pwd->pw_uid != 0) { /* Already checked this */
- gid_t newgid = (gid_t) GETGRNAM(cnf->default_group)->gr_gid;
- if (newgid != pwd->pw_gid) {
- edited = 1;
- pwd->pw_gid = newgid;
- }
- }
-
- if ((arg = getarg(args, 'p')) != NULL) {
- if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) {
- if (pwd->pw_change != 0) {
- pwd->pw_change = 0;
- edited = 1;
- }
- }
- else {
- time_t now = time(NULL);
- time_t expire = parse_date(now, arg->val);
-
- if (now == expire)
- errx(EX_DATAERR, "invalid password change date `%s'", arg->val);
- if (pwd->pw_change != expire) {
- pwd->pw_change = expire;
- edited = 1;
- }
- }
- }
-
- if ((arg = getarg(args, 'e')) != NULL) {
- if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) {
- if (pwd->pw_expire != 0) {
- pwd->pw_expire = 0;
- edited = 1;
- }
- }
- else {
- time_t now = time(NULL);
- time_t expire = parse_date(now, arg->val);
-
- if (now == expire)
- errx(EX_DATAERR, "invalid account expiry date `%s'", arg->val);
- if (pwd->pw_expire != expire) {
- pwd->pw_expire = expire;
- edited = 1;
- }
- }
- }
-
- if ((arg = getarg(args, 's')) != NULL) {
- char *shell = shell_path(cnf->shelldir, cnf->shells, arg->val);
- if (shell == NULL)
- shell = "";
- if (strcmp(shell, pwd->pw_shell) != 0) {
- pwd->pw_shell = shell;
- edited = 1;
- }
- }
-
- if (getarg(args, 'L')) {
- if (cnf->default_class == NULL)
- cnf->default_class = "";
- if (strcmp(pwd->pw_class, cnf->default_class) != 0) {
- pwd->pw_class = cnf->default_class;
- edited = 1;
- }
- }
-
- if ((arg = getarg(args, 'd')) != NULL) {
- if (strcmp(pwd->pw_dir, arg->val))
- edited = 1;
- if (stat(pwd->pw_dir = arg->val, &st) == -1) {
- if (getarg(args, 'm') == NULL && strcmp(pwd->pw_dir, "/nonexistent") != 0)
- warnx("WARNING: home `%s' does not exist", pwd->pw_dir);
- } else if (!S_ISDIR(st.st_mode))
- warnx("WARNING: home `%s' is not a directory", pwd->pw_dir);
- }
-
- if ((arg = getarg(args, 'w')) != NULL &&
- getarg(args, 'h') == NULL && getarg(args, 'H') == NULL) {
- login_cap_t *lc;
-
- lc = login_getpwclass(pwd);
- if (lc == NULL ||
- login_setcryptfmt(lc, "md5", NULL) == NULL)
- warn("setting crypt(3) format");
- login_close(lc);
- pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name);
- edited = 1;
- }
-
- } else {
- login_cap_t *lc;
-
- /*
- * Add code
- */
-
- if (a_name == NULL) /* Required */
- errx(EX_DATAERR, "login name required");
- else if ((pwd = GETPWNAM(a_name->val)) != NULL) /* Exists */
- errx(EX_DATAERR, "login name `%s' already exists", a_name->val);
-
- /*
- * Now, set up defaults for a new user
- */
- pwd = &fakeuser;
- pwd->pw_name = a_name->val;
- pwd->pw_class = cnf->default_class ? cnf->default_class : "";
- pwd->pw_uid = pw_uidpolicy(cnf, args);
- pwd->pw_gid = pw_gidpolicy(cnf, args, pwd->pw_name, (gid_t) pwd->pw_uid);
- pwd->pw_change = pw_pwdpolicy(cnf, args);
- pwd->pw_expire = pw_exppolicy(cnf, args);
- pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name);
- pwd->pw_shell = pw_shellpolicy(cnf, args, NULL);
- lc = login_getpwclass(pwd);
- if (lc == NULL || login_setcryptfmt(lc, "md5", NULL) == NULL)
- warn("setting crypt(3) format");
- login_close(lc);
- pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name);
- edited = 1;
-
- if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
- warnx("WARNING: new account `%s' has a uid of 0 (superuser access!)", pwd->pw_name);
- }
-
- /*
- * Shared add/edit code
- */
- if ((arg = getarg(args, 'c')) != NULL) {
- char *gecos = pw_checkname((u_char *)arg->val, 1);
- if (strcmp(pwd->pw_gecos, gecos) != 0) {
- pwd->pw_gecos = gecos;
- edited = 1;
- }
- }
-
- if ((arg = getarg(args, 'h')) != NULL ||
- (arg = getarg(args, 'H')) != NULL) {
- if (strcmp(arg->val, "-") == 0) {
- if (!pwd->pw_passwd || *pwd->pw_passwd != '*') {
- pwd->pw_passwd = "*"; /* No access */
- edited = 1;
- }
- } else {
- int fd = atoi(arg->val);
- int precrypt = (arg->ch == 'H');
- int b;
- int istty = isatty(fd);
- struct termios t;
- login_cap_t *lc;
-
- if (istty) {
- if (tcgetattr(fd, &t) == -1)
- istty = 0;
- else {
- struct termios n = t;
-
- /* Disable echo */
- n.c_lflag &= ~(ECHO);
- tcsetattr(fd, TCSANOW, &n);
- printf("%s%spassword for user %s:",
- (mode == M_UPDATE) ? "new " : "",
- precrypt ? "encrypted " : "",
- pwd->pw_name);
- fflush(stdout);
- }
- }
- b = read(fd, line, sizeof(line) - 1);
- if (istty) { /* Restore state */
- tcsetattr(fd, TCSANOW, &t);
- fputc('\n', stdout);
- fflush(stdout);
- }
- if (b < 0) {
- warn("-%c file descriptor", precrypt ? 'H' :
- 'h');
- return EX_IOERR;
- }
- line[b] = '\0';
- if ((p = strpbrk(line, "\r\n")) != NULL)
- *p = '\0';
- if (!*line)
- errx(EX_DATAERR, "empty password read on file descriptor %d", fd);
- if (precrypt) {
- if (strchr(line, ':') != NULL)
- return EX_DATAERR;
- pwd->pw_passwd = line;
- } else {
- lc = login_getpwclass(pwd);
- if (lc == NULL ||
- login_setcryptfmt(lc, "md5", NULL) == NULL)
- warn("setting crypt(3) format");
- login_close(lc);
- pwd->pw_passwd = pw_pwcrypt(line);
- }
- edited = 1;
- }
- }
-
- /*
- * Special case: -N only displays & exits
- */
- if (getarg(args, 'N') != NULL)
- return print_user(pwd,
- getarg(args, 'P') != NULL,
- getarg(args, '7') != NULL);
-
- if (mode == M_ADD) {
- edited = 1; /* Always */
- rc = addpwent(pwd);
- if (rc == -1) {
- warnx("user '%s' already exists", pwd->pw_name);
- return EX_IOERR;
- } else if (rc != 0) {
- warn("passwd file update");
- return EX_IOERR;
- }
- if (cnf->nispasswd && *cnf->nispasswd=='/') {
- rc = addnispwent(cnf->nispasswd, pwd);
- if (rc == -1)
- warnx("User '%s' already exists in NIS passwd", pwd->pw_name);
- else
- warn("NIS passwd update");
- /* NOTE: we treat NIS-only update errors as non-fatal */
- }
- } else if (mode == M_UPDATE || mode == M_LOCK || mode == M_UNLOCK) {
- if (edited) { /* Only updated this if required */
- rc = chgpwent(a_name->val, pwd);
- if (rc == -1) {
- warnx("user '%s' does not exist (NIS?)", pwd->pw_name);
- return EX_IOERR;
- } else if (rc != 0) {
- warn("passwd file update");
- return EX_IOERR;
- }
- if ( cnf->nispasswd && *cnf->nispasswd=='/') {
- rc = chgnispwent(cnf->nispasswd, a_name->val, pwd);
- if (rc == -1)
- warn("User '%s' not found in NIS passwd", pwd->pw_name);
- else
- warn("NIS passwd update");
- /* NOTE: NIS-only update errors are not fatal */
- }
- }
- }
-
- /*
- * Ok, user is created or changed - now edit group file
- */
-
- if (mode == M_ADD || getarg(args, 'G') != NULL)
- editgroups(pwd->pw_name, cnf->groups);
-
- /* go get a current version of pwd */
- pwd = GETPWNAM(a_name->val);
- if (pwd == NULL) {
- /* This will fail when we rename, so special case that */
- if (mode == M_UPDATE && (arg = getarg(args, 'l')) != NULL) {
- a_name->val = arg->val; /* update new name */
- pwd = GETPWNAM(a_name->val); /* refetch renamed rec */
- }
- }
- if (pwd == NULL) /* can't go on without this */
- errx(EX_NOUSER, "user '%s' disappeared during update", a_name->val);
-
- grp = GETGRGID(pwd->pw_gid);
- pw_log(cnf, mode, W_USER, "%s(%ld):%s(%ld):%s:%s:%s",
- pwd->pw_name, (long) pwd->pw_uid,
- grp ? grp->gr_name : "unknown", (long) (grp ? grp->gr_gid : -1),
- pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
-
- /*
- * If adding, let's touch and chown the user's mail file. This is not
- * strictly necessary under BSD with a 0755 maildir but it also
- * doesn't hurt anything to create the empty mailfile
- */
- if (mode == M_ADD) {
- if (!PWALTDIR()) {
- sprintf(line, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
- close(open(line, O_RDWR | O_CREAT, 0600)); /* Preserve contents &
- * mtime */
- chown(line, pwd->pw_uid, pwd->pw_gid);
- }
- }
-
- /*
- * Let's create and populate the user's home directory. Note
- * that this also `works' for editing users if -m is used, but
- * existing files will *not* be overwritten.
- */
- if (!PWALTDIR() && getarg(args, 'm') != NULL && pwd->pw_dir && *pwd->pw_dir == '/' && pwd->pw_dir[1]) {
- copymkdir(pwd->pw_dir, cnf->dotdir, cnf->homemode, pwd->pw_uid, pwd->pw_gid);
- pw_log(cnf, mode, W_USER, "%s(%ld) home %s made",
- pwd->pw_name, (long) pwd->pw_uid, pwd->pw_dir);
- }
-
-
- /*
- * Finally, send mail to the new user as well, if we are asked to
- */
- if (mode == M_ADD && !PWALTDIR() && cnf->newmail && *cnf->newmail && (fp = fopen(cnf->newmail, "r")) != NULL) {
- FILE *pfp = popen(_PATH_SENDMAIL " -t", "w");
-
- if (pfp == NULL)
- warn("sendmail");
- else {
- fprintf(pfp, "From: root\n" "To: %s\n" "Subject: Welcome!\n\n", pwd->pw_name);
- while (fgets(line, sizeof(line), fp) != NULL) {
- /* Do substitutions? */
- fputs(line, pfp);
- }
- pclose(pfp);
- pw_log(cnf, mode, W_USER, "%s(%ld) new user mail sent",
- pwd->pw_name, (long) pwd->pw_uid);
- }
- fclose(fp);
- }
-
- return EXIT_SUCCESS;
-}
-
-
-static uid_t
-pw_uidpolicy(struct userconf * cnf, struct cargs * args)
-{
- struct passwd *pwd;
- uid_t uid = (uid_t) - 1;
- struct carg *a_uid = getarg(args, 'u');
-
- /*
- * Check the given uid, if any
- */
- if (a_uid != NULL) {
- uid = (uid_t) atol(a_uid->val);
-
- if ((pwd = GETPWUID(uid)) != NULL && getarg(args, 'o') == NULL)
- errx(EX_DATAERR, "uid `%ld' has already been allocated", (long) pwd->pw_uid);
- } else {
- struct bitmap bm;
-
- /*
- * We need to allocate the next available uid under one of
- * two policies a) Grab the first unused uid b) Grab the
- * highest possible unused uid
- */
- if (cnf->min_uid >= cnf->max_uid) { /* Sanity
- * claus^H^H^H^Hheck */
- cnf->min_uid = 1000;
- cnf->max_uid = 32000;
- }
- bm = bm_alloc(cnf->max_uid - cnf->min_uid + 1);
-
- /*
- * Now, let's fill the bitmap from the password file
- */
- SETPWENT();
- while ((pwd = GETPWENT()) != NULL)
- if (pwd->pw_uid >= (uid_t) cnf->min_uid && pwd->pw_uid <= (uid_t) cnf->max_uid)
- bm_setbit(&bm, pwd->pw_uid - cnf->min_uid);
- ENDPWENT();
-
- /*
- * Then apply the policy, with fallback to reuse if necessary
- */
- if (cnf->reuse_uids || (uid = (uid_t) (bm_lastset(&bm) + cnf->min_uid + 1)) > cnf->max_uid)
- uid = (uid_t) (bm_firstunset(&bm) + cnf->min_uid);
-
- /*
- * Another sanity check
- */
- if (uid < cnf->min_uid || uid > cnf->max_uid)
- errx(EX_SOFTWARE, "unable to allocate a new uid - range fully used");
- bm_dealloc(&bm);
- }
- return uid;
-}
-
-
-static uid_t
-pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer)
-{
- struct group *grp;
- gid_t gid = (uid_t) - 1;
- struct carg *a_gid = getarg(args, 'g');
-
- /*
- * If no arg given, see if default can help out
- */
- if (a_gid == NULL && cnf->default_group && *cnf->default_group)
- a_gid = addarg(args, 'g', cnf->default_group);
-
- /*
- * Check the given gid, if any
- */
- SETGRENT();
- if (a_gid != NULL) {
- if ((grp = GETGRNAM(a_gid->val)) == NULL) {
- gid = (gid_t) atol(a_gid->val);
- if ((gid == 0 && !isdigit((unsigned char)*a_gid->val)) || (grp = GETGRGID(gid)) == NULL)
- errx(EX_NOUSER, "group `%s' is not defined", a_gid->val);
- }
- gid = grp->gr_gid;
- } else if ((grp = GETGRNAM(nam)) != NULL && grp->gr_mem[0] == NULL) {
- gid = grp->gr_gid; /* Already created? Use it anyway... */
- } else {
- struct cargs grpargs;
- char tmp[32];
-
- LIST_INIT(&grpargs);
- addarg(&grpargs, 'n', nam);
-
- /*
- * We need to auto-create a group with the user's name. We
- * can send all the appropriate output to our sister routine
- * bit first see if we can create a group with gid==uid so we
- * can keep the user and group ids in sync. We purposely do
- * NOT check the gid range if we can force the sync. If the
- * user's name dups an existing group, then the group add
- * function will happily handle that case for us and exit.
- */
- if (GETGRGID(prefer) == NULL) {
- sprintf(tmp, "%lu", (unsigned long) prefer);
- addarg(&grpargs, 'g', tmp);
- }
- if (getarg(args, 'N'))
- {
- addarg(&grpargs, 'N', NULL);
- addarg(&grpargs, 'q', NULL);
- gid = pw_group(cnf, M_NEXT, &grpargs);
- }
- else
- {
- pw_group(cnf, M_ADD, &grpargs);
- if ((grp = GETGRNAM(nam)) != NULL)
- gid = grp->gr_gid;
- }
- a_gid = LIST_FIRST(&grpargs);
- while (a_gid != NULL) {
- struct carg *t = LIST_NEXT(a_gid, list);
- LIST_REMOVE(a_gid, list);
- a_gid = t;
- }
- }
- ENDGRENT();
- return gid;
-}
-
-
-static time_t
-pw_pwdpolicy(struct userconf * cnf, struct cargs * args)
-{
- time_t result = 0;
- time_t now = time(NULL);
- struct carg *arg = getarg(args, 'p');
-
- if (arg != NULL) {
- if ((result = parse_date(now, arg->val)) == now)
- errx(EX_DATAERR, "invalid date/time `%s'", arg->val);
- } else if (cnf->password_days > 0)
- result = now + ((long) cnf->password_days * 86400L);
- return result;
-}
-
-
-static time_t
-pw_exppolicy(struct userconf * cnf, struct cargs * args)
-{
- time_t result = 0;
- time_t now = time(NULL);
- struct carg *arg = getarg(args, 'e');
-
- if (arg != NULL) {
- if ((result = parse_date(now, arg->val)) == now)
- errx(EX_DATAERR, "invalid date/time `%s'", arg->val);
- } else if (cnf->expire_days > 0)
- result = now + ((long) cnf->expire_days * 86400L);
- return result;
-}
-
-
-static char *
-pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user)
-{
- struct carg *arg = getarg(args, 'd');
-
- if (arg)
- return arg->val;
- else {
- static char home[128];
-
- if (cnf->home == NULL || *cnf->home == '\0')
- errx(EX_CONFIG, "no base home directory set");
- sprintf(home, "%s/%s", cnf->home, user);
- return home;
- }
-}
-
-static char *
-shell_path(char const * path, char *shells[], char *sh)
-{
- if (sh != NULL && (*sh == '/' || *sh == '\0'))
- return sh; /* specified full path or forced none */
- else {
- char *p;
- char paths[_UC_MAXLINE];
-
- /*
- * We need to search paths
- */
- strlcpy(paths, path, sizeof(paths));
- for (p = strtok(paths, ": \t\r\n"); p != NULL; p = strtok(NULL, ": \t\r\n")) {
- int i;
- static char shellpath[256];
-
- if (sh != NULL) {
- sprintf(shellpath, "%s/%s", p, sh);
- if (access(shellpath, X_OK) == 0)
- return shellpath;
- } else
- for (i = 0; i < _UC_MAXSHELLS && shells[i] != NULL; i++) {
- sprintf(shellpath, "%s/%s", p, shells[i]);
- if (access(shellpath, X_OK) == 0)
- return shellpath;
- }
- }
- if (sh == NULL)
- errx(EX_OSFILE, "can't find shell `%s' in shell paths", sh);
- errx(EX_CONFIG, "no default shell available or defined");
- return NULL;
- }
-}
-
-
-static char *
-pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell)
-{
- char *sh = newshell;
- struct carg *arg = getarg(args, 's');
-
- if (newshell == NULL && arg != NULL)
- sh = arg->val;
- return shell_path(cnf->shelldir, cnf->shells, sh ? sh : cnf->shell_default);
-}
-
-#define SALTSIZE 32
-
-static char const chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
-
-char *
-pw_pwcrypt(char *password)
-{
- int i;
- char salt[SALTSIZE + 1];
-
- static char buf[256];
-
- /*
- * Calculate a salt value
- */
- for (i = 0; i < SALTSIZE; i++)
- salt[i] = chars[arc4random_uniform(sizeof(chars) - 1)];
- salt[SALTSIZE] = '\0';
-
- return strcpy(buf, crypt(password, salt));
-}
-
-
-static char *
-pw_password(struct userconf * cnf, struct cargs * args, char const * user)
-{
- int i, l;
- char pwbuf[32];
-
- switch (cnf->default_password) {
- case -1: /* Random password */
- l = (arc4random() % 8 + 8); /* 8 - 16 chars */
- for (i = 0; i < l; i++)
- pwbuf[i] = chars[arc4random_uniform(sizeof(chars)-1)];
- pwbuf[i] = '\0';
-
- /*
- * We give this information back to the user
- */
- if (getarg(args, 'h') == NULL && getarg(args, 'H') == NULL &&
- getarg(args, 'N') == NULL) {
- if (isatty(STDOUT_FILENO))
- printf("Password for '%s' is: ", user);
- printf("%s\n", pwbuf);
- fflush(stdout);
- }
- break;
-
- case -2: /* No password at all! */
- return "";
-
- case 0: /* No login - default */
- default:
- return "*";
-
- case 1: /* user's name */
- strlcpy(pwbuf, user, sizeof(pwbuf));
- break;
- }
- return pw_pwcrypt(pwbuf);
-}
-
-
-static int
-print_user(struct passwd * pwd, int pretty, int v7)
-{
- if (!pretty) {
- char buf[_UC_MAXLINE];
-
- fmtpwentry(buf, pwd, v7 ? PWF_PASSWD : PWF_STANDARD);
- fputs(buf, stdout);
- } else {
- int j;
- char *p;
- struct group *grp = GETGRGID(pwd->pw_gid);
- char uname[60] = "User &", office[60] = "[None]",
- wphone[60] = "[None]", hphone[60] = "[None]";
- char acexpire[32] = "[None]", pwexpire[32] = "[None]";
- struct tm * tptr;
-
- if ((p = strtok(pwd->pw_gecos, ",")) != NULL) {
- strlcpy(uname, p, sizeof(uname));
- if ((p = strtok(NULL, ",")) != NULL) {
- strlcpy(office, p, sizeof(office));
- if ((p = strtok(NULL, ",")) != NULL) {
- strlcpy(wphone, p, sizeof(wphone));
- if ((p = strtok(NULL, "")) != NULL) {
- strlcpy(hphone, p,
- sizeof(hphone));
- }
- }
- }
- }
- /*
- * Handle '&' in gecos field
- */
- if ((p = strchr(uname, '&')) != NULL) {
- int l = strlen(pwd->pw_name);
- int m = strlen(p);
-
- memmove(p + l, p + 1, m);
- memmove(p, pwd->pw_name, l);
- *p = (char) toupper((unsigned char)*p);
- }
- if (pwd->pw_expire > (time_t)0 && (tptr = localtime(&pwd->pw_expire)) != NULL)
- strftime(acexpire, sizeof acexpire, "%c", tptr);
- if (pwd->pw_change > (time_t)0 && (tptr = localtime(&pwd->pw_change)) != NULL)
- strftime(pwexpire, sizeof pwexpire, "%c", tptr);
- printf("Login Name: %-15s #%-12ld Group: %-15s #%ld\n"
- " Full Name: %s\n"
- " Home: %-26.26s Class: %s\n"
- " Shell: %-26.26s Office: %s\n"
- "Work Phone: %-26.26s Home Phone: %s\n"
- "Acc Expire: %-26.26s Pwd Expire: %s\n",
- pwd->pw_name, (long) pwd->pw_uid,
- grp ? grp->gr_name : "(invalid)", (long) pwd->pw_gid,
- uname, pwd->pw_dir, pwd->pw_class,
- pwd->pw_shell, office, wphone, hphone,
- acexpire, pwexpire);
- SETGRENT();
- j = 0;
- while ((grp=GETGRENT()) != NULL)
- {
- int i = 0;
- while (grp->gr_mem[i] != NULL)
- {
- if (strcmp(grp->gr_mem[i], pwd->pw_name)==0)
- {
- printf(j++ == 0 ? " Groups: %s" : ",%s", grp->gr_name);
- break;
- }
- ++i;
- }
- }
- ENDGRENT();
- printf("%s", j ? "\n" : "");
- }
- return EXIT_SUCCESS;
-}
-
-char *
-pw_checkname(u_char *name, int gecos)
-{
- char showch[8];
- u_char const *badchars, *ch, *showtype;
- int reject;
-
- ch = name;
- reject = 0;
- if (gecos) {
- /* See if the name is valid as a gecos (comment) field. */
- badchars = ":!@";
- showtype = "gecos field";
- } else {
- /* See if the name is valid as a userid or group. */
- badchars = " ,\t:+&#%$^()!@~*?<>=|\\/\"";
- showtype = "userid/group name";
- /* Userids and groups can not have a leading '-'. */
- if (*ch == '-')
- reject = 1;
- }
- if (!reject) {
- while (*ch) {
- if (strchr(badchars, *ch) != NULL || *ch < ' ' ||
- *ch == 127) {
- reject = 1;
- break;
- }
- /* 8-bit characters are only allowed in GECOS fields */
- if (!gecos && (*ch & 0x80)) {
- reject = 1;
- break;
- }
- ch++;
- }
- }
- /*
- * A `$' is allowed as the final character for userids and groups,
- * mainly for the benefit of samba.
- */
- if (reject && !gecos) {
- if (*ch == '$' && *(ch + 1) == '\0') {
- reject = 0;
- ch++;
- }
- }
- if (reject) {
- snprintf(showch, sizeof(showch), (*ch >= ' ' && *ch < 127)
- ? "`%c'" : "0x%02x", *ch);
- errx(EX_DATAERR, "invalid character %s at position %d in %s",
- showch, (ch - name), showtype);
- }
- if (!gecos && (ch - name) > LOGNAMESIZE)
- errx(EX_DATAERR, "name too long `%s' (max is %d)", name,
- LOGNAMESIZE);
- return (char *)name;
-}
-
-
-static void
-rmat(uid_t uid)
-{
- DIR *d = opendir("/var/at/jobs");
-
- if (d != NULL) {
- struct dirent *e;
-
- while ((e = readdir(d)) != NULL) {
- struct stat st;
-
- if (strncmp(e->d_name, ".lock", 5) != 0 &&
- stat(e->d_name, &st) == 0 &&
- !S_ISDIR(st.st_mode) &&
- st.st_uid == uid) {
- char tmp[MAXPATHLEN];
-
- sprintf(tmp, "/usr/bin/atrm %s", e->d_name);
- system(tmp);
- }
- }
- closedir(d);
- }
-}
-
-static void
-rmopie(char const * name)
-{
- static const char etcopie[] = "/etc/opiekeys";
- FILE *fp = fopen(etcopie, "r+");
-
- if (fp != NULL) {
- char tmp[1024];
- off_t atofs = 0;
- int length = strlen(name);
-
- while (fgets(tmp, sizeof tmp, fp) != NULL) {
- if (strncmp(name, tmp, length) == 0 && tmp[length]==' ') {
- if (fseek(fp, atofs, SEEK_SET) == 0) {
- fwrite("#", 1, 1, fp); /* Comment username out */
- }
- break;
- }
- atofs = ftell(fp);
- }
- /*
- * If we got an error of any sort, don't update!
- */
- fclose(fp);
- }
-}
-
diff --git a/pw/pw_vpw.c b/pw/pw_vpw.c
deleted file mode 100644
index 473cbb6..0000000
--- a/pw/pw_vpw.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/param.h>
-
-#include "pwupd.h"
-
-static FILE * pwd_fp = NULL;
-
-void
-vendpwent(void)
-{
- if (pwd_fp != NULL) {
- fclose(pwd_fp);
- pwd_fp = NULL;
- }
-}
-
-void
-vsetpwent(void)
-{
- vendpwent();
-}
-
-static struct passwd *
-vnextpwent(char const * nam, uid_t uid, int doclose)
-{
- struct passwd * pw = NULL;
- static char pwtmp[1024];
-
- strlcpy(pwtmp, getpwpath(_MASTERPASSWD), sizeof(pwtmp));
-
- if (pwd_fp != NULL || (pwd_fp = fopen(pwtmp, "r")) != NULL) {
- int done = 0;
-
- static struct passwd pwd;
-
- while (!done && fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL)
- {
- int i, quickout = 0;
- char * q;
- char * p = strchr(pwtmp, '\n');
-
- if (p == NULL) {
- while (fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL && strchr(pwtmp, '\n')==NULL)
- ; /* Skip long lines */
- continue;
- }
-
- /* skip comments & empty lines */
- if (*pwtmp =='\n' || *pwtmp == '#')
- continue;
-
- i = 0;
- q = p = pwtmp;
- bzero(&pwd, sizeof pwd);
- while (!quickout && (p = strsep(&q, ":\n")) != NULL) {
- switch (i++)
- {
- case 0: /* username */
- pwd.pw_name = p;
- if (nam) {
- if (strcmp(nam, p) == 0)
- done = 1;
- else
- quickout = 1;
- }
- break;
- case 1: /* password */
- pwd.pw_passwd = p;
- break;
- case 2: /* uid */
- pwd.pw_uid = atoi(p);
- if (uid != (uid_t)-1) {
- if (uid == pwd.pw_uid)
- done = 1;
- else
- quickout = 1;
- }
- break;
- case 3: /* gid */
- pwd.pw_gid = atoi(p);
- break;
- case 4: /* class */
- if (nam == NULL && uid == (uid_t)-1)
- done = 1;
- pwd.pw_class = p;
- break;
- case 5: /* change */
- pwd.pw_change = (time_t)atol(p);
- break;
- case 6: /* expire */
- pwd.pw_expire = (time_t)atol(p);
- break;
- case 7: /* gecos */
- pwd.pw_gecos = p;
- break;
- case 8: /* directory */
- pwd.pw_dir = p;
- break;
- case 9: /* shell */
- pwd.pw_shell = p;
- break;
- }
- }
- }
- if (doclose)
- vendpwent();
- if (done && pwd.pw_name) {
- pw = &pwd;
-
- #define CKNULL(s) s = s ? s : ""
- CKNULL(pwd.pw_passwd);
- CKNULL(pwd.pw_class);
- CKNULL(pwd.pw_gecos);
- CKNULL(pwd.pw_dir);
- CKNULL(pwd.pw_shell);
- }
- }
- return pw;
-}
-
-struct passwd *
-vgetpwent(void)
-{
- return vnextpwent(NULL, -1, 0);
-}
-
-struct passwd *
-vgetpwuid(uid_t uid)
-{
- return vnextpwent(NULL, uid, 1);
-}
-
-struct passwd *
-vgetpwnam(const char * nam)
-{
- return vnextpwent(nam, -1, 1);
-}
-
-int vpwdb(char *arg, ...)
-{
- arg=arg;
- return 0;
-}
-
-
-
-static FILE * grp_fp = NULL;
-
-void
-vendgrent(void)
-{
- if (grp_fp != NULL) {
- fclose(grp_fp);
- grp_fp = NULL;
- }
-}
-
-RET_SETGRENT
-vsetgrent(void)
-{
- vendgrent();
-#if defined(__FreeBSD__)
- return 0;
-#endif
-}
-
-static struct group *
-vnextgrent(char const * nam, gid_t gid, int doclose)
-{
- struct group * gr = NULL;
-
- static char * grtmp = NULL;
- static int grlen = 0;
- static char ** mems = NULL;
- static int memlen = 0;
-
- extendline(&grtmp, &grlen, MAXPATHLEN);
- strlcpy(grtmp, getgrpath(_GROUP), MAXPATHLEN);
-
- if (grp_fp != NULL || (grp_fp = fopen(grtmp, "r")) != NULL) {
- int done = 0;
-
- static struct group grp;
-
- while (!done && fgets(grtmp, grlen, grp_fp) != NULL)
- {
- int i, quickout = 0;
- int mno = 0;
- char * q, * p;
- char * sep = ":\n";
-
- if ((p = strchr(grtmp, '\n')) == NULL) {
- int l;
- extendline(&grtmp, &grlen, grlen + PWBUFSZ);
- l = strlen(grtmp);
- if (fgets(grtmp + l, grlen - l, grp_fp) == NULL)
- break; /* No newline terminator on last line */
- }
- /* Skip comments and empty lines */
- if (*grtmp == '\n' || *grtmp == '#')
- continue;
- i = 0;
- q = p = grtmp;
- bzero(&grp, sizeof grp);
- extendarray(&mems, &memlen, 200);
- while (!quickout && (p = strsep(&q, sep)) != NULL) {
- switch (i++)
- {
- case 0: /* groupname */
- grp.gr_name = p;
- if (nam) {
- if (strcmp(nam, p) == 0)
- done = 1;
- else
- quickout = 1;
- }
- break;
- case 1: /* password */
- grp.gr_passwd = p;
- break;
- case 2: /* gid */
- grp.gr_gid = atoi(p);
- if (gid != (gid_t)-1) {
- if (gid == (gid_t)grp.gr_gid)
- done = 1;
- else
- quickout = 1;
- } else if (nam == NULL)
- done = 1;
- break;
- case 3:
- q = p;
- sep = ",\n";
- break;
- default:
- if (*p) {
- extendarray(&mems, &memlen, mno + 2);
- mems[mno++] = p;
- }
- break;
- }
- }
- grp.gr_mem = mems;
- mems[mno] = NULL;
- }
- if (doclose)
- vendgrent();
- if (done && grp.gr_name) {
- gr = &grp;
-
- CKNULL(grp.gr_passwd);
- }
- }
- return gr;
-}
-
-struct group *
-vgetgrent(void)
-{
- return vnextgrent(NULL, -1, 0);
-}
-
-
-struct group *
-vgetgrgid(gid_t gid)
-{
- return vnextgrent(NULL, gid, 1);
-}
-
-struct group *
-vgetgrnam(const char * nam)
-{
- return vnextgrent(nam, -1, 1);
-}
-
-int
-vgrdb(char *arg, ...)
-{
- arg=arg;
- return 0;
-}
-
diff --git a/pw/pwupd.c b/pw/pwupd.c
deleted file mode 100644
index cb8456d..0000000
--- a/pw/pwupd.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/wait.h>
-
-#include "pwupd.h"
-
-#define HAVE_PWDB_C 1
-#define HAVE_PWDB_U 1
-
-static char pathpwd[] = _PATH_PWD;
-static char * pwpath = pathpwd;
-
-int
-setpwdir(const char * dir)
-{
- if (dir == NULL)
- return -1;
- else {
- char * d = malloc(strlen(dir)+1);
- if (d == NULL)
- return -1;
- pwpath = strcpy(d, dir);
- }
- return 0;
-}
-
-char *
-getpwpath(char const * file)
-{
- static char pathbuf[MAXPATHLEN];
-
- snprintf(pathbuf, sizeof pathbuf, "%s/%s", pwpath, file);
- return pathbuf;
-}
-
-int
-pwdb(char *arg,...)
-{
- int i = 0;
- pid_t pid;
- va_list ap;
- char *args[10];
-
- args[i++] = _PATH_PWD_MKDB;
- va_start(ap, arg);
- while (i < 6 && arg != NULL) {
- args[i++] = arg;
- arg = va_arg(ap, char *);
- }
- if (pwpath != pathpwd) {
- args[i++] = "-d";
- args[i++] = pwpath;
- }
- args[i++] = getpwpath(_MASTERPASSWD);
- args[i] = NULL;
-
- if ((pid = fork()) == -1) /* Error (errno set) */
- i = errno;
- else if (pid == 0) { /* Child */
- execv(args[0], args);
- _exit(1);
- } else { /* Parent */
- waitpid(pid, &i, 0);
- if (WEXITSTATUS(i))
- i = EIO;
- }
- return i;
-}
-
-int
-fmtpwentry(char *buf, struct passwd * pwd, int type)
-{
- int l;
- char *pw;
-
- pw = (type == PWF_MASTER) ?
- ((pwd->pw_passwd == NULL) ? "" : pwd->pw_passwd) : "*";
-
- if (type == PWF_PASSWD)
- l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
- pwd->pw_name, (long) pwd->pw_uid, (long) pwd->pw_gid,
- pwd->pw_gecos ? pwd->pw_gecos : "User &",
- pwd->pw_dir, pwd->pw_shell);
- else
- l = sprintf(buf, "%s:%s:%ld:%ld:%s:%lu:%lu:%s:%s:%s\n",
- pwd->pw_name, pw, (long) pwd->pw_uid, (long) pwd->pw_gid,
- pwd->pw_class ? pwd->pw_class : "",
- (unsigned long) pwd->pw_change,
- (unsigned long) pwd->pw_expire,
- pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
- return l;
-}
-
-
-int
-fmtpwent(char *buf, struct passwd * pwd)
-{
- return fmtpwentry(buf, pwd, PWF_STANDARD);
-}
-
-static int
-pw_update(struct passwd * pwd, char const * user, int mode)
-{
- int rc = 0;
-
- ENDPWENT();
-
- /*
- * First, let's check the see if the database is alright
- * Note: -C is only available in FreeBSD 2.2 and above
- */
-#ifdef HAVE_PWDB_C
- rc = pwdb("-C", (char *)NULL); /* Check only */
- if (rc == 0) {
-#else
- { /* No -C */
-#endif
- char pfx[PWBUFSZ];
- char pwbuf[PWBUFSZ];
- int l = snprintf(pfx, PWBUFSZ, "%s:", user);
-#ifdef HAVE_PWDB_U
- int isrename = pwd!=NULL && strcmp(user, pwd->pw_name);
-#endif
-
- /*
- * Update the passwd file first
- */
- if (pwd == NULL)
- *pwbuf = '\0';
- else
- fmtpwentry(pwbuf, pwd, PWF_PASSWD);
-
- if (l < 0)
- l = 0;
- rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode);
- if (rc == 0) {
-
- /*
- * Then the master.passwd file
- */
- if (pwd != NULL)
- fmtpwentry(pwbuf, pwd, PWF_MASTER);
- rc = fileupdate(getpwpath(_MASTERPASSWD), 0600, pwbuf, pfx, l, mode);
- if (rc == 0) {
-#ifdef HAVE_PWDB_U
- if (mode == UPD_DELETE || isrename)
-#endif
- rc = pwdb(NULL);
-#ifdef HAVE_PWDB_U
- else
- rc = pwdb("-u", user, (char *)NULL);
-#endif
- }
- }
- }
- return rc;
-}
-
-int
-addpwent(struct passwd * pwd)
-{
- return pw_update(pwd, pwd->pw_name, UPD_CREATE);
-}
-
-int
-chgpwent(char const * login, struct passwd * pwd)
-{
- return pw_update(pwd, login, UPD_REPLACE);
-}
-
-int
-delpwent(struct passwd * pwd)
-{
- return pw_update(NULL, pwd->pw_name, UPD_DELETE);
-}
diff --git a/pw/pwupd.h b/pw/pwupd.h
deleted file mode 100644
index 7289065..0000000
--- a/pw/pwupd.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _PWUPD_H_
-#define _PWUPD_H_
-
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <sys/cdefs.h>
-
-#if defined(__FreeBSD__)
-#define RET_SETGRENT int
-#else
-#define RET_SETGRENT void
-#endif
-
-enum updtype
-{
- UPD_DELETE = -1,
- UPD_CREATE = 0,
- UPD_REPLACE = 1
-};
-
-__BEGIN_DECLS
-int fileupdate(char const * fname, mode_t fm, char const * nline, char const * pfx, int pfxlen, int updmode);
-__END_DECLS
-
-enum pwdfmttype
-{
- PWF_STANDARD, /* MASTER format but with '*' as password */
- PWF_PASSWD, /* V7 format */
- PWF_GROUP = PWF_PASSWD,
- PWF_MASTER /* MASTER format with password */
-};
-
-struct pwf
-{
- int _altdir;
- void (*_setpwent)(void);
- void (*_endpwent)(void);
- struct passwd * (*_getpwent)(void);
- struct passwd * (*_getpwuid)(uid_t uid);
- struct passwd * (*_getpwnam)(const char * nam);
- int (*_pwdb)(char *arg, ...);
- RET_SETGRENT (*_setgrent)(void);
- void (*_endgrent)(void);
- struct group * (*_getgrent)(void);
- struct group * (*_getgrgid)(gid_t gid);
- struct group * (*_getgrnam)(const char * nam);
- int (*_grdb)(char *arg, ...);
-};
-
-extern struct pwf PWF;
-extern struct pwf VPWF;
-
-#define SETPWENT() PWF._setpwent()
-#define ENDPWENT() PWF._endpwent()
-#define GETPWENT() PWF._getpwent()
-#define GETPWUID(uid) PWF._getpwuid(uid)
-#define GETPWNAM(nam) PWF._getpwnam(nam)
-#define PWDB(args) PWF._pwdb(args)
-
-#define SETGRENT() PWF._setgrent()
-#define ENDGRENT() PWF._endgrent()
-#define GETGRENT() PWF._getgrent()
-#define GETGRGID(gid) PWF._getgrgid(gid)
-#define GETGRNAM(nam) PWF._getgrnam(nam)
-#define GRDB(args) PWF._grdb(args)
-
-#define PWALTDIR() PWF._altdir
-#ifndef _PATH_PWD
-#define _PATH_PWD "/etc"
-#endif
-#ifndef _GROUP
-#define _GROUP "group"
-#endif
-#ifndef _PASSWD
-#define _PASSWD "passwd"
-#endif
-#ifndef _MASTERPASSWD
-#define _MASTERPASSWD "master.passwd"
-#endif
-#ifndef _GROUP
-#define _GROUP "group"
-#endif
-
-__BEGIN_DECLS
-int addpwent(struct passwd * pwd);
-int delpwent(struct passwd * pwd);
-int chgpwent(char const * login, struct passwd * pwd);
-int fmtpwent(char *buf, struct passwd * pwd);
-int fmtpwentry(char *buf, struct passwd * pwd, int type);
-
-int setpwdir(const char * dir);
-char * getpwpath(char const * file);
-int pwdb(char *arg, ...);
-
-int addgrent(struct group * grp);
-int delgrent(struct group * grp);
-int chggrent(char const * name, struct group * grp);
-int fmtgrent(char **buf, int * buflen, struct group * grp);
-int fmtgrentry(char **buf, int * buflen, struct group * grp, int type);
-int editgroups(char *name, char **groups);
-
-int setgrdir(const char * dir);
-char * getgrpath(const char *file);
-int grdb(char *arg, ...);
-
-void vsetpwent(void);
-void vendpwent(void);
-struct passwd * vgetpwent(void);
-struct passwd * vgetpwuid(uid_t uid);
-struct passwd * vgetpwnam(const char * nam);
-struct passwd * vgetpwent(void);
-int vpwdb(char *arg, ...);
-
-struct group * vgetgrent(void);
-struct group * vgetgrgid(gid_t gid);
-struct group * vgetgrnam(const char * nam);
-struct group * vgetgrent(void);
-int vgrdb(char *arg, ...);
-RET_SETGRENT vsetgrent(void);
-void vendgrent(void);
-
-void copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid);
-void rm_r(char const * dir, uid_t uid);
-int extendline(char **buf, int *buflen, int needed);
-int extendarray(char ***buf, int *buflen, int needed);
-__END_DECLS
-
-#define PWBUFSZ 1024
-
-#endif /* !_PWUPD_H */
diff --git a/pw/rm_r.c b/pw/rm_r.c
deleted file mode 100644
index 4ad590b..0000000
--- a/pw/rm_r.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-
- * Copyright (C) 1996
- * David L. Nugent. 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 DAVID L. NUGENT 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 DAVID L. NUGENT 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 lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <dirent.h>
-
-#include "pwupd.h"
-
-void
-rm_r(char const * dir, uid_t uid)
-{
- DIR *d = opendir(dir);
-
- if (d != NULL) {
- struct dirent *e;
- struct stat st;
- char file[MAXPATHLEN];
-
- while ((e = readdir(d)) != NULL) {
- if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0) {
- sprintf(file, "%s/%s", dir, e->d_name);
- if (lstat(file, &st) == 0) { /* Need symlinks, not
- * linked file */
- if (S_ISDIR(st.st_mode)) /* Directory - recurse */
- rm_r(file, uid);
- else {
- if (S_ISLNK(st.st_mode) || st.st_uid == uid)
- remove(file);
- }
- }
- }
- }
- closedir(d);
- if (lstat(dir, &st) == 0) {
- if (S_ISLNK(st.st_mode))
- remove(dir);
- else if (st.st_uid == uid)
- rmdir(dir);
- }
- }
-}