aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/ChangeLog19
-rw-r--r--src/util/Makefile.in2
-rw-r--r--src/util/db2/ChangeLog4
-rw-r--r--src/util/db2/hash/dbm.c5
-rw-r--r--src/util/et/ChangeLog48
-rw-r--r--src/util/et/com_err.c11
-rw-r--r--src/util/et/com_err.h6
-rw-r--r--src/util/et/error_message.c16
-rw-r--r--src/util/et/et.pbexp10
-rw-r--r--src/util/et/et_c.awk4
-rw-r--r--src/util/et/et_c.pl (renamed from src/util/et/et_c.perl)8
-rw-r--r--src/util/et/et_h.awk6
-rw-r--r--src/util/et/et_h.pl (renamed from src/util/et/et_h.perl)16
-rw-r--r--src/util/makeshlib.sh8
-rw-r--r--src/util/mkrel34
-rw-r--r--src/util/profile/ChangeLog29
-rw-r--r--src/util/profile/Makefile.in2
-rw-r--r--src/util/profile/krb5.conf8
-rw-r--r--src/util/profile/prof_err.et6
-rw-r--r--src/util/profile/prof_parse.c6
-rw-r--r--src/util/profile/profile.pbexp32
-rw-r--r--src/util/pty/ChangeLog166
-rw-r--r--src/util/pty/Makefile.in12
-rw-r--r--src/util/pty/cleanup.c6
-rw-r--r--src/util/pty/configure.in163
-rw-r--r--src/util/pty/dump-utmp.c362
-rw-r--r--src/util/pty/getpty.c17
-rw-r--r--src/util/pty/libpty.h24
-rw-r--r--src/util/pty/logwtmp.c93
-rw-r--r--src/util/pty/open_ctty.c44
-rw-r--r--src/util/pty/open_slave.c108
-rw-r--r--src/util/pty/pty-int.h28
-rw-r--r--src/util/pty/pty_paranoia.c650
-rw-r--r--src/util/pty/sane_hostname.c4
-rw-r--r--src/util/pty/update_utmp.c781
-rw-r--r--src/util/pty/update_wtmp.c141
-rw-r--r--src/util/pty/void_assoc.c37
-rw-r--r--src/util/ss/ChangeLog8
-rw-r--r--src/util/ss/help.c14
-rw-r--r--src/util/ss/list_rqs.c13
-rw-r--r--src/util/ss/mk_cmds.c5
-rw-r--r--src/util/ss/utils.c11
42 files changed, 2393 insertions, 574 deletions
diff --git a/src/util/ChangeLog b/src/util/ChangeLog
index 3862b25..39731b1 100644
--- a/src/util/ChangeLog
+++ b/src/util/ChangeLog
@@ -1,3 +1,22 @@
+2001-02-21 Tom Yu <tlyu@mit.edu>
+
+ * mkrel: When generating multiple tarballs, also generate a
+ consolidated tarball.
+
+2001-02-06 Tom Yu <tlyu@mit.edu>
+
+ * mkrel: Default to making a single tarball.
+
+2001-01-28 Tom Yu <tlyu@mit.edu>
+
+ * Makefile.in (all-prerecurse): Move aix.bincmds rule to
+ all-prerecurse so it gets built before the subdirectories of
+ src/util.
+
+ * makeshlib.sh: Use the linker flag -berok so that unresolved
+ symbols don't turn into link-time errors for building shared libs
+ on AIX.
+
1999-10-26 Tom Yu <tlyu@mit.edu>
* Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
diff --git a/src/util/Makefile.in b/src/util/Makefile.in
index 3b4fd5d..f5d91d4 100644
--- a/src/util/Makefile.in
+++ b/src/util/Makefile.in
@@ -77,7 +77,7 @@ makeshlib: $(srcdir)/makeshlib.sh Makefile
#
# We only need this for AIX, but we generate it for all systems.
#
-all-unix:: aix.bincmds
+all-prerecurse:: aix.bincmds
aix.bincmds: Makefile
echo libpath $(KRB5_LIBDIR):`pwd`/$(TOPLIBD):/usr/lib:/lib >aix.bincmds
diff --git a/src/util/db2/ChangeLog b/src/util/db2/ChangeLog
index 7972728..9ce240a 100644
--- a/src/util/db2/ChangeLog
+++ b/src/util/db2/ChangeLog
@@ -1,3 +1,7 @@
+2000-05-01 Nalin Dahyabhai <nalin@redhat.com>
+
+ * hash/dbm.c (kdb2_dbm_open): Don't overflow buffer "path".
+
1999-08-15 Tom Yu <tlyu@mit.edu>
* README.NOT.SLEEPYCAT.DB: New file; pointer to README to
diff --git a/src/util/db2/hash/dbm.c b/src/util/db2/hash/dbm.c
index 50921de..aa96766 100644
--- a/src/util/db2/hash/dbm.c
+++ b/src/util/db2/hash/dbm.c
@@ -168,8 +168,9 @@ kdb2_dbm_open(file, flags, mode)
info.cachesize = 0;
info.hash = NULL;
info.lorder = 0;
- (void)strcpy(path, file);
- (void)strcat(path, DBM_SUFFIX);
+ (void)strncpy(path, file, sizeof(path) - 1);
+ path[sizeof(path) - 1] = '\0';
+ (void)strncat(path, DBM_SUFFIX, sizeof(path) - 1 - strlen(path));
return ((DBM *)__hash_open(path, flags, mode, &info, 0));
}
diff --git a/src/util/et/ChangeLog b/src/util/et/ChangeLog
index 345416e..2cda2d7 100644
--- a/src/util/et/ChangeLog
+++ b/src/util/et/ChangeLog
@@ -1,3 +1,51 @@
+2001-10-31 Miro Jurisic <meeroh@mit.edu>
+
+ * et_c.awk, et_c.pl, et_h.awk, et_h.pl: Fixed the incorrect
+ #if defined(unix) ... which was accidentally reintroduced
+
+2001-10-31 Danilo Almeida <dalmeida@mit.edu>
+
+ * com_err.h: Windows should include <win-mac.h> as opposed
+ to <Kerberos5/win-mac.h>
+
+2001-10-29 Miro Jurisic <meeroh@mit.edu>
+ * pullup from krb5-1-2 branch after krb5-1-2-2-bp
+ * error_message.c: fixed busted parentheses
+ * error_message.c: call through to strerror on Mac OS X
+ * error_message.c: call through to ErrorLib on Mac OS X
+ * et.pbexp: export com_err() on Mac OS X
+ * error_massage.c: #include <KerberosSupport/ErrorLib.h> on Mac OS
+ * com_err.h: #include <Kerberos5/win-mac.h> on Mac OS
+ * et_c.awk, et_c.pl, et_h.awk, et_h.pl: Updated Mac OS #defines
+ and #includes for new header layout and Mac OS X frameworks
+
+2000-10-08 Miro Jurisic <meeroh@mit.edu>
+
+ * et_c.perl, et_h.perl:
+ Renamed to et_c.pl and et_h.pl because the extension is used
+ as a newline separator heuristic in MacPerl parser
+
+2000-10-08 Miro Jurisic <meeroh@mit.edu>
+
+ * et_c.perl, et_h.perl:
+ Removed #! from the first line to avoid confusing MacPerl
+
+2000-10-02 Alexandra Ellwood <lxs@mit.edu>
+
+ * com_err.h, error_message.c, et.pbexp, et_c.awk, et_h.awk:
+ conditionalized com_err so it doesn't need to export et_list
+ on Mac OS X
+
+2000-05-07 Miro Jurisic <meeroh@mit.edu>
+
+ * com_err.c (default_com_err_proc): use strncpy
+ where strncpy was meant (typo in Nalin's patch)
+
+2000-05-01 Nalin Dahyabhai <nalin@redhat.com>
+
+ * com_err.c (default_com_err_proc) [_MSDOS || _WIN32 ||
+ macintosh]: Don't overflow buffer "errbuf".
+
2000-02-23 Ken Raeburn <raeburn@mit.edu>
* Makefile.in (com_err.o): Depends on com_err.c.
diff --git a/src/util/et/com_err.c b/src/util/et/com_err.c
index 31da130..7bb0810 100644
--- a/src/util/et/com_err.c
+++ b/src/util/et/com_err.c
@@ -50,15 +50,18 @@ static void default_com_err_proc(whoami, code, fmt, ap)
char errbuf[1024] = "";
if (whoami) {
- strcat (errbuf, whoami);
- strcat (errbuf, ": ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ strncat (errbuf, whoami, sizeof(errbuf) - 1 - strlen(errbuf));
+ strncat (errbuf, ": ", sizeof(errbuf) - 1 - strlen(errbuf));
}
if (code) {
- strcat (errbuf, error_message(code));
- strcat (errbuf, " ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ strncat (errbuf, error_message(code), sizeof(errbuf) - 1 - strlen(errbuf));
+ strncat (errbuf, " ", sizeof(errbuf) - 1 - strlen(errbuf));
}
if (fmt)
vsprintf (errbuf + strlen (errbuf), fmt, ap);
+ errbuf[sizeof(errbuf) - 1] = '\0';
#ifdef macintosh
MacMessageBox(errbuf);
diff --git a/src/util/et/com_err.h b/src/util/et/com_err.h
index 7a8858b..f1acb70 100644
--- a/src/util/et/com_err.h
+++ b/src/util/et/com_err.h
@@ -13,7 +13,11 @@
#ifndef __COM_ERR_H
#if defined(_MSDOS) || defined(_WIN32) || defined(macintosh)
+#ifdef _WIN32
#include <win-mac.h>
+#else
+#include <Kerberos5/win-mac.h>
+#endif
#if defined(macintosh) && defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
#pragma import on
#endif
@@ -80,7 +84,7 @@ KRB5_DLLIMP extern errcode_t KRB5_CALLCONV add_error_table
KRB5_DLLIMP extern errcode_t KRB5_CALLCONV remove_error_table
ET_P((const struct error_table FAR *));
-#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh)
+#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh) && !defined(__MACH__)
/*
* The display routine should be application specific. A global hook,
* may cause inappropriate display procedures to be called between
diff --git a/src/util/et/error_message.c b/src/util/et/error_message.c
index b4a0537..4a5de74 100644
--- a/src/util/et/error_message.c
+++ b/src/util/et/error_message.c
@@ -27,8 +27,9 @@
#include "com_err.h"
#include "error_table.h"
-#ifdef macintosh
-#include <ErrorLib.h>
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+ #include <KerberosSupport/KerberosSupport.h>
+ #include <KerberosSupport/ErrorLib.h>
#endif
#if defined(_MSDOS) || defined(_WIN32)
@@ -48,7 +49,7 @@ extern const int sys_nerr;
static char buffer[ET_EBUFSIZ];
-#if (defined(_MSDOS) || defined(_WIN32) || defined(macintosh))
+#if (defined(_MSDOS) || defined(_WIN32) || defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)))
static struct et_list * _et_list = (struct et_list *) NULL;
#else
/* Old interface compatibility */
@@ -150,12 +151,19 @@ KRB5_DLLIMP const char FAR * KRB5_CALLCONV error_message(code)
oops:
-#if defined(macintosh)
+#if TARGET_OS_MAC
{
/* This may be a Mac OS Toolbox error or an MIT Support Library Error. Ask ErrorLib */
if (GetErrorLongString(code, buffer, ET_EBUFSIZ - 1) == noErr) {
return buffer;
}
+
+#if TARGET_API_MAC_OSX
+ /* ComErr and ErrorLib don't know about this error, ask the system */
+ /* Of course there's no way to tell if it knew what error it got */
+ return (strerror (code));
+#endif
+
}
#endif
diff --git a/src/util/et/et.pbexp b/src/util/et/et.pbexp
new file mode 100644
index 0000000..3109761
--- /dev/null
+++ b/src/util/et/et.pbexp
@@ -0,0 +1,10 @@
+#
+# comerr library Macintosh export file
+#
+# $Header$
+
+_com_err
+_com_err_va
+_error_message
+_add_error_table
+_remove_error_table
diff --git a/src/util/et/et_c.awk b/src/util/et/et_c.awk
index 94b258f..c9ecc6f 100644
--- a/src/util/et/et_c.awk
+++ b/src/util/et/et_c.awk
@@ -209,14 +209,14 @@ END {
tab_base_low, table_item_count) > outfile
}
print "" > outfile
- print "#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh)" > outfile
+ print "#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh) && !(defined(__MACH__) && defined(__APPLE__))" > outfile
print "struct et_list {" > outfile
print " struct et_list *next;" > outfile
print " const struct error_table * table;" > outfile
print "};" > outfile
print "extern struct et_list *_et_list;" > outfile
print "static struct et_list link = { 0, 0 };" > outfile
- print "void initialize_" table_name "_error_table (NOARGS) {" > outfile
+ print "void initialize_" table_name "_error_table (NOARGS) {" > outfile
print " if (!link.table) {" > outfile
print " link.next = _et_list;" > outfile
print " link.table = &et_" table_name "_error_table;" > outfile
diff --git a/src/util/et/et_c.perl b/src/util/et/et_c.pl
index 6af7179..83bce3b 100644
--- a/src/util/et/et_c.perl
+++ b/src/util/et/et_c.pl
@@ -1,9 +1,3 @@
-#!/afs/athena/contrib/perl5/p
-eval 'exec /afs/athena/contrib/perl5/arch/sun4x_55/bin/perl -S $0 ${1+"$@"}'
- if $running_under_some_shell;
- # this emulates #! processing on NIH machines.
- # (remove #! line above if indigestible)
-
eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
# process any FOO=bar switches
@@ -279,7 +273,7 @@ else {
&Pick('>', $outfile) &&
(print $fh '');
&Pick('>', $outfile) &&
- (print $fh '#if defined(unix) || defined(_AIX)');
+ (print $fh '#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh) && !(defined(__MACH__) && defined(__APPLE__))');
&Pick('>', $outfile) &&
(print $fh 'struct et_list {');
&Pick('>', $outfile) &&
diff --git a/src/util/et/et_h.awk b/src/util/et/et_h.awk
index 2521886..2ce75bf 100644
--- a/src/util/et/et_h.awk
+++ b/src/util/et/et_h.awk
@@ -111,7 +111,11 @@ c2n["_"]=63
print " * This file is automatically generated; please do not edit it." > outfile
print " */" > outfile
print "" > outfile
+ print "#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))" > outfile
+ print "#include <KerberosComErr/KerberosComErr.h>" > outfile
+ print "#else" > outfile
print "#include <com_err.h>" > outfile
+ print "#endif" > outfile
print "" > outfile
}
@@ -148,7 +152,7 @@ END {
print "" > outfile
print "extern struct error_table et_" table_name "_error_table;" > outfile
print "" > outfile
- print "#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh)" > outfile
+ print "#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh) && !(defined(__MACH__) && defined(__APPLE__))" > outfile
print "/* for compatibility with older versions... */" > outfile
print "extern void initialize_" table_name "_error_table ();" > outfile
print "#define init_" table_name "_err_tbl initialize_" table_name "_error_table" > outfile
diff --git a/src/util/et/et_h.perl b/src/util/et/et_h.pl
index b477faf..a5d5507 100644
--- a/src/util/et/et_h.perl
+++ b/src/util/et/et_h.pl
@@ -1,9 +1,3 @@
-#!/afs/athena/contrib/perl5/p
-eval 'exec /afs/athena/contrib/perl5/arch/sun4x_55/bin/perl -S $0 ${1+"$@"}'
- if $running_under_some_shell;
- # this emulates #! processing on NIH machines.
- # (remove #! line above if indigestible)
-
eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
# process any FOO=bar switches
@@ -138,8 +132,16 @@ line: while (<>) {
&Pick('>', $outfile) &&
(print $fh '');
&Pick('>', $outfile) &&
+ (print $fh '#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))');
+ &Pick('>', $outfile) &&
+ (print $fh '#include <KerberosComErr/KerberosComErr.h>');
+ &Pick('>', $outfile) &&
+ (print $fh '#else');
+ &Pick('>', $outfile) &&
(print $fh '#include <com_err.h>');
&Pick('>', $outfile) &&
+ (print $fh '#endif');
+ &Pick('>', $outfile) &&
(print $fh '');
}
@@ -192,7 +194,7 @@ else {
&Pick('>', $outfile) &&
(print $fh '');
&Pick('>', $outfile) &&
- (print $fh '#if defined(unix) || defined(_AIX)');
+ (print $fh '#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh) && !(defined(__MACH__) && defined(__APPLE__))');
&Pick('>', $outfile) &&
(print $fh '/* for compatibility with older versions... */');
&Pick('>', $outfile) &&
diff --git a/src/util/makeshlib.sh b/src/util/makeshlib.sh
index ec485ca..303c0ce 100644
--- a/src/util/makeshlib.sh
+++ b/src/util/makeshlib.sh
@@ -38,16 +38,14 @@ case $host in
stat=$?
if [ $stat -eq 0 ] ; then
if test "$HAVE_GCC" = "yes" ; then
-
-
- $CC -o shr.o.$version $library -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:${library}.syms $LDFLAGS -lc
+ $CC -o shr.o.$version $library -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:${library}.syms -Xlinker -berok $LDFLAGS -lc
else
# Pull in by explicit pathname so we don't get gnu ld if
# installed (it could be even if we chose not to use gcc).
# Better still would be to do this through $CC -- how do
# we get crt0.o left out?
- echo /bin/ld -o shr.o.$version $library -H512 -T512 -bnoentry -bM:SRE $LDFLAGS -bgcbypass:1 -bnodelcsect -bE:${library}.syms $libdirfl $liblist -lc
- /bin/ld -o shr.o.$version $library -H512 -T512 -bnoentry -bM:SRE $LDFLAGS -bgcbypass:1 -bnodelcsect -bE:${library}.syms -lc
+ echo /bin/ld -o shr.o.$version $library -H512 -T512 -bnoentry -bM:SRE $LDFLAGS -bgcbypass:1 -bnodelcsect -bE:${library}.syms -berok $libdirfl $liblist -lc
+ /bin/ld -o shr.o.$version $library -H512 -T512 -bnoentry -bM:SRE $LDFLAGS -bgcbypass:1 -bnodelcsect -bE:${library}.syms -berok -lc
fi
stat=$?
if [ $stat -eq 0 ] ; then
diff --git a/src/util/mkrel b/src/util/mkrel
index e534a47..a086450 100644
--- a/src/util/mkrel
+++ b/src/util/mkrel
@@ -3,12 +3,15 @@ repository=:kserver:cvs.mit.edu:/cvs/krbdev
dodoc=t
dosrc=t
checkout=t
+multitar=nil
while test $# -gt 2; do
case $1 in
--srconly)
dodoc=nil;;
--doconly)
dosrc=nil;;
+ --multi*)
+ multitar=t;;
--repository)
shift; repository=$1;;
--nocheckout)
@@ -136,22 +139,25 @@ fi
echo "Generating tarfiles..."
GZIP=-9; export GZIP
-if test $dosrc = t; then
- gtar --exclude $reldir/src/lib/crypto \
- --exclude $reldir/src/lib/des425 \
- --exclude $reldir/doc \
- -zcf ${reldir}.src.tar.gz $reldir
-
- gtar zcf ${reldir}.crypto.tar.gz \
- $reldir/src/lib/crypto \
- $reldir/src/lib/des425
-fi
-
-if test $dodoc = t; then
- gtar zcf ${reldir}.doc.tar.gz $reldir/doc $reldir/README
+if test $multitar = t; then
+ if test $dosrc = t; then
+ gtar --exclude $reldir/src/lib/crypto \
+ --exclude $reldir/src/lib/des425 \
+ --exclude $reldir/doc \
+ -zcf ${reldir}.src.tar.gz $reldir
+
+ gtar zcf ${reldir}.crypto.tar.gz \
+ $reldir/src/lib/crypto \
+ $reldir/src/lib/des425
+ fi
+ if test $dodoc = t; then
+ gtar zcf ${reldir}.doc.tar.gz $reldir/doc $reldir/README
+ fi
+ ls -l ${reldir}.*.tar.gz
fi
-ls -l ${reldir}.*.tar.gz
+gtar zcf ${reldir}.tar.gz $reldir
+ls -l ${reldir}.tar.gz
echo "Done."
diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog
index 172d7ac..0139378 100644
--- a/src/util/profile/ChangeLog
+++ b/src/util/profile/ChangeLog
@@ -1,3 +1,32 @@
+2001-11-05 Tom Yu <tlyu@mit.edu>
+
+ * Makefile.in (LIBMINOR): Bump due to error table changes.
+
+2001-09-25 Ken Raeburn <raeburn@mit.edu>
+
+ * prof_err.et (PROF_BAD_BOOLEAN, PROF_BAD_INTEGER): New error
+ codes.
+
+2001-02-02 Tom Yu <tlyu@mit.edu>
+
+ * krb5.conf: Test with trailing whitespace on "default_realm"
+ line. [pullup from trunk]
+
+ * krb5.conf: Test with a space after ']' and '{' [pullup from trunk]
+
+ * prof_parse.c (parse_std_line): Spaces after '{' or ']' should
+ not be a fatal error. This is a common lossage in krb5.conf files.
+ [pullup from trunk]
+
+2000-10-7 Miro Jurisic <meeroh@mit.edu>
+
+ * et.pbexp: Added the Mach-O initializer function
+
+2000-10-7 Miro Jurisic <meeroh@mit.edu>
+
+ * et.pbexp: Added the Mac OS X export file (hopefully temporary,
+ until Apple fixes their tools to use the same format as Mac OS 9)
+
1999-10-26 Tom Yu <tlyu@mit.edu>
* Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
diff --git a/src/util/profile/Makefile.in b/src/util/profile/Makefile.in
index 3955ca8..fa3f6db 100644
--- a/src/util/profile/Makefile.in
+++ b/src/util/profile/Makefile.in
@@ -40,7 +40,7 @@ MLIBS = -lcom_err $(GEN_LIB)
LIB=profile
LIBMAJOR=1
-LIBMINOR=0
+LIBMINOR=1
SHLIB_EXPDEPS = $(TOPLIBD)/libcom_err$(SHLIBEXT)
SHLIB_EXPLIBS = -lcom_err
SHLIB_DIRS = -L$(TOPLIBD)
diff --git a/src/util/profile/krb5.conf b/src/util/profile/krb5.conf
index 01eb66c..19c59c6 100644
--- a/src/util/profile/krb5.conf
+++ b/src/util/profile/krb5.conf
@@ -1,5 +1,5 @@
[libdefaults]
- default_realm = ATHENA.MIT.EDU
+ default_realm = ATHENA.MIT.EDU
default_tgs_enctypes = des-cbc-crc
default_tkt_enctypes = des-cbc-crc
krb4_config = /etc/athena/krb.conf
@@ -8,8 +8,8 @@
kdc_timesync = 1
ccache_type = 4
-[realms]
- ATHENA.MIT.EDU = {
+[realms]
+ ATHENA.MIT.EDU = {
# kdc = kerberos-2000.mit.edu
kdc = kerberos.mit.edu:88
kdc = kerberos-1.mit.edu:88
@@ -17,7 +17,7 @@
kdc = kerberos-3.mit.edu:88
admin_server = kerberos.mit.edu
default_domain = mit.edu
- }
+ }
MEDIA-LAB.MIT.EDU = {
kdc = kerberos.media.mit.edu
admin_server = kerberos.media.mit.edu
diff --git a/src/util/profile/prof_err.et b/src/util/profile/prof_err.et
index e6e35db..dc248f4 100644
--- a/src/util/profile/prof_err.et
+++ b/src/util/profile/prof_err.et
@@ -54,4 +54,10 @@ error_code PROF_FAIL_OPEN, "Couldn't open profile file"
#
error_code PROF_EXISTS, "Section already exists"
+#
+# generated by prof_get.c
+#
+error_code PROF_BAD_BOOLEAN, "Invalid boolean value"
+error_code PROF_BAD_INTEGER, "Invalid integer value"
+
end
diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c
index 0e3cffe..7e8bcb8 100644
--- a/src/util/profile/prof_parse.c
+++ b/src/util/profile/prof_parse.c
@@ -130,6 +130,10 @@ static errcode_t parse_std_line(line, state)
profile_make_node_final(state->current_section);
cp++;
}
+ /*
+ * A space after ']' should not be fatal
+ */
+ cp = skip_over_blanks(cp);
if (*cp)
return PROF_SECTION_SYNTAX;
return 0;
@@ -169,7 +173,7 @@ static errcode_t parse_std_line(line, state)
} else if (value[0] == 0) {
do_subsection++;
state->state = STATE_GET_OBRACE;
- } else if (value[0] == '{' && value[1] == 0)
+ } else if (value[0] == '{' && *(skip_over_blanks(value+1)) == 0)
do_subsection++;
else {
cp = value + strlen(value) - 1;
diff --git a/src/util/profile/profile.pbexp b/src/util/profile/profile.pbexp
new file mode 100644
index 0000000..10e9ba4
--- /dev/null
+++ b/src/util/profile/profile.pbexp
@@ -0,0 +1,32 @@
+#
+# _profile library Macintosh export file
+#
+# $Header$
+
+___InitializeProfileLib
+
+_profile_init
+_profile_init_path
+_profile_flush
+_profile_abandon
+_profile_release
+_profile_get_values
+_profile_free_list
+_profile_get_string
+_profile_get_integer
+_profile_get_relation_names
+_profile_get_subsection_names
+_profile_iterator_create
+_profile_iterator_free
+_profile_iterator
+_profile_release_string
+_profile_update_relation
+_profile_clear_relation
+_profile_rename_section
+_profile_add_relation
+
+### Temporary -- DO NOT USE
+
+_profile_ser_internalize
+_profile_ser_externalize
+_profile_ser_size
diff --git a/src/util/pty/ChangeLog b/src/util/pty/ChangeLog
index ff815b7..3dac1a3 100644
--- a/src/util/pty/ChangeLog
+++ b/src/util/pty/ChangeLog
@@ -1,3 +1,169 @@
+2001-11-28 Tom Yu <tlyu@mit.edu>
+
+ * update_utmp.c (PTY_GETUTXENT): Fix typo. Thanks to Shawn
+ Stepper. [fixes krb5-build/1020]
+
+2001-11-19 Tom Yu <tlyu@mit.edu>
+
+ * update_utmp.c (pty_update_utmp): Patch from Garry Zacheiss to
+ kludge around cases where we need to use more than 2 characters of
+ LINE in order to avoid conflicts in UT_ID.
+
+2001-11-05 Tom Yu <tlyu@mit.edu>
+
+ * Makefile.in (LIBMINOR): Bump due to changes to internals.
+
+2001-09-25 Tom Yu <tlyu@mit.edu>
+
+ * pty-int.h: Fix up botched merge: cause prototypes for
+ ptyint_update_wtmp{,x} to be correct.
+
+2001-09-07 Tom Yu <tlyu@mit.edu>
+
+ * update_utmp.c (pty_update_utmp): Remember to chop off leading
+ "/dev/" for the non-sysV case. Handle lseek() returning non-zero
+ yet non-negative values (it usually does... :-), so that we can
+ actually write somewhere not at the beginning of the utmp file if
+ necessary.
+
+ * update_utmp.c (pty_update_utmp): Don't copy host if it's a null
+ pointer.
+
+ * dump-utmp.c (print_ut): Use size of ut_name field, not ut_user,
+ which may not exist, for width when printing ut_name field value.
+ Specify width when printing hostname, it may be unterminated.
+ (main): Move utp and utxp declarations closer to their usages, and
+ make both conditionalized so they're not declared if they're not
+ used.
+
+ * getpty.c: Make pty_getpty() into ptyint_getpty_ext(), which has
+ an extra argument that determines whether to call grantpt() and
+ unlockpt() on systems that support it. The new pty_getpty() will
+ simply call the extended version. This is to support some
+ wackiness needed by pty_paranoia.c tests.
+
+ * pty-int.h: Add prototype for ptyint_getpty_ext().
+
+ * pty_paranoia.c: Add rant about ptys and quirks therein. Needs
+ to be updated somewhat. Add some more paranoia for the case where
+ we actually succeed in opening the slave of a closed master and
+ then succeed in opening the same master. This program will get
+ rewritten at some point to actually see what things result in EOFs
+ and under what conditions data will actually get passed between
+ master and slave.
+
+ * pty_paranoia.c: New file; do many paranoid checks about ctty
+ handling by the pty drivers.
+
+ * Makefile.in: Add rules for pty_paranoia and check-paranoia,
+ which runs pty_paranoia.
+
+ * configure.in: Define REVOKE_NEEDS_OPEN for Tru64. Add support
+ for program building and run flags for the sake of pty_paranoia.
+
+ * open_slave.c: Fix somewhat; AIX doesn't like opening the ctty
+ twice, so only do initial open if we special-case it in
+ configure.in, e.g. for Tru64.
+
+ * logwtmp.c: Delete code under "#if 0". Fix reversed test for
+ loggingin. Don't forget to set the ut_tv or ut_time for the
+ entry.
+
+ * update_utmp.c: Update rant about Tru64; remove fetching of
+ ut_user from old entry. The existence of the old ut_user in the
+ logout entry in wtmp was confusing last.
+
+ * cleanup.c: Call update_utmp() with the correct pid to assist in
+ finding the old utmp entry.
+
+ * open_ctty.c: Reformat somewhat and revise comment.
+
+ * open_slave.c: Rework significantly. Primarily, keep a fd open
+ to the slave if we need to reopen the slave device following
+ vhangup() or revoke(), to accommodate various OS quirks.
+
+ * update_utmp.c: Revise history section somewhat to document more
+ HP-UX brokenness. Search via ut_pid before searching via
+ ut_line. Copy stuff around because entuxent() will clobber some
+ things.
+
+ * void_assoc.c: Revise comment and reformat somewhat.
+
+ * open_slave.c (pty_open_slave): If revoke() present on system but
+ VHANG_FIRST is not defined, declare local variable.
+
+ * dump-utmp.c: Fix some off-by-one errors. Handle cases where we
+ have utmpname() but not utmpname().
+
+ * pty-int.h: Fix typo; VHANG_first -> VHANG_FIRST.
+
+ * open_slave.c (pty_open_slave): Add workaround for Tru64 v5.0,
+ since its revoke() will fail if the slave isn't open already.
+
+ * cleanup.c (pty_cleanup): Delcare local variable only if
+ VHANG_LAST defined.
+
+ * logwtmp.c (pty_logwtmp): Only declare local variables if
+ logwtmp() not available on system.
+
+ * update_utmp.c (pty_update_utmp): Fix typo (OWRONLY ->
+ O_WRONLY).
+
+ * update_wtmp.c (ptyint_update_wtmpx): Add missing semi-colon in
+ code path if PTY_UTMP_E_EXIT and PTY_UTMPX_E_EXIT exist.
+
+ * configure.in: Fix some quoting of shell variables when passing
+ to "test". Reorder some logic in consistency checks to validate
+ cache variables against "yes" to account for possible empty or
+ nonexistent values.
+
+ * pty-int.h: Fix conditional prototype of update_wtmp().
+
+ * update_wtmp.c: Fix conditional compilation of update_wtmp() to
+ cover the case where we have setutxent() but don't have updwtmpx()
+ and WTMPX_FILE, as is the case on some Linux installations.
+
+ * configure.in(K5_CHECK_UT_MEMBER): Fix typo in previous; make
+ sure to include the correct header when checking structure
+ members.
+
+ * configure.in: Many changes to support the rewriting of the utmp
+ pieces of libpty. Do a large amount of checking for consistency
+ of various utmp and utmpx APIs as currently understood. See rant
+ in update_utmp.c.
+
+ * dump-utmp.c: Rewrite; now has capability to use utmp{,x}name()
+ to extract entries from utmp and utmpx files. Adjusts field
+ widths when printing as appropriate.
+
+ * libpty.h: Update call signature for update_utmp() and logwtmp();
+ make prototypes unconditional.
+
+ * logwtmp.c: Rewrite. Use pututline() or pututxline() API
+ whenever possible.
+
+ * pty-int.h: Update call signatures for update_wtmp{,x}(); make
+ prototypes unconditional.
+
+ * sane_hostname.c: Use the autoconf-correct macro names.
+
+ * update_utmp.c: Rewrite. Basically, use functions from the
+ pututline() or pututxline() API whenever possible, to avoid
+ lossage. Inserted large rant about the conjectured history of BSD
+ utmp, sysV utmp, and utmpx, as well as documentation about some
+ known quirks.
+
+ * update_wtmp.c: Rewrite. Add new function ptyint_logwtmpx() that
+ takes a utmpx rather than a utmp, so it can fail to lose data
+ converting to and from utmp.
+
+ [many pullups from trunk]
+
+2000-03-24 Ken Raeburn <raeburn@mit.edu>
+
+ * configure.in: Check for alpha*-dec-osf* instead of
+ alpha-dec-osf*.
+
1999-10-26 Tom Yu <tlyu@mit.edu>
* Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
diff --git a/src/util/pty/Makefile.in b/src/util/pty/Makefile.in
index 83d61dc..135fc7b 100644
--- a/src/util/pty/Makefile.in
+++ b/src/util/pty/Makefile.in
@@ -6,9 +6,13 @@ RELDIR=../util/pty
SED = sed
+KRB5_RUN_ENV= @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
LIB=pty
LIBMAJOR=1
-LIBMINOR=1
+LIBMINOR=2
STLIBOBJS= cleanup.o getpty.o init_slave.o open_ctty.o open_slave.o \
update_utmp.o update_wtmp.o vhangup.o void_assoc.o pty_err.o \
@@ -49,6 +53,12 @@ dump-utmp: dump-utmp.o
$(CC) $(LDFLAGS) -o dump-utmp dump-utmp.o
dump-utmp.o: dump-utmp.c
+pty_paranoia: pty_paranoia.o $(COM_ERR_DEPLIB) $(PTY_DEPLIB)
+ $(CC_LINK) -o pty_paranoia pty_paranoia.o $(PTY_LIB) $(COM_ERR_LIB) $(LIBS)
+
+check-paranoia: pty_paranoia
+ $(KRB5_RUN_ENV) ./pty_paranoia
+
install-unix:: install-libs
clean-unix::
diff --git a/src/util/pty/cleanup.c b/src/util/pty/cleanup.c
index cf0b451..87a77c1 100644
--- a/src/util/pty/cleanup.c
+++ b/src/util/pty/cleanup.c
@@ -32,10 +32,12 @@ long pty_cleanup (slave, pid, update_utmp)
int pid; /* May be zero for unknown.*/
int update_utmp;
{
+#ifdef VHANG_LAST
int retval, fd;
+#endif
if (update_utmp)
- pty_update_utmp(PTY_DEAD_PROCESS,0, "", slave, (char *)0, PTY_UTMP_USERNAME_VALID);
+ pty_update_utmp(PTY_DEAD_PROCESS, pid, "", slave, (char *)0, PTY_UTMP_USERNAME_VALID);
(void)chmod(slave, 0666);
(void)chown(slave, 0, 0);
@@ -79,7 +81,7 @@ long pty_cleanup (slave, pid, update_utmp)
return errno;
case 0:
ptyint_void_association();
- if ( retval = ( pty_open_ctty( slave, &fd )))
+ if ((retval = pty_open_ctty(slave, &fd)))
exit(retval);
ptyint_vhangup();
exit(0);
diff --git a/src/util/pty/configure.in b/src/util/pty/configure.in
index 398b182..27fac92 100644
--- a/src/util/pty/configure.in
+++ b/src/util/pty/configure.in
@@ -30,11 +30,13 @@ ac_cv_func_setsid=no # setsid doesn't do the right thing under Ultrix even thoug
# Moreover, strops.h trashes sys/ioctl.h
krb5_cv_has_streams=no
;;
-alpha-dec-osf*)
+alpha*-dec-osf*)
AC_CHECK_LIB(security,main,
AC_DEFINE(HAVE_SETLUID)
LOGINLIBS="$LOGINLIBS -lsecurity"
)
+ AC_MSG_RESULT(will open ctty prior to revoke due to OSF/1 lossage)
+ AC_DEFINE(REVOKE_NEEDS_OPEN)
;;
*-*-solaris*)
AC_DEFINE(PUSH_PTEM)
@@ -48,23 +50,144 @@ esac
dnl
AC_SUBST(LOGINLIBS)
dnl
-AC_CHECK_LIB(util,openpty, AC_DEFINE(HAVE_OPENPTY) LIBS="$LIBS -lutil")
+AC_CHECK_LIB(util,openpty, [AC_DEFINE(HAVE_OPENPTY) LIBS="$LIBS -lutil"])
AC_TYPE_MODE_T
AC_CHECK_TYPE(time_t, long)
-AC_FUNC_CHECK(strsave,AC_DEFINE(HAS_STRSAVE))
-AC_HAVE_FUNCS(getutent setreuid gettosbyname setsid ttyname line_push ptsname grantpt openpty logwtmp getutmpx)
-AC_CHECK_HEADERS(unistd.h stdlib.h string.h utmpx.h utmp.h sys/filio.h sys/sockio.h sys/label.h sys/tty.h ttyent.h lastlog.h sys/select.h sys/ptyvar.h)
+AC_CHECK_FUNC(strsave,[AC_DEFINE(HAS_STRSAVE)])
+AC_CHECK_FUNCS(setreuid gettosbyname setsid ttyname line_push ptsname grantpt openpty)
+AC_CHECK_HEADERS(unistd.h stdlib.h string.h pty.h sys/filio.h sys/sockio.h sys/label.h sys/tty.h ttyent.h lastlog.h sys/select.h sys/ptyvar.h)
AC_CHECK_HEADERS(sys/wait.h)
-AC_CHECK_FUNCS(waitpid updwtmpx)
+AC_CHECK_FUNCS(waitpid)
DECLARE_SYS_ERRLIST
KRB5_SIGTYPE
CHECK_SIGNALS
CHECK_SETJMP
CHECK_DIRENT
-AC_HEADER_CHECK(termios.h,AC_FUNC_CHECK(cfsetispeed,AC_DEFINE(POSIX_TERMIOS)))
-CHECK_UTMP
-dnl
-dnl
+AC_CHECK_HEADER(termios.h,AC_CHECK_FUNC(cfsetispeed,AC_DEFINE(POSIX_TERMIOS)))
+
+######################################################################
+#
+# utmp related hair here. There's lots of it.
+#
+
+AC_CHECK_HEADERS(utmp.h utmpx.h)
+AC_CHECK_FUNCS(setutent setutxent updwtmp updwtmpx logwtmp getutmp getutmpx)
+AC_CHECK_FUNCS(utmpname utmpxname)
+
+AC_DEFUN(K5_CHECK_UT_MEMBER,
+[AC_MSG_CHECKING([for $2 in struct $1])
+AC_CACHE_VAL([krb5_cv_struct_$1_$2],
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <$1.h>], [struct $1 u; u.$2;],
+eval "krb5_cv_struct_$1_$2=yes", eval "krb5_cv_struct_$1_$2=no")])
+if eval "test \"`echo '$krb5_cv_struct_'$1'_'$2`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ krb5_tr_ut=HAVE_STRUCT_`echo $1'_'$2 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ AC_DEFINE_UNQUOTED($krb5_tr_ut)
+else
+ AC_MSG_RESULT(no)
+fi])
+
+if test "$ac_cv_header_utmp_h" = yes; then
+ AC_MSG_RESULT(checking struct utmp members)
+ for krb5_mem in ut_host ut_syslen ut_addr ut_id ut_pid ut_type ut_exit; do
+ K5_CHECK_UT_MEMBER(utmp, $krb5_mem)
+ done
+fi
+
+if test "$ac_cv_header_utmpx_h" = yes; then
+ AC_MSG_RESULT(checking struct utmpx members)
+ for krb5_mem in ut_host ut_syslen ut_addr ut_id ut_pid ut_type ut_exit; do
+ K5_CHECK_UT_MEMBER(utmpx, $krb5_mem)
+ done
+fi
+
+AC_DEFUN(K5_CHECK_UT_EXIT_MEMBER,
+[AC_MSG_CHECKING([for ut_exit.$2 in struct $1])
+AC_CACHE_VAL([krb5_cv_struct_$1_ut_exit_$2],
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <$1.h>], [struct $1 u; u.ut_exit.$2;],
+eval "krb5_cv_struct_$1_ut_exit_$2=yes",
+eval "krb5_cv_struct_$1_ut_exit_$2=no")])
+if eval "test \"`echo '$krb5_cv_struct_'$1'_ut_exit_'$2`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], , :, [$3])
+else
+ AC_MSG_RESULT(no)
+ ifelse([$4], , :, [$4])
+fi])
+
+if test "$krb5_cv_struct_utmp_ut_exit" = yes; then
+ AC_MSG_RESULT(checking for working ut_exit.e_exit in struct utmp)
+ for krb5_mem in __e_exit ut_e_exit ut_exit e_exit; do
+ K5_CHECK_UT_EXIT_MEMBER(utmp, $krb5_mem,
+[krb5_utmp_e_exit=$krb5_mem
+krb5_utmp_e_termination=`echo $krb5_mem|sed -e 's%_exit$%_termination%'`], )
+ done
+ if test "${krb5_utmp_e_exit+set}" = set; then
+ AC_MSG_RESULT([working ut_exit.e_exit in utmp is $krb5_utmp_e_exit])
+ AC_DEFINE_UNQUOTED(PTY_UTMP_E_EXIT, $krb5_utmp_e_exit)
+ AC_DEFINE_UNQUOTED(PTY_UTMP_E_TERMINATION, $krb5_utmp_e_termination)
+ else
+ AC_MSG_RESULT([cannot find working ut_exit.e_exit in utmp])
+ fi
+fi
+
+if test "$krb5_cv_struct_utmpx_ut_exit" = yes; then
+ AC_MSG_RESULT(checking for working ut_exit.e_exit in struct utmpx)
+ for krb5_mem in __e_exit ut_e_exit ut_exit e_exit; do
+ K5_CHECK_UT_EXIT_MEMBER(utmpx, $krb5_mem,
+[krb5_utmpx_e_exit=$krb5_mem
+krb5_utmpx_e_termination=`echo $krb5_mem|sed -e 's%_exit$%_termination%'`], )
+ done
+ if test "${krb5_utmpx_e_exit+set}" = set; then
+ AC_MSG_RESULT([working ut_exit.e_exit in utmpx is $krb5_utmpx_e_exit])
+ AC_DEFINE_UNQUOTED(PTY_UTMPX_E_EXIT, $krb5_utmpx_e_exit)
+ AC_DEFINE_UNQUOTED(PTY_UTMPX_E_TERMINATION, $krb5_utmpx_e_termination)
+ else
+ AC_MSG_RESULT([cannot find working ut_exit.e_exit in utmpx])
+ fi
+fi
+
+if test "$ac_cv_func_setutent" = yes; then
+ AC_MSG_CHECKING(consistency of sysV-ish utmp API)
+ if test "$ac_cv_header_utmp_h" = yes; then
+ if test "$krb5_cv_struct_utmp_ut_id" = yes \
+ && test "$krb5_cv_struct_utmp_ut_type" = yes \
+ && test "$krb5_cv_struct_utmp_ut_pid" = yes; then
+ AC_MSG_RESULT(ok)
+ else
+ AC_MSG_RESULT(not ok)
+ AC_MSG_ERROR([have setutent but no ut_id, ut_type, or ut_pid in utmp])
+ fi
+ else
+ AC_MSG_RESULT(not ok)
+ AC_MSG_ERROR([have setutent but no utmp.h])
+ fi
+fi
+
+if test "$ac_cv_header_utmpx_h" = yes; then
+ AC_MSG_CHECKING(consistency of utmpx API)
+ if test "$ac_cv_func_setutxent" = yes; then
+ if test "$krb5_cv_struct_utmpx_ut_id" = yes \
+ && test "$krb5_cv_struct_utmpx_ut_type" = yes \
+ && test "$krb5_cv_struct_utmpx_ut_pid" = yes; then
+ AC_MSG_RESULT(ok)
+ else
+ AC_MSG_RESULT(not ok)
+ AC_MSG_ERROR([have setutxent but no ut_id, ut_type, or ut_pid in utmpx])
+ fi
+ else
+ AC_MSG_RESULT(not ok)
+ AC_MSG_ERROR([have utmpx.h but no setutxent])
+ fi
+fi
+
+#
+# end of utmp-related hair
+#
+######################################################################
+
AC_MSG_CHECKING([streams interface])
AC_CACHE_VAL(krb5_cv_has_streams,
[AC_TRY_COMPILE(
@@ -131,24 +254,10 @@ if test $krb5_cv_setpgrp_args = two; then
AC_DEFINE(SETPGRP_TWOARG)
fi
dnl
-dnl
-if test $ac_cv_header_utmpx_h = yes -a $ac_cv_func_getutmpx = no; then
-AC_MSG_CHECKING([if utmpx and utmp ut_exit structures differ])
-AC_CACHE_VAL(krb5_cv_utmp_utmpx_diff_exit_struct,
-[AC_TRY_COMPILE(
-[#include <sys/types.h>
-#include <utmp.h>
-#include <utmpx.h>],[struct utmpx utx; struct utmp ut;
-utx.ut_exit.ut_exit = ut.ut_exit.e_exit],
-krb5_cv_utmp_utmpx_diff_exit_struct=yes, krb5_cv_utmp_utmpx_diff_exit_struct=no)])
-AC_MSG_RESULT($krb5_cv_utmp_utmpx_diff_exit_struct)
-if test $krb5_cv_utmp_utmpx_diff_exit_struct = yes; then
-AC_DEFINE(UT_EXIT_STRUCTURE_DIFFER)
-fi
-fi
-dnl
ADD_DEF(-DKERBEROS)
-AC_CONST
+AC_C_CONST
KRB5_BUILD_LIBRARY_WITH_DEPS
KRB5_BUILD_LIBOBJS
+KRB5_BUILD_PROGRAM
+KRB5_RUN_FLAGS
V5_AC_OUTPUT_MAKEFILE
diff --git a/src/util/pty/dump-utmp.c b/src/util/pty/dump-utmp.c
index 7cc8469..d4c303f 100644
--- a/src/util/pty/dump-utmp.c
+++ b/src/util/pty/dump-utmp.c
@@ -1,6 +1,29 @@
-#include <stdio.h>
+/*
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ *
+ * dump-utmp.c: dump utmp and utmpx format files for debugging purposes.
+ */
+
+#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
#ifndef UTMPX
#ifdef HAVE_UTMPX_H
@@ -8,138 +31,251 @@
#endif
#endif
+#if defined(HAVE_UTMPNAME) || defined(HAVE_UTMPXNAME)
+#define UTN /* we can set utmp or utmpx for getut*() */
+#endif
+
#ifdef UTMPX
#include <utmpx.h>
+void print_utx(int, const struct utmpx *);
#endif
#include <utmp.h>
-extern char *ctime ();
+void print_ut(int, const struct utmp *);
+
+void usage(const char *);
#if defined (HAVE_STRUCT_UTMP_UT_TYPE) || defined (UTMPX)
-char *ut_typename (t) {
- switch (t) {
+char *ut_typename(int);
+
+char *
+ut_typename(int t) {
+ switch (t) {
#define S(N) case N : return #N
#define S2(N,N2) case N : return #N2
- S(EMPTY);
- S(RUN_LVL);
- S(BOOT_TIME);
- S(OLD_TIME);
- S(NEW_TIME);
- S2(INIT_PROCESS,INIT);
- S2(LOGIN_PROCESS,LOGIN);
- S2(USER_PROCESS,USER);
- S2(DEAD_PROCESS,DEAD);
- S(ACCOUNTING);
- default: return "??";
- }
+ S(EMPTY);
+ S(RUN_LVL);
+ S(BOOT_TIME);
+ S(OLD_TIME);
+ S(NEW_TIME);
+ S2(INIT_PROCESS,INIT);
+ S2(LOGIN_PROCESS,LOGIN);
+ S2(USER_PROCESS,USER);
+ S2(DEAD_PROCESS,DEAD);
+ S(ACCOUNTING);
+ default: return "??";
+ }
}
#endif
-int main (argc, argv) int argc; char *argv[]; {
- int f;
- char id[5], user[50], host[100];
- char *file = 0;
- int all = 0;
- int is_utmpx = 0;
-
- while (*++argv)
- {
- char *arg = *argv;
- if (!arg)
- break;
- if (!strcmp ("-a", arg))
- all = 1;
- else if (!strcmp ("-x", arg))
- is_utmpx = 1;
- else if (arg[0] == '-')
- {
- fprintf (stderr, "unknown arg `%s'\n", arg);
- return 1;
- }
- else if (file)
- {
- fprintf (stderr, "already got a file\n");
- return 1;
+#define S2D(x) (sizeof(x) * 2.4 + 1.5)
+
+void
+print_ut(int all, const struct utmp *u)
+{
+ int lu, ll;
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+ int lid;
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+ int lpid;
+#endif
+#ifdef PTY_UTMP_E_EXIT
+ int let, lee;
+#endif
+
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ if (!all && ((u->ut_type == EMPTY) || (u->ut_type == DEAD_PROCESS)))
+ return;
+#endif
+
+ lu = sizeof(u->ut_name);
+ ll = sizeof(u->ut_line);
+ printf("%-*.*s:", lu, lu, u->ut_name);
+ printf("%-*.*s:", ll, ll, u->ut_line);
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+ lid = sizeof(u->ut_id);
+ printf("%-*.*s:", lid, lid, u->ut_id);
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+ lpid = S2D(u->ut_pid);
+ printf("%*ld", lpid, (long)u->ut_pid);
+#endif
+#ifdef PTY_UTMP_E_EXIT
+ let = S2D(u->ut_exit.PTY_UTMP_E_TERMINATION);
+ lee = S2D(u->ut_exit.PTY_UTMP_E_EXIT);
+ printf("(%*ld,", let, (long)u->ut_exit.PTY_UTMP_E_TERMINATION);
+ printf("%*ld)", lee, (long)u->ut_exit.PTY_UTMP_E_EXIT);
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ printf(" %-9s", ut_typename(u->ut_type));
+#endif
+ printf(" %s", ctime(&u->ut_time) + 4);
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ if (u->ut_host[0])
+ printf(" %.*s\n", (int) sizeof(u->ut_host), u->ut_host);
+#endif
+
+ return;
+}
+
+#ifdef UTMPX
+void
+print_utx(int all, const struct utmpx *u)
+{
+ int lu, ll, lid, lpid;
+#ifdef PTY_UTMPX_E_EXIT
+ int let, lee;
+#endif
+
+ if (!all && ((u->ut_type == EMPTY) || (u->ut_type == DEAD_PROCESS)))
+ return;
+
+ lu = sizeof(u->ut_user);
+ ll = sizeof(u->ut_line);
+ lid = sizeof(u->ut_id);
+ printf("%-*.*s:", lu, lu, u->ut_user);
+ printf("%-*.*s:", ll, ll, u->ut_line);
+ printf("%-*.*s", lid, lid, u->ut_id);
+ if (lu + ll + lid >= 60)
+ printf("\n");
+ else
+ printf(":");
+ lpid = S2D(u->ut_pid);
+ printf("%*ld", lpid, (long)u->ut_pid);
+#ifdef PTY_UTMPX_E_EXIT
+ let = S2D(u->ut_exit.PTY_UTMPX_E_TERMINATION);
+ lee = S2D(u->ut_exit.PTY_UTMPX_E_EXIT);
+ printf("(%*ld,", let, (long)u->ut_exit.PTY_UTMPX_E_TERMINATION);
+ printf("%*ld)", lee, (long)u->ut_exit.PTY_UTMPX_E_EXIT);
+#endif
+ printf(" %-9s", ut_typename(u->ut_type));
+ printf(" %s", ctime(&u->ut_tv.tv_sec) + 4);
+#ifdef HAVE_STRUCT_UTMPX_UT_HOST
+ if (u->ut_host[0])
+ printf(" %s\n", u->ut_host);
+#endif
+
+ return;
+}
+#endif
+
+#ifdef UTMPX
+#define OPTX "x"
+#else
+#define OPTX
+#endif
+#ifdef UTN
+#define OPTG "g"
+#else
+#define OPTG
+#endif
+#define OPTS "a" OPTX OPTG
+
+void
+usage(const char *prog)
+{
+ fprintf(stderr, "usage: %s [-" OPTS "] file\n", prog);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ int all, is_utmpx, do_getut;
+ int f;
+ char *fn;
+ size_t recsize;
+ size_t nread;
+ union {
+ struct utmp ut;
+#ifdef UTMPX
+ struct utmpx utx;
+#endif
+ } u;
+
+ all = is_utmpx = do_getut = 0;
+ recsize = sizeof(struct utmp);
+
+ while ((c = getopt(argc, argv, OPTS)) != EOF) {
+ switch (c) {
+ case 'a':
+ all = 1;
+ break;
+#ifdef UTMPX
+ case 'x':
+ is_utmpx = 1;
+ recsize = sizeof(struct utmpx);
+ break;
+#endif
+#ifdef UTN
+ case 'g':
+ do_getut = 1;
+ break;
+#endif
+ default:
+ usage(argv[0]);
}
- else
- file = arg;
}
- f = open (file, O_RDONLY);
- if (f < 0) {
- perror (file);
- exit (1);
- }
- id[4] = 0;
- if (is_utmpx) {
+ if (argc <= optind)
+ usage(argv[0]);
+ fn = argv[optind];
+ if (!do_getut) {
+ f = open(fn, O_RDONLY);
+ if (f == -1) {
+ perror(fn);
+ exit(1);
+ }
+ while ((nread = read(f, &u, recsize)) > 0) {
+ if (nread < recsize) {
+ fprintf(stderr, "short read");
+ close(f);
+ exit(1);
+ }
+ if (is_utmpx) {
#ifdef UTMPX
- struct utmpx u;
- while (1) {
- int nread = read (f, &u, sizeof (u));
- if (nread == 0) {
- /* eof */
- return 0;
- } else if (nread == -1) {
- /* error */
- perror ("read");
- return 1;
- }
- if ((u.ut_type == DEAD_PROCESS
- || u.ut_type == EMPTY)
- && !all)
- continue;
- strncpy (id, u.ut_id, 4);
- printf ("%-8s:%-12s:%-4s", u.ut_user, u.ut_line, id);
- printf (":%5d", u.ut_pid);
- printf ("(%5d,%5d)", u.ut_exit.e_termination, u.ut_exit.e_exit);
- printf (" %-9s %s", ut_typename (u.ut_type), ctime (&u.ut_xtime) + 4);
- if (u.ut_syslen && u.ut_host[0])
- printf (" %s\n", u.ut_host);
- }
- abort ();
+ print_utx(all, &u.utx);
#else
- fprintf (stderr, "utmpx support not compiled in\n");
- return 1;
-#endif
- }
- /* else */
- {
- struct utmp u;
- while (read (f, &u, sizeof (u)) == sizeof (u)) {
-#ifdef EMPTY
- if ((u.ut_type == DEAD_PROCESS
- || u.ut_type == EMPTY)
- && !all)
- continue;
+ abort();
#endif
-#ifdef HAVE_STRUCT_UTMP_UT_PID
- strncpy (id, u.ut_id, 4);
- strncpy (user, u.ut_user, sizeof (u.ut_user));
- user[sizeof(u.ut_user)] = 0;
- printf ("%-8s:%-12s:%-4s", user, u.ut_line, id);
- printf (":%5d", u.ut_pid);
+ } else {
+ print_ut(all, &u.ut);
+ }
+ }
+ if (nread == -1) {
+ perror("read");
+ exit(1);
+ }
+ close(f);
+ } else {
+ if (is_utmpx) {
+#ifdef UTMPX
+#ifdef HAVE_UTMPXNAME
+ struct utmpx *utxp;
+ utmpxname(fn);
+ setutxent();
+ while ((utxp = getutxent()) != NULL)
+ print_utx(all, utxp);
#else
- strncpy (user, u.ut_name, sizeof (u.ut_name));
- user[sizeof(u.ut_name)] = 0;
- printf ("%-8s:%-12s", user, u.ut_line);
-#endif
-#ifdef HAVE_STRUCT_UTMP_UT_HOST
- {
- char host[sizeof (u.ut_host) + 1];
- strncpy (host, u.ut_host, sizeof(u.ut_host));
- host[sizeof (u.ut_host)] = 0;
- printf (":%-*s", sizeof (u.ut_host), host);
- }
+ fprintf(stderr, "no utmpxname(); can't use getutxent()\n");
+ exit(1);
#endif
-#ifdef HAVE_STRUCT_UTMP_UT_EXIT
- printf ("(%5d,%5d)", u.ut_exit.e_termination, u.ut_exit.e_exit);
+#else
+ abort();
#endif
-#ifdef HAVE_STRUCT_UTMP_UT_TYPE
- printf (" %-9s", ut_typename (u.ut_type));
+ } else {
+#ifdef HAVE_UTMPNAME
+ struct utmp *utp;
+ utmpname(fn);
+ setutxent();
+ while ((utp = getutent()) != NULL)
+ print_ut(all, utp);
+#else
+ fprintf(stderr, "no utmpname(); can't use getutent()\n");
+ exit(1);
#endif
- /* this ends with a newline */
- printf (" %s", ctime (&u.ut_time) + 4);
+ }
}
- }
-
- return 0;
+ exit(0);
}
diff --git a/src/util/pty/getpty.c b/src/util/pty/getpty.c
index 3683ba6..0e86514 100644
--- a/src/util/pty/getpty.c
+++ b/src/util/pty/getpty.c
@@ -24,15 +24,17 @@
#include "libpty.h"
#include "pty-int.h"
-long pty_getpty (fd, slave, slavelength)
- int slavelength;
- int *fd; char *slave;
+long
+ptyint_getpty_ext(int *fd, char *slave, int slavelength, int do_grantpt)
{
+#if !defined(HAVE__GETPTY) && !defined(HAVE_OPENPTY)
char *cp;
char *p;
int i,ptynum;
struct stat stb;
char slavebuf[1024];
+#endif
+
#ifdef HAVE__GETPTY
char *slaveret; /*Temporary to hold pointer to slave*/
#endif /*HAVE__GETPTY*/
@@ -76,7 +78,8 @@ long pty_getpty (fd, slave, slavelength)
if (*fd >= 0) {
#if defined(HAVE_GRANTPT)&&defined(HAVE_STREAMS)
- if (grantpt(*fd) || unlockpt(*fd)) return PTY_GETPTY_STREAMS;
+ if (do_grantpt)
+ if (grantpt(*fd) || unlockpt(*fd)) return PTY_GETPTY_STREAMS;
#endif
#ifdef HAVE_PTSNAME
@@ -139,3 +142,9 @@ long pty_getpty (fd, slave, slavelength)
#endif /*HAVE__GETPTY*/
#endif /* HAVE_OPENPTY */
}
+
+long
+pty_getpty(int *fd, char *slave, int slavelength)
+{
+ return ptyint_getpty_ext(fd, slave, slavelength, 1);
+}
diff --git a/src/util/pty/libpty.h b/src/util/pty/libpty.h
index 82d2d81..ddd20c1 100644
--- a/src/util/pty/libpty.h
+++ b/src/util/pty/libpty.h
@@ -30,7 +30,6 @@
/* flags to update_utmp*/
#define PTY_TTYSLOT_USABLE (0x1)
#define PTY_UTMP_USERNAME_VALID (0x2)
-#ifdef __STDC__ /* use prototypes */
long pty_init(void);
long pty_getpty ( int *fd, char *slave, int slavelength);
@@ -39,24 +38,17 @@ long pty_open_slave (const char *slave, int *fd);
long pty_open_ctty (const char *slave, int *fd);
long pty_initialize_slave ( int fd);
-long pty_update_utmp (int process_type,int pid, char *user, char *line, char *host, int flags);
+long pty_update_utmp(int process_type, int pid, const char *user,
+ const char *line, const char *host, int flags);
-long pty_logwtmp (char *tty, char * user, char *host);
+long pty_logwtmp(const char *tty, const char *user, const char *host);
long pty_cleanup(char *slave, int pid, int update_utmp);
+
+#ifndef SOCK_DGRAM
+struct sockaddr_in;
+#endif
+
long pty_make_sane_hostname(struct sockaddr_in *, int, int, int, char **);
-#else /*__STDC__*/
-long pty_init();
-long pty_getpty();
-
-long pty_open_slave();
-long pty_open_ctty();
-long pty_initialize_slave();
-
-long pty_update_utmp();
-long pty_logwtmp();
-long pty_cleanup();
-long pty_make_sane_hostname();
-#endif /* __STDC__*/
#define __LIBPTY_H__
#endif
diff --git a/src/util/pty/logwtmp.c b/src/util/pty/logwtmp.c
index e3611f6..2047278 100644
--- a/src/util/pty/logwtmp.c
+++ b/src/util/pty/logwtmp.c
@@ -1,8 +1,7 @@
/*
* pty_logwtmp: Implement the logwtmp function if not present.
*
- * Copyright 1995 by the Massachusetts Institute of Technology.
- *
+ * Copyright 1995, 2001 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -24,42 +23,86 @@
#include "libpty.h"
#include "pty-int.h"
-long pty_logwtmp (tty, user, host )
- char *user, *tty, *host;
+#if defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT)
+#ifdef HAVE_SETUTXENT
+#define PTY_STRUCT_UTMPX struct utmpx
+#else
+#define PTY_STRUCT_UTMPX struct utmp
+#endif
+
+long
+pty_logwtmp(const char *tty, const char *user, const char *host)
{
+#ifndef HAVE_LOGWTMP
+ PTY_STRUCT_UTMPX utx;
+ int loggingin;
+ size_t len;
+ const char *cp;
+ char utmp_id[5];
+#endif
+
#ifdef HAVE_LOGWTMP
logwtmp(tty,user,host);
return 0;
#else
- struct utmp ut;
- char *tmpx;
- char utmp_id[5];
- /* Will be empty for logout */
- int loggingin = user[0];
+ loggingin = (user[0] != '\0');
+ memset(&utx, 0, sizeof(utx));
+ strncpy(utx.ut_line, tty, sizeof(utx.ut_line));
+ strncpy(utx.ut_user, user, sizeof(utx.ut_user));
+#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_HOST)) \
+ || (!defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_HOST))
+ strncpy(utx.ut_host, host, sizeof(utx.ut_host));
+ utx.ut_host[sizeof(utx.ut_host) - 1] = '\0';
+#endif
+#ifdef HAVE_SETUTXENT
+ gettimeofday(&utx.ut_tv, NULL);
+#else
+ (void)time(&utx.ut_time);
+#endif
+ utx.ut_pid = (loggingin ? getpid() : 0);
+ utx.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);
-#ifndef NO_UT_HOST
- strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+ len = strlen(tty);
+ if (len >= 2)
+ cp = tty + len - 2;
+ else
+ cp = tty;
+ sprintf(utmp_id, "kr%s", cp);
+ strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id));
+
+#ifdef HAVE_SETUTXENT
+ return ptyint_update_wtmpx(&utx);
+#else
+ return ptyint_update_wtmp(&utx);
#endif
- strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
- ut.ut_time = time(0);
-
-#ifndef NO_UT_PID
- ut.ut_pid = getpid();
- strncpy(ut.ut_user, user, sizeof(ut.ut_user));
+#endif /* !HAVE_LOGWTMP */
+}
- tmpx = tty + strlen(tty) - 2;
- sprintf(utmp_id, "kr%s", tmpx);
- strncpy(ut.ut_id, utmp_id, sizeof(ut.ut_id));
- ut.ut_pid = (loggingin ? getpid() : 0);
- ut.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);
+#else /* !(defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT)) */
+
+long
+pty_logwtmp(const char *tty, const char *user, const char *host)
+{
+ struct utmp ut;
+
+#ifdef HAVE_LOGWTMP
+ logwtmp(tty,user,host);
+ return 0;
#else
- strncpy(ut.ut_name, user, sizeof(ut.ut_name));
+
+ memset(&ut, 0, sizeof(ut));
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+ ut.ut_host[sizeof(ut.ut_host) - 1] = '\0';
#endif
+ strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
+ strncpy(ut.ut_name, user, sizeof(ut.ut_name));
+ return ptyint_update_wtmp(&ut);
- return ptyint_update_wtmp(&ut, host, user);
-#endif /*HAVE_LOGWTMP*/
+#endif /* !HAVE_LOGWTMP */
}
+#endif /* !(defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT)) */
diff --git a/src/util/pty/open_ctty.c b/src/util/pty/open_ctty.c
index d02a8c1..5e41d95 100644
--- a/src/util/pty/open_ctty.c
+++ b/src/util/pty/open_ctty.c
@@ -24,35 +24,37 @@
#include "pty-int.h"
/*
- * This routine will be called twice. It's not particularly important
- * that the setsid() or TIOCSTTY ioctls succeed (they may not the
- * second time), but rather that we have a controlling terminal at the
- * end. It is assumed that vhangup doesn't exist and confuse the
- * process's notion of controlling terminal on any system without
- * TIOCNOTTY. That is, either vhangup() leaves the controlling
- * terminal in tact, breaks the association completely, or the system
- * provides TIOCNOTTY to get things back into a reasonable state. In
- * practice, vhangup() either breaks the association completely or
- * doesn't effect controlling terminals, so this condition is met.
+ * This function will be called twice. The first time it will acquire
+ * a controlling terminal from which to vhangup() or revoke() (see
+ * comments in open_slave.c); the second time, it will be to open the
+ * actual slave device for use by the application. We no longer call
+ * ptyint_void_association(), as that will be called in
+ * pty_open_slave() to avoid spurious calls to setsid(), etc.
+ *
+ * It is assumed that systems where vhangup() exists and does break
+ * the ctty association will allow the slave to be re-acquired as the
+ * ctty. Also, if revoke() or vhangup() doesn't break the ctty
+ * association, we assume that we can successfully reopen the slave.
+ *
+ * This function doesn't check whether we actually acquired the ctty;
+ * we assume that the caller will check that, or that it doesn't
+ * matter in the particular case.
*/
long
-pty_open_ctty (slave, fd)
- const char * slave;
- int *fd;
+pty_open_ctty(const char *slave, int *fd)
{
- int retval;
-/* First, dissociate from previous terminal */
- if ( (retval = ptyint_void_association()) != 0 )
- return retval;
#ifdef ultrix
- /* The Ultrix (and other BSD tty drivers) require the process group
- * to be zero, in order to acquire the new tty as a controlling tty. */
+ /*
+ * The Ultrix (and other BSD tty drivers) require the process
+ * group to be zero, in order to acquire the new tty as a
+ * controlling tty. This may actually belong in
+ * ptyint_void_association().
+ */
(void) setpgrp(0, 0);
#endif
-
*fd = open(slave, O_RDWR);
- if (*fd < 0 )
+ if (*fd < 0)
return PTY_OPEN_SLAVE_OPENFAIL;
#ifdef ultrix
setpgrp(0, getpid());
diff --git a/src/util/pty/open_slave.c b/src/util/pty/open_slave.c
index aea04de..cc52228 100644
--- a/src/util/pty/open_slave.c
+++ b/src/util/pty/open_slave.c
@@ -1,7 +1,8 @@
/*
* pty_open_slave: open slave side of terminal, clearing for use.
*
- * Copyright 1995, 1996 by the Massachusetts Institute of Technology.
+ * Copyright 1995, 1996, 2001 by the Massachusetts Institute of
+ * Technology.
*
*
* Permission to use, copy, modify, and distribute this software and
@@ -24,76 +25,77 @@
#include "libpty.h"
#include "pty-int.h"
-
-long pty_open_slave ( slave, fd)
- const char *slave;
- int *fd;
+long
+pty_open_slave(const char *slave, int *fd)
{
- int vfd, testfd;
+ int tmpfd;
long retval;
-#ifdef POSIX_SIGNALS
- struct sigaction sa;
- /* Initialize "sa" structure. */
- (void) sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
-
-#endif
+ /* Sanity check. */
+ if (slave == NULL || *slave == '\0')
+ return PTY_OPEN_SLAVE_TOOSHORT;
+
+ /* First, set up a new session and void old associations. */
+ ptyint_void_association();
- /* First, chmod and chown the slave*/
/*
- * If we have vhangup then we really need pty_open_ctty to make sure
- * Our controlling terminal is the pty we're opening. However, if we
- * are using revoke or nothing then we just need a file descriiptor
- * for the pty. Considering some OSes in this category break on
- * the second call to open_ctty (currently OSF but others may),
- * we simply use a descriptor if we can.
- */
-#ifdef VHANG_FIRST
- if (( retval = pty_open_ctty ( slave, &vfd )) != 0 )
- return retval;
- if (vfd < 0)
+ * Make a first attempt at acquiring the ctty under certain
+ * condisions. This is necessary for several reasons:
+ *
+ * Under Irix, if you open a pty slave and then close it, a
+ * subsequent open of the slave will cause the master to read EOF.
+ * To prevent this, don't close the first fd until we do the real
+ * open following vhangup().
+ *
+ * Under Tru64 v5.0, if there isn't a fd open on the slave,
+ * revoke() fails with ENOTTY, curiously enough.
+ *
+ * Anyway, sshd seems to make a practice of doing this.
+ */
+#if defined(VHANG_FIRST) || defined(REVOKE_NEEDS_OPEN)
+ retval = pty_open_ctty(slave, fd);
+ if (retval)
+ return retval;
+ if (*fd < 0)
return PTY_OPEN_SLAVE_OPENFAIL;
-
#endif
-
- if (slave == NULL || *slave == '\0')
- return PTY_OPEN_SLAVE_TOOSHORT;
- if (chmod(slave, 0))
- return PTY_OPEN_SLAVE_CHMODFAIL;
- if ( chown(slave, 0, 0 ) == -1 )
- return PTY_OPEN_SLAVE_CHOWNFAIL;
+ /* chmod and chown the slave. */
+ if (chmod(slave, 0))
+ return PTY_OPEN_SLAVE_CHMODFAIL;
+ if (chown(slave, 0, 0) == -1)
+ return PTY_OPEN_SLAVE_CHOWNFAIL;
-#ifdef VHANG_FIRST
- ptyint_vhangup();
- (void) close(vfd);
-#endif
-
- if ( (retval = ptyint_void_association()) != 0)
- return retval;
-
#ifdef HAVE_REVOKE
- if (revoke (slave) < 0 ) {
+ if (revoke(slave) < 0) {
return PTY_OPEN_SLAVE_REVOKEFAIL;
}
-#endif /*HAVE_REVOKE*/
+#else /* !HAVE_REVOKE */
+#ifdef VHANG_FIRST
+ ptyint_vhangup();
+#endif
+#endif /* !HAVE_REVOKE */
-/* Open the pty for real. */
- if (( retval = pty_open_ctty ( slave, fd)) != 0 ) {
+ /* Open the pty for real. */
+ retval = pty_open_ctty(slave, &tmpfd);
+#if defined(VHANG_FIRST) || defined(REVOKE_NEEDS_OPEN)
+ close(*fd);
+#endif
+ if (retval) {
+ *fd = -1;
return PTY_OPEN_SLAVE_OPENFAIL;
}
- retval = pty_initialize_slave (*fd);
-
+ *fd = tmpfd;
+ retval = pty_initialize_slave(*fd);
if (retval)
- return retval;
- testfd = open("/dev/tty", O_RDWR|O_NDELAY);
- if ( testfd < 0 )
- {
+ return retval;
+ /* Make sure it's really our ctty. */
+ tmpfd = open("/dev/tty", O_RDWR|O_NDELAY);
+ if (tmpfd < 0) {
close(*fd);
*fd = -1;
return PTY_OPEN_SLAVE_NOCTTY;
- }
- close(testfd);
+ }
+ close(tmpfd);
return 0;
}
diff --git a/src/util/pty/pty-int.h b/src/util/pty/pty-int.h
index 2c47780..0135165 100644
--- a/src/util/pty/pty-int.h
+++ b/src/util/pty/pty-int.h
@@ -82,8 +82,13 @@
#endif
#endif
-#if defined(HAVE_VHANGUP) && !defined(OPEN_CTTY_ONLY_ONCE)
-#define VHANG_first /* Breaks under Ultrix and others where you cannot get controlling terminal twice.*/
+#if defined(HAVE_VHANGUP) && !defined(OPEN_CTTY_ONLY_ONCE) \
+ && !defined(HAVE_REVOKE)
+/*
+ * Breaks under Ultrix and others where you cannot get controlling
+ * terminal twice.
+ */
+#define VHANG_FIRST
#define VHANG_LAST
#endif
@@ -91,14 +96,27 @@
#ifdef __STDC__
long ptyint_void_association(void);
long ptyint_open_ctty (char *slave, int *fd);
-long ptyint_update_wtmp (struct utmp *ut, char *host, char *user);
-
+long ptyint_getpty_ext(int *, char *, int, int);
+#ifdef HAVE_SETUTXENT
+long ptyint_update_wtmpx(struct utmpx *utx);
+#endif
+#if !(defined(WTMPX_FILE) && defined(HAVE_UPDWTMPX)) \
+ || !defined(HAVE_SETUXENT)
+long ptyint_update_wtmp(struct utmp *ut);
+#endif
void ptyint_vhangup(void);
#else /*__STDC__*/
long ptyint_void_association();
-void ptyint_vhangup();
+long ptyint_getpty_ext();
+#ifdef HAVE_SETUTXENT
+long ptyint_update_wtmpx();
+#endif
+#if !(defined(WTMPX_FILE) && defined(HAVE_UPDWTMPX)) \
+ || !defined(HAVE_SETUXENT)
long ptyint_update_wtmp();
+#endif
+void ptyint_vhangup();
#endif /* __STDC__*/
#define __PTY_INT_H__
diff --git a/src/util/pty/pty_paranoia.c b/src/util/pty/pty_paranoia.c
new file mode 100644
index 0000000..7311e08
--- /dev/null
+++ b/src/util/pty/pty_paranoia.c
@@ -0,0 +1,650 @@
+/*
+ * Copyright 2001 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * M.I.T. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability
+ * of this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+/*
+ * A rant on the nature of pseudo-terminals:
+ * -----------------------------------------
+ *
+ * Controlling terminals and job control:
+ *
+ * First, some explanation of job control and controlling terminals is
+ * necessary for background. This discussion applies to hardwired
+ * terminals as well as ptys. On most modern systems, all processes
+ * belong to a process group. A process whose process group id (pgid)
+ * is the sames as its pid is the process group leader of its process
+ * group. Process groups belong to sessions. On a modern system, a
+ * process that is not currently a process group leader may create a
+ * new session by calling setsid(), which makes it a session leader as
+ * well as a process group leader, and also removes any existing
+ * controlling terminal (ctty) association. Only a session leader may
+ * acquire a ctty. It's not clear how systems that don't have
+ * setsid() handle ctty acquisition, though probably any process group
+ * leader that doesn't have a ctty may acquire one that way.
+ *
+ * A terminal that is a ctty has an associated foreground process
+ * group, which is a member of the terminal's associated session.
+ * This process group gets read/write access to the terminal and will
+ * receive terminal-generated signals (e.g. SIGINT, SIGTSTP). Process
+ * groups belonging to the session but not in the foreground may get
+ * signals that suspend them if they try to read/write from the ctty,
+ * depending on various terminal settings.
+ *
+ * On many systems, the controlling process (the session leader
+ * associated with a ctty) exiting will cause the session to lose its
+ * ctty, even though some processes may continue to have open file
+ * descriptors on the former ctty. It is possible for a process to
+ * have no file descriptors open on its controlling tty, but to
+ * reacquire such by opening /dev/tty, as long as its session still
+ * has a ctty.
+ *
+ * On ptys in general:
+ *
+ * Ptys have a slave side and a master side. The slave side looks
+ * like a hardwired serial line to the application that opens it;
+ * usually, telnetd or rlogind, etc. opens the slave and hands it to
+ * the login program as stdin/stdout/stderr. The master side usually
+ * gets the actual network traffic written to/from it. Roughly, the
+ * master and slave are two ends of a bidirectional pair of FIFOs,
+ * though this can get complicated by other things.
+ *
+ * The master side of a pty is theoretically a single-open device.
+ * This MUST be true on systems that have BSD-style ptys, since there
+ * is usually no way to allocate an unused pty except by attempting to
+ * open all the master pty nodes in the system.
+ *
+ * Often, but not always, the last close of a slave device will cause
+ * the master to get an EOF. Closing the master device will sometimes
+ * cause the foreground process group of the slave to get a SIGHUP,
+ * but that may depend on terminal settings.
+ *
+ * BSD ptys:
+ *
+ * On a BSD-derived system, the master nodes are named like
+ * /dev/ptyp0, and the slave nodes are named like /dev/ttyp0. The
+ * last two characters are the variable ones, and a shell-glob type
+ * pattern for a slave device is usually of the form
+ * /dev/tty[p-z][0-9a-f], though variants are known to exist.
+ *
+ * System V cloning ptys:
+ *
+ * There is a cloning master device (usually /dev/ptmx, but the name
+ * can vary) that gets opened. Each open of the cloning master
+ * results in an open file descriptor of a unique master device. The
+ * application calls ptsname() to find the pathname to the slave node.
+ *
+ * In theory, the slave side of the pty is locked out until the
+ * process opening the master calls grantpt() to adjust permissions
+ * and unlockpt() to unlock the slave. It turns out that Unix98
+ * doesn't require that the slave actually get locked out, or that
+ * unlockpt() actually do anything on such systems. At least AIX
+ * allows the slave to be opened prior to calling unlockpt(), but most
+ * other SysV-ish systems seem to actually lock out the slave.
+ *
+ * Pty security:
+ *
+ * It's not guaranteed on a BSD-ish system that a slave can't be
+ * opened when the master isn't open. It's even possible to acquire
+ * the slave as a ctty (!) if the open is done as non-blocking. It's
+ * possible to open the master corresponding to an open slave, which
+ * creates some security issues: once this master is open, data
+ * written to the slave will actually pass to the master.
+ *
+ * On a SysV-ish system, the close of the master will invalidate any
+ * open file descriptors on the slave.
+ *
+ * In general, there are two functions that can be used to "clean" a
+ * pty slave, revoke() and vhangup(). revoke() will invalidate all
+ * file descriptors open on a particular pathname (often this only
+ * works on terminal devices), usually by invalidating the underlying
+ * vnode. vhangup() will send a SIGHUP to the foreground process
+ * group of the control terminal. On many systems, it also has
+ * revoke() semantics.
+ *
+ * If a process acquires a controlling terminal in order to perform a
+ * vhangup(), the reopen of the controlling terminal after the
+ * vhangup() call should be done prior to the close of the file
+ * descriptor used to initially acquire the controlling terminal,
+ * since that will likely prevent the process on the master side from
+ * reading a spurious EOF due to all file descriptors to the slave
+ * being closed.
+ *
+ * Known quirks of various OSes:
+ *
+ * AIX 4.3.3:
+ *
+ * If the environment variable XPG_SUS_ENV is not equal to "ON", then
+ * it's possible to open the slave prior to calling unlockpt().
+ */
+
+/*
+ * NOTE: this program will get reworked at some point to actually test
+ * passing of data between master and slave, and to do general cleanup.
+ *
+ * This is rather complex, so it bears some explanation.
+ *
+ * There are multiple child processes and a parent process. These
+ * communicate via pipes (which we assume here to be unidirectional).
+ * The pipes are:
+ *
+ * pp1 - parent -> any children
+ *
+ * p1p - any children -> parent
+ *
+ * p21 - only child2 -> child1
+ *
+ * A parent process will acquire a pty master and slave via
+ * pty_getpty(). It will then fork a process, child1. It then does a
+ * waitpid() for child1, and then writes to child2 via syncpipe pp1.
+ * It then reads from child3 via syncpipe p1p, then closes the
+ * master. It writes to child3 via syncpipe pp1 to indicate that it
+ * has closed the master. It then reads from child3 via syncpipe p1p
+ * and exits with a value appropriate to what it read from child3.
+ *
+ * child1 will acquire the slave as its ctty and fork child2; child1
+ * will exit once it reads from the syncpipe p21 from child2.
+ *
+ * child2 will set a signal handler for SIGHUP and then write to
+ * child1 via syncpipe p21 to indicate that child2 has set up the
+ * handler. It will then read from the syncpipe pp1 from the parent
+ * to confirm that the parent has seen child1 exit, and then checks to
+ * see if it still has a ctty. Under Unix98, and likely earlier
+ * System V derivatives, the exiting of the session leader associated
+ * with a ctty (in this case, child1) will cause the entire session to
+ * lose its ctty.
+ *
+ * child2 will then check to see if it can reopen the slave, and
+ * whether it has a ctty after reopening it. This should fail on most
+ * systems.
+ *
+ * child2 will then fork child3 and immediately exit.
+ *
+ * child3 will write to the syncpipe p1p and read from the syncpipe
+ * pp1. It will then check if it has a ctty and then attempt to
+ * reopen the slave. This should fail. It will then write to the
+ * parent via syncpipe p1p and exit.
+ *
+ * If this doesn't fail, child3 will attempt to write to the open
+ * slave fd. This should fail unless a prior call to revoke(),
+ * etc. failed due to lack of permissions, e.g. NetBSD when running as
+ * non-root.
+ */
+
+#include <com_err.h>
+#include "libpty.h"
+#include "pty-int.h"
+#include <sys/wait.h>
+#include <stdlib.h>
+
+char *prog;
+int masterfd, slavefd;
+char slave[64], slave2[64];
+pid_t pid1, pid2, pid3;
+int status1, status2;
+int pp1[2], p1p[2], p21[2];
+
+void handler(int);
+void rdsync(int, int *, const char *);
+void wrsync(int, int, const char *);
+void testctty(const char *);
+void testex(int, const char *);
+void testwr(int, const char *);
+void child1(void);
+void child2(void);
+void child3(void);
+
+void
+handler(int sig)
+{
+ printf("pid %ld got signal %d\n", (long)getpid(), sig);
+ fflush(stdout);
+ return;
+}
+
+void
+rdsync(int fd, int *status, const char *caller)
+{
+ int n;
+ char c;
+
+#if 0
+ printf("rdsync: %s: starting\n", caller);
+ fflush(stdout);
+#endif
+ while ((n = read(fd, &c, 1)) < 0) {
+ if (errno != EINTR) {
+ fprintf(stderr, "rdsync: %s", caller);
+ perror("");
+ exit(1);
+ } else {
+ printf("rdsync: %s: got EINTR; looping\n", caller);
+ fflush(stdout);
+ }
+ }
+ if (!n) {
+ fprintf(stderr, "rdsync: %s: unexpected EOF\n", caller);
+ exit(1);
+ }
+ printf("rdsync: %s: got sync byte\n", caller);
+ fflush(stdout);
+ if (status != NULL)
+ *status = c;
+}
+
+void
+wrsync(int fd, int status, const char *caller)
+{
+ int n;
+ char c;
+
+ c = status;
+ while ((n = write(fd, &c, 1)) < 0) {
+ if (errno != EINTR) {
+ fprintf(stderr, "wrsync: %s", caller);
+ perror("");
+ exit(1);
+ } else {
+ printf("wrsync: %s: got EINTR; looping\n", caller);
+ fflush(stdout);
+ }
+ }
+#if 0
+ printf("wrsync: %s: sent sync byte\n", caller);
+#endif
+ fflush(stdout);
+}
+
+void
+testctty(const char *caller)
+{
+ int fd;
+
+ fd = open("/dev/tty", O_RDWR|O_NONBLOCK);
+ if (fd < 0) {
+ printf("%s: no ctty\n", caller);
+ } else {
+ printf("%s: have ctty\n", caller);
+ }
+}
+
+void
+testex(int fd, const char *caller)
+{
+ fd_set rfds, xfds;
+ struct timeval timeout;
+ int n;
+ char c;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ FD_ZERO(&rfds);
+ FD_ZERO(&xfds);
+ FD_SET(fd, &rfds);
+ FD_SET(fd, &xfds);
+
+ n = select(fd + 1, &rfds, NULL, &xfds, &timeout);
+ if (n < 0) {
+ fprintf(stderr, "testex: %s: ", caller);
+ perror("select");
+ }
+ if (n) {
+ if (FD_ISSET(fd, &rfds) || FD_ISSET(fd, &xfds)) {
+ n = read(fd, &c, 1);
+ if (!n) {
+ printf("testex: %s: got EOF\n", caller);
+ fflush(stdout);
+ return;
+ } else if (n == -1) {
+ printf("testex: %s: got errno=%ld (%s)\n",
+ caller, (long)errno, strerror(errno));
+ } else {
+ printf("testex: %s: read 1 byte!?\n", caller);
+ }
+ }
+ } else {
+ printf("testex: %s: no exceptions or readable fds\n", caller);
+ }
+}
+
+void
+testwr(int fd, const char *caller)
+{
+ fd_set wfds;
+ struct timeval timeout;
+ int n;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+
+ n = select(fd + 1, NULL, &wfds, NULL, &timeout);
+ if (n < 0) {
+ fprintf(stderr, "testwr: %s: ", caller);
+ perror("select");
+ }
+ if (n) {
+ if (FD_ISSET(fd, &wfds)) {
+ printf("testwr: %s: is writable\n", caller);
+ fflush(stdout);
+ }
+ }
+}
+
+
+void
+child3(void)
+{
+ int n;
+
+ ptyint_void_association();
+ slavefd = open(slave, O_RDWR|O_NONBLOCK);
+ if (slavefd < 0) {
+ wrsync(p1p[1], 1, "[02] child3->parent");
+ printf("child3: failed reopen of slave\n");
+ fflush(stdout);
+ exit(1);
+ }
+#ifdef TIOCSCTTY
+ ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+
+ printf("child3: reopened slave\n");
+ testctty("child3: after reopen of slave");
+ testwr(slavefd, "child3: after reopen of slave");
+ testex(slavefd, "child3: after reopen of slave");
+ close(slavefd);
+ testctty("child3: after close of slave");
+
+ /*
+ * Sync for parent to close master.
+ */
+ wrsync(p1p[1], 0, "[02] child3->parent");
+ rdsync(pp1[0], NULL, "[03] parent->child3");
+
+ testctty("child3: after close of master");
+ printf("child3: attempting reopen of slave\n");
+ fflush(stdout);
+ slavefd = open(slave, O_RDWR|O_NONBLOCK);
+ if (slavefd < 0) {
+ printf("child3: failed reopen of slave after master close: "
+ "errno=%ld (%s)\n", (long)errno, strerror(errno));
+ wrsync(p1p[1], 0, "[04] child3->parent");
+ fflush(stdout);
+ exit(0);
+ }
+ if (fcntl(slavefd, F_SETFL, 0) == -1) {
+ perror("child3: fcntl");
+ wrsync(p1p[1], 2, "[04] child3->parent");
+ exit(1);
+ }
+#ifdef TIOCSCTTY
+ ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+ printf("child3: reopened slave after master close\n");
+ testctty("child3: after reopen of slave after master close");
+ testwr(slavefd, "child3: after reopen of slave after master close");
+ testex(slavefd, "child3: after reopen of slave after master close");
+ n = write(slavefd, "foo", 4);
+ if (n < 0) {
+ printf("child3: writing to slave of closed master: errno=%ld (%s)\n",
+ (long)errno, strerror(errno));
+ wrsync(p1p[1], 1, "[04] child3->parent");
+ } else {
+ printf("child3: wrote %d byes to slave of closed master\n", n);
+ fflush(stdout);
+ wrsync(p1p[1], 2, "[04] child3->parent");
+ }
+ rdsync(pp1[0], NULL, "[05] parent->child3");
+ testex(slavefd, "child3: after parent reopen of master");
+ testwr(slavefd, "child3: after parent reopen of master");
+ fflush(stdout);
+ n = write(slavefd, "bar", 4);
+ if (n < 0) {
+ perror("child3: writing to slave");
+ } else {
+ printf("child3: wrote %d bytes to slave\n", n);
+ fflush(stdout);
+ }
+ wrsync(p1p[1], 0, "[06] child3->parent");
+ rdsync(pp1[0], NULL, "[07] parent->child3");
+ wrsync(p1p[1], 0, "[08] child3->parent");
+ exit(0);
+}
+
+void
+child2(void)
+{
+ struct sigaction sa;
+
+ close(p21[0]);
+ setpgid(0, 0);
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = handler;
+ if (sigaction(SIGHUP, &sa, NULL) < 0) {
+ wrsync(p21[1], 1, "[00] child2->child1");
+ perror("child2: sigaction");
+ fflush(stdout);
+ exit(1);
+ }
+ printf("child2: set up signal handler\n");
+ testctty("child2: after start");
+ testwr(slavefd, "child2: after start");
+ wrsync(p21[1], 0, "[00] child2->child1");
+ rdsync(pp1[0], NULL, "[01] parent->child2");
+
+ testctty("child2: after child1 exit");
+ testex(slavefd, "child2: after child1 exit");
+ testwr(slavefd, "child2: after child1 exit");
+ close(slavefd);
+ testctty("child2: after close of slavefd");
+ slavefd = open(slave, O_RDWR|O_NONBLOCK);
+ if (slavefd < 0) {
+ wrsync(p1p[1], 1, "[02] child2->parent");
+ printf("child2: failed reopen of slave\n");
+ fflush(stdout);
+ exit(1);
+ }
+#ifdef TIOCSCTTY
+ ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+ printf("child2: reopened slave\n");
+ testctty("child2: after reopen of slave");
+ fflush(stdout);
+ close(slavefd);
+ pid3 = fork();
+ if (!pid3) {
+ child3();
+ } else if (pid3 == -1) {
+ wrsync(p1p[1], 1, "[02] child2->parent");
+ perror("child2: fork of child3");
+ exit(1);
+ }
+ printf("child2: forked child3=%ld\n", (long)pid3);
+ fflush(stdout);
+ exit(0);
+}
+
+void
+child1(void)
+{
+ int status;
+
+#if 0
+ setuid(1);
+#endif
+ close(pp1[1]);
+ close(p1p[0]);
+ close(masterfd);
+ ptyint_void_association();
+ slavefd = open(slave, O_RDWR|O_NONBLOCK);
+ if (slavefd < 0) {
+ perror("child1: open slave");
+ exit(1);
+ }
+#ifdef TIOCSCTTY
+ ioctl(slavefd, TIOCSCTTY, 0);
+#endif
+
+ printf("child1: opened slave\n");
+ testctty("child1: after slave open");
+
+ if (pipe(p21) < 0) {
+ perror("pipe child2->child1");
+ exit(1);
+ }
+ pid2 = fork();
+ if (!pid2) {
+ child2();
+ } else if (pid2 == -1) {
+ perror("child1: fork child2");
+ exit(1);
+ }
+ close(p21[1]);
+ printf("child1: forked child2=%ld\n", (long)pid2);
+ fflush(stdout);
+ rdsync(p21[0], &status, "[00] child2->child1");
+ exit(status);
+}
+
+int
+main(int argc, char *argv[])
+{
+ long retval;
+ int status;
+ char buf[4];
+ int n;
+
+ prog = argv[0];
+
+ printf("parent: pid=%ld\n", (long)getpid());
+
+ retval = ptyint_getpty_ext(&masterfd, slave, sizeof(slave), 0);
+
+ if (retval) {
+ com_err(prog, retval, "open master");
+ exit(1);
+ }
+#if 0
+ chown(slave, 1, -1);
+#endif
+ printf("parent: master opened; slave=%s\n", slave);
+ fflush(stdout);
+
+#if defined(HAVE_GRANTPT) && defined(HAVE_STREAMS)
+#ifdef O_NOCTTY
+ printf("parent: attempting to open slave before unlockpt\n");
+ fflush(stdout);
+ slavefd = open(slave, O_RDWR|O_NONBLOCK|O_NOCTTY);
+ if (slavefd < 0) {
+ printf("parent: failed slave open before unlockpt errno=%ld (%s)\n",
+ (long)errno, strerror(errno));
+ } else {
+ printf("parent: WARNING: "
+ "succeeded in opening slave before unlockpt\n");
+ }
+ close(slavefd);
+#endif
+ if (grantpt(masterfd) < 0) {
+ perror("parent: grantpt");
+ exit(1);
+ }
+ if (unlockpt(masterfd) < 0) {
+ perror("parent: unlockpt");
+ exit(1);
+ }
+#endif /* HAVE_GRANTPT && HAVE_STREAMS */
+
+ if (pipe(pp1) < 0) {
+ perror("pipe parent->child1");
+ exit(1);
+ }
+ if (pipe(p1p) < 0) {
+ perror("pipe child1->parent");
+ exit(1);
+ }
+
+ pid1 = fork();
+ if (!pid1) {
+ child1();
+ } else if (pid1 == -1) {
+ perror("fork of child1");
+ exit(1);
+ }
+ printf("parent: forked child1=%ld\n", (long)pid1);
+ fflush(stdout);
+ if (waitpid(pid1, &status1, 0) < 0) {
+ perror("waitpid for child1");
+ exit(1);
+ }
+ printf("parent: child1 exited, status=%d\n", status1);
+ if (status1)
+ exit(status1);
+
+ wrsync(pp1[1], 0, "[01] parent->child2");
+ rdsync(p1p[0], &status, "[02] child3->parent");
+ if (status) {
+ fprintf(stderr, "child2 or child3 got an error\n");
+ exit(1);
+ }
+
+ printf("parent: closing master\n");
+ fflush(stdout);
+ close(masterfd);
+ chmod(slave, 0666);
+ printf("parent: closed master\n");
+ wrsync(pp1[1], 0, "[03] parent->child3");
+
+ rdsync(p1p[0], &status, "[04] child3->parent");
+ switch (status) {
+ case 1:
+ break;
+ case 0:
+ exit(0);
+ default:
+ fprintf(stderr, "child3 got an error\n");
+ fflush(stdout);
+ exit(1);
+ }
+
+ retval = pty_getpty(&masterfd, slave2, sizeof(slave2));
+ printf("parent: new master opened; slave=%s\n", slave2);
+#if 0
+#ifdef HAVE_REVOKE
+ printf("parent: revoking\n");
+ revoke(slave2);
+#endif
+#endif
+ fflush(stdout);
+ wrsync(pp1[1], 0, "[05] parent->child3");
+ rdsync(p1p[0], NULL, "[06] child3->parent");
+
+ n = read(masterfd, buf, 4);
+ if (n < 0) {
+ perror("parent: reading from master");
+ } else {
+ printf("parent: read %d bytes (%.*s) from master\n", n, n, buf);
+ fflush(stdout);
+ }
+ chmod(slave2, 0666);
+ close(masterfd);
+ wrsync(pp1[1], 0, "[07] parent->child3");
+ rdsync(p1p[0], NULL, "[08] child3->parent");
+ fflush(stdout);
+ exit(0);
+}
diff --git a/src/util/pty/sane_hostname.c b/src/util/pty/sane_hostname.c
index 43814df..8881fde 100644
--- a/src/util/pty/sane_hostname.c
+++ b/src/util/pty/sane_hostname.c
@@ -42,7 +42,7 @@ pty_make_sane_hostname(struct sockaddr_in *addr,
char **out)
{
struct hostent *hp;
-#ifndef NO_UT_HOST
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
struct utmp ut;
#else
struct utmpx utx;
@@ -55,7 +55,7 @@ pty_make_sane_hostname(struct sockaddr_in *addr,
if (maxlen && maxlen < 16)
/* assume they meant 16, otherwise IP addr won't fit */
maxlen = 16;
-#ifndef NO_UT_HOST
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
ut_host_len = sizeof (ut.ut_host);
#else
ut_host_len = sizeof (utx.ut_host);
diff --git a/src/util/pty/update_utmp.c b/src/util/pty/update_utmp.c
index 0c089d6..72c41be 100644
--- a/src/util/pty/update_utmp.c
+++ b/src/util/pty/update_utmp.c
@@ -1,8 +1,7 @@
/*
* pty_update_utmp: Update or create a utmp entry
*
- * Copyright 1995 by the Massachusetts Institute of Technology.
- *
+ * Copyright 1995, 2001 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -17,7 +16,296 @@
* M.I.T. makes no representations about the suitability
* of this software for any purpose. It is provided "as is" without
* express or implied warranty.
- *
+ */
+
+/*
+ * Rant about the historical vagaries of utmp:
+ * -------------------------------------------
+ *
+ * There exist many subtly incompatible incarnations of utmp, ranging
+ * from BSD to System V to Unix98 and everywhere in between. This
+ * rant attempts to collect in one place as much knowledge as possible
+ * about this portability nightmare.
+ *
+ * BSD:
+ * ----
+ *
+ * The simplest (and earliest? possibly dating back to Version 7...)
+ * case is 4.x BSD utmp/wtmp. There are no auxiliary files. There is
+ * only a struct utmp, declared in utmp.h. Its contents usually
+ * include:
+ *
+ * char ut_line[]
+ * char ut_name[]
+ * char ut_host[]
+ * long ut_time
+ *
+ * The meanings of these fields follow their names reasonbly well.
+ * The ut_line field usually is the pathname of the tty device
+ * associated with the login, with the leading "/dev/" stripped off.
+ *
+ * It is believed that ut_host is nul-terminated, while the other
+ * strings are merely nul-padded.
+ *
+ * Generally, ut_name is an empty string for a logout record in both
+ * utmp and wtmp. For entries made by the window system or other
+ * terminal emulation stuff, ut_host is an empty string (at least
+ * under SunOS 4.x, it seems). The macro nonuser() is used to
+ * determine this if a utmp entry is made by the window system on at
+ * least SunOS 4.x.
+ *
+ * The native login never clears its own utmp entry or writes its own
+ * logout record; its parent (one of init, rlogind, telnetd, etc.)
+ * should handle that. In theory, getty could do that, but getty
+ * usually doesn't fork to exec login.
+ *
+ * Old (c. 1984) System V:
+ * -----------------------
+ *
+ * This is partially conjecture, based on some reading of
+ * /usr/xpg2include/utmp.h on a SunOS 4.x system. There appears to
+ * only be a struct utmp, declared in utmp.h. It is likely used for
+ * both utmp and wtmp files. It is quite likely that the utmp is only
+ * supposed to be accessed via the getutline()/pututline() API. The
+ * contents of struct utmp seem to include:
+ *
+ * char ut_user[]
+ * char ut_id[]
+ * char ut_line[]
+ * short ut_pid
+ * short ut_type
+ * struct exit_status ut_exit
+ * time_t ut_time
+ *
+ * On these systems, ut_name is often #define'ed to be ut_user to be
+ * somewhat compatible with the BSD-style utmp. Note that there is
+ * not necessarily a ut_host field in this utmp structure.
+ *
+ * The ut_id field bears some explanation. The systems that use this
+ * style of utmp also use a sysV-ish init, which starts processes out
+ * of /etc/inittab rather than /etc/ttys, and has the concept of
+ * runlevels. The first field in each line of /etc/inittab contains a
+ * unique ID field. init probably gets really confused if there are
+ * conflicts here. Every process that init starts gets its own entry
+ * written to utmp.
+ *
+ * It is possible for multiple entries to have the same ut_line but
+ * different ut_id values, since the sysadmin will be responsible for
+ * assigning values to ut_id. Usually, ut_id is four characters,
+ * while the permissible unique ID values for entries in /etc/inittab
+ * are constrained to two characters, but this is not always the
+ * case. In the case where we are emulating the vendor's login
+ * program and being run out of getty, we need to account for which
+ * value of ut_id was used by the getty, since pututline() will search
+ * based on ut_id and not ut_line for some reason.
+ *
+ * The ut_pid and ut_type fields are used for bookkeeping by init.
+ * The ut_type field gets the value INIT_PROCESS for processes started
+ * by init. It gets the value LOGIN_PROCESS if it is a process that
+ * is prompting for a login name, and it gets the value USER_PROCESS
+ * for an actual valid login. When the process dies, either init
+ * cleans up after it and records a DEAD_PROCESS entry in utmp, or the
+ * process itself does so. It's not completely clear which actually
+ * happens, though it is quite possible that init only cleans up after
+ * processes that it starts itself.
+ *
+ * Other values of ut_type exist; they're largely internal bookkeeping
+ * for init's runlevels and such, and don't really interest this
+ * library at all.
+ *
+ * The ut_exit field contains the following members:
+ *
+ * short e_termination
+ * short e_exit
+ *
+ * It is not clear how these values are used; presumably they record
+ * the process termination status of dead processes.
+ *
+ * There is no uniform API for manipulating wtmp on systems that use
+ * this sort of utmp structure; it can be assumed that the structure
+ * can be directly written to the wtmp file.
+ *
+ * Unix98:
+ * -------
+ *
+ * This description also likely applies to later System V derivatives
+ * as well as systems conforming to earlier X/Open standards such as
+ * XPG4. There is a new header, utmpx.h, which defines a struct utmpx
+ * and a new getutxline()/pututxline() API for accessing it. Some
+ * systems actually have a utmpx file on disk; others use the utmpx
+ * API to access a file named utmp, just to further confuse matters.
+ *
+ * The utmpx structure is guaranteed (by Unix98) to contain at least
+ * the following:
+ *
+ * char ut_user[]
+ * char ut_line[]
+ * char ut_id[]
+ * pid_t ut_pid
+ * short ut_type
+ * struct timeval ut_tv
+ *
+ * It is not guaranteed to contain, but often does contain, the
+ * following:
+ *
+ * char ut_host[]
+ * int ut_syslen
+ * int ut_session
+ * struct exit_status ut_exit
+ *
+ * The ut_syslen field, on systems that contain it, contains the
+ * number of significant characters in ut_host, including the
+ * terminating nul character.
+ *
+ * The main difference between this struct utmpx and the struct utmp
+ * used by early sysV derivatives is the change from a time_t or long
+ * for ut_time to a struct timeval for ut_tv.
+ *
+ * Comments in various header files imply that ut_session is used for
+ * window systems, but it's not clear how. Perhaps it contains the
+ * session ID of the session running the window system, e.g. the xdm
+ * or X server on an X11 system.
+ *
+ * Most of the description of the earlier sysV format probably applies
+ * here, with suitable changes of names. On systems that maintain
+ * utmpx and utmp files in parallel, it is assumed that using the
+ * pututxline() API is sufficient to keep them in sync. There are no
+ * known counterexamples to this.
+ *
+ * Nevertheless, there are, on some systems, API functions getutmp()
+ * and getutmpx() that appear to convert from struct utmpx to struct
+ * utmp and vice versa. This could be useful when there is a wtmp
+ * file but not a corresponding wtmpx file.
+ *
+ * Incidentally, ut_exit is sometimes present in the struct utmp but
+ * not the struct utmpx for a given system. Sometimes, it exists in
+ * both, but contains differently named members. It's probably one of
+ * the least portable pieces in this whole mess.
+ *
+ * Known Quirks of Specific OSes:
+ * ------------------------------
+ *
+ * Solaris 2.x:
+ *
+ * Has utmpd, which will automatically clean up utmpx, utmp, wtmpx,
+ * wtmp after process termination, provided that pututxline() was
+ * used.
+ *
+ * Solaris 8 seems to have a bug in utmpname() that causes
+ * garbage filenames to be generated. Solaris 7 (and possibly Solaris
+ * 8) have a bug in utmpxname() that prevents them from looking at
+ * anything other than /var/adm/utmpx, it seems. For some reason,
+ * though, utmpname() goes and looks at the corresponding utmpx file.
+ *
+ * Solaris 7 (and may be 8 as well) has a bug in pututline() that
+ * interacts badly with prior invocation of getutline(): if
+ * getutline() finds an entry, calling pututline() without first
+ * calling setutent() will overwrite the record following the one that
+ * was intended.
+ *
+ * Also, ut_exit in utmpx contains ut_e_termination and
+ * ut_e_exit (otherwise it contains the expected e_termination and
+ * e_exit) only if _XPG4_2 is defined and __EXTENSIONS__ is not, which
+ * is not a compilation environment we're likely to encourage. The
+ * ut_exit field of utmp contains the expected fields.
+ *
+ * If _XPG4_2 is not defined or __EXTENSIONS__ is defined, the
+ * functions getutmp(), getutmpx(), updwtmp(), and updwtmpx() are
+ * available, as well as the undocumented functions makeutx() and
+ * modutx().
+ *
+ * All the files utmp, utmpx, wtmp, and wtmpx exist.
+ *
+ * HP-UX 10.x:
+ *
+ * There is a curious interaction between how we allocate pty masters
+ * and how ttyname() works. It seems that if /dev/ptmx/clone is
+ * opened, a call to ptsname() on the master fd gets a filename of the
+ * form /dev/pty/tty[pqrs][0-9a-f], while ttyname() called on a fd
+ * opened with that filename returns a filename of the form
+ * /dev/tty[pqrs][0-9a-f] instead. These two filenames are actually
+ * hardlinks to the same special device node, so it shouldn't be a
+ * security problem.
+ *
+ * We can't call ttyname() in the parent because it would involve
+ * possibly acquiring a controlling terminal (which would be
+ * potentially problematic), so we have to resort to some trickery in
+ * order to ensure that the ut_line in the wtmp logout and login
+ * records match. If they don't match, various utilities such as last
+ * will get confused. Of course it's likely an OS bug that ttyname()
+ * and ptsname() are inconsistent in this way, but it's one that isn't
+ * too painful to work around.
+ *
+ * It seems that the HP-UX native telnetd has problems similar to ours
+ * in this area, though it manages to write the correct logout record
+ * to wtmp somehow. It probably does basically what we do here:
+ * search for a record with a matching ut_pid and grab its ut_line for
+ * writing into the logout record. Interestingly enough, its
+ * LOGIN_PROCESS record is of the form pty/tty[pqrs][0-9][a-f].
+ *
+ * Uses four-character unique IDs for /etc/inittab, which means that
+ * programs not running out of init should use two-character ut_id
+ * fields to avoid conflict.
+ *
+ * In utmpx, ut_exit contains __e_termination and __e_exit, while
+ * ut_exit in utmp contains the expected fields.
+ *
+ * There is no wtmpx file, despite there being utmp and utmpx files.
+ *
+ * Irix 6.x:
+ *
+ * In utmpx, ut_exit contains __e_termination and __e_exit, which get
+ * #define aliases e_termination and e_exit if _NO_XOPEN4 is true.
+ * Curiously enough, utmp.h declares ut_exit to have __e_termination
+ * and __e_exit as well, but does #define e_termination
+ * __e_termination, etc. if another header (utmpx.h) hasn't already
+ * declared struct __exit_status. It seems that the default
+ * compilation environment has the effect of making _NO_XOPEN4 true
+ * though.
+ *
+ * If _NO_XOPEN4 is true, getutmp(), getutmpx(), updwtmp(), and
+ * updwtmpx() are available, as well as the undocumented functions
+ * makeutx() and modutx().
+ *
+ * All the files utmp, utmpx, wtmp, and wtmpx exist.
+ *
+ * Tru64 Unix 4.x:
+ *
+ * In utmpx, ut_exit contains ut_termination and ut_exit, while utmp
+ * contains the expected fields. The files utmp and wtmp seem to
+ * exist, but not utmpx or wtmpx.
+ *
+ * When writing a logout entry, the presence of a non-empty username
+ * confuses last.
+ *
+ * AIX 4.3.x:
+ *
+ * The ut_exit field seems to exist in utmp, but not utmpx. The files
+ * utmp and wtmp seem to exist, but not utmpx, or wtmpx.
+ *
+ * libpty Implementation Decisions:
+ * --------------------------------
+ *
+ * We choose to use the pututxline() whenever possible, falling back
+ * to pututline() and calling write() to write out struct utmp if
+ * necessary. The code to handle pututxline() and pututline() is
+ * rather similar, since the structure members are quite similar, and
+ * we make the assumption that it will never be necessary to call
+ * both. This allows us to avoid duplicating lots of code, by means
+ * of some slightly demented macros.
+ *
+ * If neither pututxline() nor pututline() are available, we assume
+ * BSD-style utmp files and behave accordingly, writing the structure
+ * out to disk ourselves.
+ *
+ * On systems where updwtmpx() or updwtmp() are available, we use
+ * those to update the wtmpx or wtmp file. When they're not
+ * available, we write the utmpx or utmp structure out to disk
+ * ourselves, though sometimes conversion from utmpx to utmp format is
+ * needed.
+ *
+ * We assume that at logout the system is ok with with having an empty
+ * username both in utmp and wtmp.
*/
#include <com_err.h>
@@ -32,178 +320,387 @@
#ifndef UTMP_FILE
#define UTMP_FILE "/etc/utmp"
#endif
-#ifndef NO_UT_PID
-#define WTMP_REQUIRES_USERNAME
-#endif
-long pty_update_utmp (process_type, pid, username, line, host, flags)
- int process_type;
- int pid;
- char *username, *line, *host;
- int flags;
-{
- struct utmp ent, ut;
-#ifndef HAVE_SETUTENT
- struct stat statb;
- int tty;
-#endif
+
+/*
+ * The following grossness exists to avoid duplicating lots of code
+ * between the cases where we have an old-style sysV utmp and where we
+ * have a modern (Unix98 or XPG4) utmpx. See the above history rant
+ * for further explanation.
+ */
+#if defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT)
#ifdef HAVE_SETUTXENT
- struct utmpx utx;
-#endif
-#ifndef NO_UT_PID
- char *tmpx;
- char utmp_id[5];
+#define PTY_STRUCT_UTMPX struct utmpx
+#define PTY_SETUTXENT setutxent
+#define PTY_GETUTXENT getutxent
+#define PTY_GETUTXLINE getutxline
+#define PTY_PUTUTXLINE pututxline
+#define PTY_ENDUTXENT endutxent
+#else
+#define PTY_STRUCT_UTMPX struct utmp
+#define PTY_SETUTXENT setutent
+#define PTY_GETUTXENT getutent
+#define PTY_GETUTXLINE getutline
+#define PTY_PUTUTXLINE pututline
+#define PTY_ENDUTXENT endutent
#endif
- char userbuf[32];
- int fd;
- strncpy(ent.ut_line, line+sizeof("/dev/")-1, sizeof(ent.ut_line));
- ent.ut_time = time(0);
-#ifdef NO_UT_PID
- if (process_type == PTY_LOGIN_PROCESS)
+static int better(const PTY_STRUCT_UTMPX *, const PTY_STRUCT_UTMPX *,
+ const PTY_STRUCT_UTMPX *);
+static int match_pid(const PTY_STRUCT_UTMPX *,
+ const PTY_STRUCT_UTMPX *);
+static PTY_STRUCT_UTMPX *best_utxent(const PTY_STRUCT_UTMPX *);
+
+/*
+ * Utility function to determine whether A is a better match for
+ * SEARCH than B. Should only be called by best_utxent().
+ */
+static int
+better(const PTY_STRUCT_UTMPX *search,
+ const PTY_STRUCT_UTMPX *a, const PTY_STRUCT_UTMPX *b)
+{
+ if (strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) {
+ if (!strncmp(search->ut_id, a->ut_id, sizeof(a->ut_id))) {
+ return 1;
+ }
+ }
+
+ if (strncmp(a->ut_id, b->ut_id, sizeof(b->ut_id))) {
+ /* Got different UT_IDs; find the right one. */
+ if (!strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) {
+ /* Old entry already matches; use it. */
+ return 0;
+ }
+ if (a->ut_type == LOGIN_PROCESS
+ && b->ut_type != LOGIN_PROCESS) {
+ /* Prefer LOGIN_PROCESS */
+ return 1;
+ }
+ if (search->ut_type == DEAD_PROCESS
+ && a->ut_type == USER_PROCESS
+ && b->ut_type != USER_PROCESS) {
+ /*
+ * Try USER_PROCESS if we're entering a DEAD_PROCESS.
+ */
+ return 1;
+ }
+ return 0;
+ } else {
+ /*
+ * Bad juju. We shouldn't get two entries with identical
+ * ut_id fields for the same value of ut_line. pututxline()
+ * will probably pick the first entry, in spite of the strange
+ * state of utmpx, if we rewind with setutxent() first.
+ *
+ * For now, return 0, to force the earlier entry to be used.
+ */
+ return 0;
+ }
+}
+
+static int
+match_pid(const PTY_STRUCT_UTMPX *search, const PTY_STRUCT_UTMPX *u)
+{
+ if (u->ut_type != LOGIN_PROCESS && u->ut_type != USER_PROCESS)
return 0;
-#else /* NO_UT_PID */
- ent.ut_pid = pid;
+ if (u->ut_pid == search->ut_pid) {
+ /*
+ * One of ut_line or ut_id should match, else some nastiness
+ * may result. We can fall back to searching by ut_line if
+ * need be. This should only really break if we're login.krb5
+ * running out of getty, or we're cleaning up after the vendor
+ * login, and either the vendor login or the getty has
+ * different ideas than we do of what both ut_id and ut_line
+ * should be. It should be rare, though. We may want to
+ * remove this restriction later.
+ */
+ if (!strncmp(u->ut_line, search->ut_line, sizeof(u->ut_line)))
+ return 1;
+ if (!strncmp(u->ut_id, search->ut_id, sizeof(u->ut_id)))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * This expects to be called with SEARCH pointing to a struct utmpx
+ * with its ut_type equal to USER_PROCESS or DEAD_PROCESS, since if
+ * we're making a LOGIN_PROCESS entry, we presumably don't care about
+ * preserving existing state. At the very least, the ut_pid, ut_line,
+ * ut_id, and ut_type fields must be filled in by the caller.
+ */
+static PTY_STRUCT_UTMPX *
+best_utxent(const PTY_STRUCT_UTMPX *search)
+{
+ PTY_STRUCT_UTMPX utxtmp, *utxp;
+ int i, best;
+
+ memset(&utxtmp, 0, sizeof(utxtmp));
+
+ /*
+ * First, search based on pid, but only if non-zero.
+ */
+ if (search->ut_pid) {
+ i = 0;
+ PTY_SETUTXENT();
+ while ((utxp = PTY_GETUTXENT()) != NULL) {
+ if (match_pid(search, utxp)) {
+ return utxp;
+ }
+ i++;
+ }
+ }
+ /*
+ * Uh-oh, someone didn't enter our pid. Try valiantly to search
+ * by terminal line.
+ */
+ i = 0;
+ best = -1;
+ PTY_SETUTXENT();
+ while ((utxp = PTY_GETUTXLINE(search)) != NULL) {
+ if (better(search, utxp, &utxtmp)) {
+ utxtmp = *utxp;
+ best = i;
+ }
+ memset(utxp, 0, sizeof(*utxp));
+ i++;
+ }
+ if (best == -1)
+ return NULL;
+ PTY_SETUTXENT();
+ for (i = 0; i <= best; i++) {
+ if (utxp != NULL)
+ memset(utxp, 0, sizeof(*utxp));
+ utxp = PTY_GETUTXLINE(search);
+ }
+ return utxp;
+}
+
+/*
+ * All calls to this function for a given login session must have the
+ * pids be equal; various things will break if this is not the case,
+ * since we do some searching based on the pid. Note that if a parent
+ * process calls this via pty_cleanup(), it should still pass the
+ * child's pid rather than its own.
+ */
+long
+pty_update_utmp(int process_type, int pid, const char *username,
+ const char *line, const char *host, int flags)
+{
+ PTY_STRUCT_UTMPX utx, *utxtmp, utx2;
+ const char *cp;
+ size_t len;
+ char utmp_id[5];
+
+ /*
+ * Zero things out in case there are fields we don't handle here.
+ * They tend to be non-portable anyway.
+ */
+ memset(&utx, 0, sizeof(utx));
+ utxtmp = NULL;
+ cp = line;
+ if (strncmp(cp, "/dev/", sizeof("/dev/") - 1) == 0)
+ cp += sizeof("/dev/") - 1;
+ strncpy(utx.ut_line, cp, sizeof(utx.ut_line));
+ utx.ut_pid = pid;
switch (process_type) {
case PTY_LOGIN_PROCESS:
- ent.ut_type = LOGIN_PROCESS;
+ utx.ut_type = LOGIN_PROCESS;
break;
case PTY_USER_PROCESS:
- ent.ut_type = USER_PROCESS;
+ utx.ut_type = USER_PROCESS;
break;
case PTY_DEAD_PROCESS:
- ent.ut_type = DEAD_PROCESS;
+ utx.ut_type = DEAD_PROCESS;
break;
default:
return PTY_UPDATE_UTMP_PROCTYPE_INVALID;
}
-#endif /*NO_UT_PID*/
-
-#ifndef NO_UT_HOST
- if (host)
- strncpy(ent.ut_host, host, sizeof(ent.ut_host));
+ len = strlen(line);
+ if (len >= 2) {
+ cp = line + len - 1;
+ if (*(cp - 1) != '/')
+ cp--; /* last two characters, unless it's a / */
+ } else
+ cp = line;
+ /*
+ * HP-UX has mostly 4-character inittab ids, while most other sysV
+ * variants use only 2-charcter inittab ids, so to avoid
+ * conflicts, we pick 2-character ut_ids for our own use. We may
+ * want to feature-test for this, but it would be somewhat of a
+ * pain, and would eit cross-compiling.
+ */
+#ifdef __hpux
+ strcpy(utmp_id, cp);
+#else
+ if (len > 2 && *(cp - 1) != '/')
+ sprintf(utmp_id, "k%s", cp - 1);
else
- ent.ut_host[0] = '\0';
+ sprintf(utmp_id, "k0%s", cp);
#endif
+ strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id));
+ /*
+ * Get existing utmpx entry for PID or LINE, if any, so we can
+ * copy some stuff from it. This is particularly important if we
+ * are login.krb5 and are running out of getty, since getty will
+ * have written the entry for the line with ut_type ==
+ * LOGIN_PROCESS, and what it has recorded in ut_id may not be
+ * what we come up with, since that's up to the whim of the
+ * sysadmin who writes the inittab entry.
+ *
+ * Note that we may be screwed if we try to write a logout record
+ * for a vendor's login program, since it may construct ut_line
+ * and ut_id differently from us; even though we search on ut_pid,
+ * we validate against ut_id or ut_line to sanity-check. We may
+ * want to rethink whether to actually include this check, since
+ * it should be highly unlikely that there will be a bogus entry
+ * in utmpx matching our pid.
+ */
+ if (process_type != PTY_LOGIN_PROCESS)
+ utxtmp = best_utxent(&utx);
-#ifndef NO_UT_PID
- if (!strcmp (line, "/dev/console")) {
-#if (defined(sun) && defined(__SVR4))
- strncpy (ent.ut_id, "co", 4);
-#else
- strncpy (ent.ut_id, "cons", 4);
-#endif
- } else {
- tmpx = line + strlen(line)-1;
- if (*(tmpx-1) != '/') tmpx--; /* last two characters, unless it's a / */
-#ifdef __hpux
- strcpy(utmp_id, tmpx);
+#ifdef HAVE_SETUTXENT
+ if (gettimeofday(&utx.ut_tv, NULL))
+ return errno;
#else
- sprintf(utmp_id, "kl%s", tmpx);
+ (void)time(&utx.ut_time);
#endif
- strncpy(ent.ut_id, utmp_id, sizeof(ent.ut_id));
- }
- strncpy(ent.ut_user, username, sizeof(ent.ut_user));
-#else
- strncpy(ent.ut_name, username, sizeof(ent.ut_name));
+ /*
+ * On what system is there not ut_host? Unix98 doesn't mandate
+ * this field, but we have yet to see a system that supports utmpx
+ * that doesn't have it. For what it's worth, some ancient utmp
+ * headers on svr4 systems imply that there's no ut_host in struct
+ * utmp...
+ */
+#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_HOST)) \
+ || (!defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_HOST))
+ if (host != NULL) {
+ strncpy(utx.ut_host, host, sizeof(utx.ut_host));
+ /* Unlike other things in utmpx, ut_host is nul-terminated? */
+ utx.ut_host[sizeof(utx.ut_host) - 1] = '\0';
+ } else
+ utx.ut_host[0] = '\0';
+#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_SYSLEN)) \
+ || (!defined (HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_SYSLEN))
+ if (host != NULL)
+ utx.ut_syslen = strlen(utx.ut_host) + 1;
+ else
+ utx.ut_syslen = 0;
#endif
- if(username[0])
- strncpy(userbuf, username, sizeof(userbuf));
- else userbuf[0] = '\0';
-
-#ifdef HAVE_SETUTENT
-
- utmpname(UTMP_FILE);
- setutent();
-/* If we need to preserve the user name in the wtmp structure and
- * Our flags tell us we can obtain it from the utmp and we succeed in
- * obtaining it, we then save the utmp structure we obtain, write
- * out the utmp structure and change the username pointer so it is used by
- * update_wtmp.*/
-#ifdef WTMP_REQUIRES_USERNAME
- if (( !username[0]) && (flags&PTY_UTMP_USERNAME_VALID)
- &&line)
- {
- struct utmp *utptr;
- strncpy(ut.ut_line, line, sizeof(ut.ut_line));
- utptr = getutline(&ut);
- if (utptr)
- strncpy(userbuf,utptr->ut_user,sizeof(ut.ut_user));
- }
#endif
- pututline(&ent);
- endutent();
-
+ /* XXX deal with ut_addr? */
+
+ if (utxtmp != NULL) {
+ /*
+ * For entries not of type LOGIN_PROCESS, override some stuff
+ * with what was in the previous entry we found, if any.
+ */
+ strncpy(utx.ut_id, utxtmp->ut_id, sizeof(utx.ut_id));
+ utx.ut_pid = utxtmp->ut_pid;
+ }
+
+ strncpy(utx.ut_user, username, sizeof(utx.ut_user));
+
+ /*
+ * Make a copy now and deal with copying relevant things out of
+ * utxtmp in case setutxline() or pututxline() clobbers utxtmp.
+ * (After all, the returned pointer from the getutx*() functions
+ * is allowed to point to static storage that may get overwritten
+ * by subsequent calls to related functions.)
+ */
+ utx2 = utx;
+ if (process_type == PTY_DEAD_PROCESS && utxtmp != NULL) {
+ /*
+ * Use ut_line from old entry to avoid confusing last on
+ * HP-UX.
+ */
+ strncpy(utx2.ut_line, utxtmp->ut_line, sizeof(utx2.ut_line));
+ }
+
+ PTY_SETUTXENT();
+ PTY_PUTUTXLINE(&utx);
+ PTY_ENDUTXENT();
+
+ /* Don't record LOGIN_PROCESS entries. */
+ if (process_type == PTY_LOGIN_PROCESS)
+ return 0;
+
#ifdef HAVE_SETUTXENT
- setutxent();
-#ifdef HAVE_GETUTMPX
- getutmpx(&ent, &utx);
+ return ptyint_update_wtmpx(&utx2);
#else
- /* For platforms like HPUX and Dec Unix which don't have getutmpx */
- strncpy(utx.ut_user, ent.ut_user, sizeof(ent.ut_user));
- strncpy(utx.ut_id, ent.ut_id, sizeof(ent.ut_id));
- strncpy(utx.ut_line, ent.ut_line, sizeof(ent.ut_line));
- utx.ut_pid = pid; /* kludge for Irix, etc. to avoid trunc. */
- utx.ut_type = ent.ut_type;
-#ifdef UT_EXIT_STRUCTURE_DIFFER
- utx.ut_exit.ut_exit = ent.ut_exit.e_exit;
-#else
-/* KLUDGE for now; eventually this will be a feature test... See PR#[40] */
-#ifdef __hpux
- utx.ut_exit.__e_termination = ent.ut_exit.e_termination;
- utx.ut_exit.__e_exit = ent.ut_exit.e_exit;
-#else
- /*xxx do nothing for now; we don't even know the structure member exists*/
-#endif
-#endif
- utx.ut_tv.tv_sec = ent.ut_time;
- utx.ut_tv.tv_usec = 0;
+ return ptyint_update_wtmp(&utx2);
#endif
+}
+
+#else /* !(HAVE_SETUTXENT || HAVE_SETUTENT) */
+
+long
+pty_update_utmp(int process_type, int pid, const char *username,
+ const char *line, const char *host, int flags)
+{
+ struct utmp ent, ut;
+ const char *cp;
+ int tty, lc, fd;
+ off_t seekpos;
+ ssize_t ret;
+ struct stat statb;
+
+ memset(&ent, 0, sizeof(ent));
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
if (host)
- strncpy(utx.ut_host, host, sizeof(utx.ut_host));
- else
- utx.ut_host[0] = 0;
- pututxline(&utx);
- endutxent();
-#endif /* HAVE_SETUTXENT */
+ strncpy(ent.ut_host, host, sizeof(ent.ut_host));
+#endif
+ strncpy(ent.ut_name, username, sizeof(ent.ut_name));
+ cp = line;
+ if (strncmp(cp, "/dev/", sizeof("/dev/") - 1) == 0)
+ cp += sizeof("/dev/") - 1;
+ strncpy(ent.ut_line, cp, sizeof(ent.ut_line));
+ (void)time(&ent.ut_time);
-#else /* HAVE_SETUTENT */
- if (flags&PTY_TTYSLOT_USABLE)
+ if (flags & PTY_TTYSLOT_USABLE)
tty = ttyslot();
else {
- int lc;
- tty = -1;
- if ((fd = open(UTMP_FILE, O_RDWR)) < 0)
- return errno;
- for (lc = 0;
- lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET) != -1;
- lc++) {
- if (read(fd, (char *) &ut, sizeof(struct utmp)) != sizeof(struct utmp))
- break;
- if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
- tty = lc;
-#ifdef WTMP_REQUIRES_USERNAME
- if (!username&&(flags&PTY_UTMP_USERNAME_VALID))
- strncpy(userbuf, ut.ut_user, sizeof(ut.ut_user));
-#endif
- break;
+ tty = -1;
+ fd = open(UTMP_FILE, O_RDONLY);
+ if (fd == -1)
+ return errno;
+ for (lc = 0; ; lc++) {
+ seekpos = lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET);
+ if (seekpos != (off_t)(lc * sizeof(struct utmp)))
+ break;
+ if (read(fd, (char *) &ut, sizeof(struct utmp))
+ != sizeof(struct utmp))
+ break;
+ if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
+ tty = lc;
+ break;
+ }
}
- }
- close(fd);
+ close(fd);
}
-
- if (tty > 0 && (fd = open(UTMP_FILE, O_WRONLY, 0)) >= 0) {
- (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
- (void)write(fd, (char *)&ent, sizeof(struct utmp));
- (void)close(fd);
+ if (tty > 0) {
+ fd = open(UTMP_FILE, O_WRONLY);
+ if (fd == -1)
+ return 0;
+ if (fstat(fd, &statb)) {
+ close(fd);
+ return 0;
+ }
+ seekpos = lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
+ if (seekpos != (off_t)(tty * sizeof(struct utmp))) {
+ close(fd);
+ return 0;
+ }
+ ret = write(fd, (char *)&ent, sizeof(struct utmp));
+ if (ret != sizeof(struct utmp)) {
+ ftruncate(fd, statb.st_size);
+ }
+ close(fd);
}
-
-
-#endif /* HAVE_SETUTENT */
-
/* Don't record LOGIN_PROCESS entries. */
if (process_type == PTY_LOGIN_PROCESS)
- return 0;
+ return 0;
else
- return ptyint_update_wtmp(&ent, host, userbuf);
+ return ptyint_update_wtmp(&ent);
}
+#endif
diff --git a/src/util/pty/update_wtmp.c b/src/util/pty/update_wtmp.c
index 7e8d573..f557d36 100644
--- a/src/util/pty/update_wtmp.c
+++ b/src/util/pty/update_wtmp.c
@@ -1,8 +1,7 @@
/*
- * ptyint_update_utmp: Update or create a utmp entry
- *
- * Copyright 1995 by the Massachusetts Institute of Technology.
+ * ptyint_update_wtmp: Update wtmp.
*
+ * Copyright 1995, 2001 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -28,7 +27,7 @@
#define WTMP_FILE _PATH_WTMP
#endif
-#if !defined(WTMPX_FILE) && defined(_PATH_WTMPX) && defined(HAVE_UPDWTMPX)
+#if !defined(WTMPX_FILE) && defined(_PATH_WTMPX)
#define WTMPX_FILE _PATH_WTMPX
#endif
@@ -37,82 +36,88 @@
#define WTMP_FILE "/usr/adm/wtmp"
#endif
-#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
-/* This is ugly, but the lack of standardization in the utmp/utmpx
- * space, and what glibc implements and doesn't make available, is
- * even worse.
- */
-#undef HAVE_UPDWTMPX /* Don't use updwtmpx for glibc 2.1 */
-#endif
+#ifdef HAVE_SETUTXENT
-long ptyint_update_wtmp (ent , host, user)
- struct utmp *ent;
- char *host;
- char *user;
+/*
+ * Welcome to conditional salad.
+ *
+ * This really wants to take a (const struct utmpx *) but updutmpx()
+ * on Solaris at least doesn't take a const argument. *sigh*
+ */
+long
+ptyint_update_wtmpx(struct utmpx *ent)
{
+#if !(defined(HAVE_UPDWTMPX) && defined(WTMPX_FILE))
struct utmp ut;
- struct stat statb;
- int fd;
- time_t uttime;
-#ifdef HAVE_UPDWTMPX
- struct utmpx utx;
-
- getutmpx(ent, &utx);
- if (host)
- strncpy(utx.ut_host, host, sizeof(utx.ut_host) );
- else
- utx.ut_host[0] = 0;
- if (user)
- strncpy(utx.ut_user, user, sizeof(utx.ut_user));
- updwtmpx(WTMPX_FILE, &utx);
#endif
-#ifdef HAVE_UPDWTMP
-#ifndef HAVE_UPDWTMPX
-/* This is already performed byupdwtmpx if present.*/
- updwtmp(WTMP_FILE, ent);
-#endif /* HAVE_UPDWTMPX*/
-#else /* HAVE_UPDWTMP */
+#if defined(HAVE_UPDWTMPX) && defined(WTMPX_FILE)
+ updwtmpx(WTMPX_FILE, ent);
+ return 0;
+#else
- if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) >= 0) {
- if (!fstat(fd, &statb)) {
- (void)memset((char *)&ut, 0, sizeof(ut));
-#ifdef __hpux
- strncpy (ut.ut_id, ent->ut_id, sizeof (ut.ut_id));
+#ifdef HAVE_GETUTMP
+ getutmp(ent, &ut);
+#else /* Emulate getutmp(). Yuck. */
+ memset(&ut, 0, sizeof(ut));
+ strncpy(ut.ut_name, ent->ut_user, sizeof(ut.ut_name));
+ strncpy(ut.ut_line, ent->ut_line, sizeof(ut.ut_line));
+ ut.ut_time = ent->ut_tv.tv_sec;
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(ut.ut_host, ent->ut_host, sizeof(ut.ut_host));
+ ut.ut_host[sizeof(ut.ut_host) - 1] = '\0';
+#ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
+ ut.ut_syslen = strlen(ut.ut_host) + 1;
#endif
- (void)strncpy(ut.ut_line, ent->ut_line, sizeof(ut.ut_line));
- (void)strncpy(ut.ut_name, ent->ut_name, sizeof(ut.ut_name));
-#ifndef NO_UT_HOST
- (void)strncpy(ut.ut_host, ent->ut_host, sizeof(ut.ut_host));
#endif
- (void)time(&uttime);
- ut.ut_time = uttime;
-#if defined(HAVE_GETUTENT) && defined(USER_PROCESS)
- if (ent->ut_name) {
- if (!ut.ut_pid)
- ut.ut_pid = getpid();
-#ifndef __hpux
- ut.ut_type = USER_PROCESS;
-#else
- ut.ut_type = ent->ut_type;
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+ strncpy(ut.ut_id, ent->ut_id, sizeof(ut.ut_id));
#endif
- } else {
-#ifdef EMPTY
- ut.ut_type = EMPTY;
-#else
- ut.ut_type = DEAD_PROCESS; /* For Linux brokenness*/
-#endif
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+ ut.ut_pid = ent->ut_pid;
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ ut.ut_type = ent->ut_type;
+#endif
+#if defined(PTY_UTMP_E_EXIT) && defined(PTY_UTMPX_E_EXIT)
+ ut.ut_exit.PTY_UTMP_E_EXIT = ent->ut_exit.PTY_UTMPX_E_EXIT;
+ ut.ut_exit.PTY_UTMP_E_TERMINATION =
+ ent->ut_exit.PTY_UTMPX_E_TERMINATION;
+#endif
+#endif /* !HAVE_GETUTMP */
+
+ return ptyint_update_wtmp(&ut);
+#endif /* !(defined(WTMPX_FILE) && defined(HAVE_UPDWTMPX)) */
+}
- }
+#endif /* HAVE_SETUTXENT */
+
+#if !(defined(WTMPX_FILE) && defined(HAVE_UPDWTMPX)) \
+ || !defined(HAVE_SETUTXENT)
+
+long
+ptyint_update_wtmp(struct utmp *ent)
+{
+#ifndef HAVE_UPDWTMP
+ int fd;
+ struct stat statb;
#endif
- if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
- sizeof(struct utmp))
- (void)ftruncate(fd, statb.st_size);
- }
+
+#ifdef HAVE_UPDWTMP
+ updwtmp(WTMP_FILE, ent);
+#else
+ fd = open(WTMP_FILE, O_WRONLY | O_APPEND, 0);
+ if (fd != -1 && !fstat(fd, &statb)) {
+ if (write(fd, (char *)ent, sizeof(struct utmp))
+ != sizeof(struct utmp))
+ (void)ftruncate(fd, statb.st_size);
(void)close(fd);
}
-#endif /* HAVE_UPDWTMP */
- return 0; /* no current failure cases; file not found is not failure!*/
-
+#endif
+ /*
+ * no current failure cases; file not found is not failure!
+ */
+ return 0;
}
+#endif
diff --git a/src/util/pty/void_assoc.c b/src/util/pty/void_assoc.c
index a6ec33d..4b7e26c 100644
--- a/src/util/pty/void_assoc.c
+++ b/src/util/pty/void_assoc.c
@@ -23,32 +23,27 @@
#include <com_err.h>
#include "libpty.h"
#include "pty-int.h"
-/*
- * This routine will be called twice. It's not particularly important
- * that the setsid() or TIOCSTTY ioctls succeed (they may not the
- * second time), but rather that we have a controlling terminal at the
- * end. It is assumed that vhangup doesn't exist and confuse the
- * process's notion of controlling terminal on any system without
- * TIOCNOTTY. That is, either vhangup() leaves the controlling
- * terminal in tact, breaks the association completely, or the system
- * provides TIOCNOTTY to get things back into a reasonable state. In
- * practice, vhangup() either breaks the association completely or
- * doesn't effect controlling terminals, so this condition is met.
- */
-long ptyint_void_association()
+/*
+ * This function gets called to set up the current process as a
+ * session leader (hence, can't be called except from a process that
+ * isn't already a session leader) and dissociates the controlling
+ * terminal (if any) from the session.
+ */
+long
+ptyint_void_association(void)
{
- int con_fd;
+ int fd;
#ifdef HAVE_SETSID
(void) setsid();
#endif
-
- /* Void tty association first */
+ /* Void tty association first */
#ifdef TIOCNOTTY
- if ((con_fd = open("/dev/tty", O_RDWR)) >= 0) {
- ioctl(con_fd, TIOCNOTTY, 0);
- close(con_fd);
- }
+ fd = open("/dev/tty", O_RDWR);
+ if (fd >= 0) {
+ ioctl(fd, TIOCNOTTY, 0);
+ close(fd);
+ }
#endif
- return 0;
+ return 0;
}
diff --git a/src/util/ss/ChangeLog b/src/util/ss/ChangeLog
index 8cac4b7..72063d7 100644
--- a/src/util/ss/ChangeLog
+++ b/src/util/ss/ChangeLog
@@ -1,3 +1,11 @@
+2000-05-01 Nalin Dahyabhai <nalin@redhat.com>
+
+ * help.c (ss_help): Don't overflow buffers "buffer" or "buf".
+ * list_rqs.c (ss_list_requests): Don't overflow buffer "buffer".
+ * mk_cmds.c (main): Don't overflow buffer "c_file".
+ * utils.c (generate_rqte): Update lengths of constant strings in
+ computing buffer size.
+
2000-02-01 Ken Raeburn <raeburn@mit.edu>
* listen.c (ss_listen): Local var END should be volatile.
diff --git a/src/util/ss/help.c b/src/util/ss/help.c
index e09b777..3c9cbec 100644
--- a/src/util/ss/help.c
+++ b/src/util/ss/help.c
@@ -53,16 +53,18 @@ void ss_help (argc, argv, sci_idx, info_ptr)
return;
}
for (idx = 0; info->info_dirs[idx] != (char *)NULL; idx++) {
- (void) strcpy(buffer, info->info_dirs[idx]);
- (void) strcat(buffer, "/");
- (void) strcat(buffer, argv[1]);
- (void) strcat(buffer, ".info");
+ (void) strncpy(buffer, info->info_dirs[idx], sizeof(buffer) - 1);
+ buffer[sizeof(buffer) - 1] = '\0';
+ (void) strncat(buffer, "/", sizeof(buffer) - 1 - strlen(buffer));
+ (void) strncat(buffer, argv[1], sizeof(buffer) - 1 - strlen(buffer));
+ (void) strncat(buffer, ".info", sizeof(buffer) - 1 - strlen(buffer));
if ((fd = open(&buffer[0], O_RDONLY)) >= 0) goto got_it;
}
if ((fd = open(&buffer[0], O_RDONLY)) < 0) {
char buf[MAXPATHLEN];
- strcpy(buf, "No info found for ");
- strcat(buf, argv[1]);
+ strncpy(buf, "No info found for ", sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ strncat(buf, argv[1], sizeof(buf) - 1 - strlen(buf));
ss_perror(sci_idx, 0, buf);
return;
}
diff --git a/src/util/ss/list_rqs.c b/src/util/ss/list_rqs.c
index cf2c931..045a0c8 100644
--- a/src/util/ss/list_rqs.c
+++ b/src/util/ss/list_rqs.c
@@ -87,23 +87,24 @@ ss_list_requests(argc, argv, sci_idx, info_ptr)
buffer[0] = '\0';
if (entry->flags & SS_OPT_DONT_LIST)
continue;
+ buffer[sizeof(buffer) - 1] = '\0';
for (name = entry->command_names; *name; name++) {
register int len = strlen(*name);
- strncat(buffer, *name, len);
+ strncat(buffer, *name, sizeof(buffer) - 1 - strlen(buffer));
spacing += len + 2;
if (name[1]) {
- strcat(buffer, ", ");
+ strncat(buffer, ", ", sizeof(buffer) - 1 - strlen(buffer));
}
}
if (spacing > 23) {
- strcat(buffer, NL);
+ strncat(buffer, NL, sizeof(buffer) - 1 - strlen(buffer));
fputs(buffer, output);
spacing = 0;
buffer[0] = '\0';
}
- strncat(buffer, twentyfive_spaces, 25-spacing);
- strcat(buffer, entry->info_string);
- strcat(buffer, NL);
+ strncat(buffer, twentyfive_spaces, sizeof(buffer) - 1 - (25-spacing));
+ strncpy(buffer + 25, entry->info_string, sizeof(buffer) - 1 - 25);
+ strncat(buffer, NL, sizeof(buffer) - 1 - strlen(buffer));
fputs(buffer, output);
}
}
diff --git a/src/util/ss/mk_cmds.c b/src/util/ss/mk_cmds.c
index 0bcd770..bba5edd 100644
--- a/src/util/ss/mk_cmds.c
+++ b/src/util/ss/mk_cmds.c
@@ -62,8 +62,9 @@ int main(argc, argv)
p = strrchr(path, '.');
*p = '\0';
q = rindex(path, '/');
- strcpy(c_file, (q) ? q + 1 : path);
- strcat(c_file, ".c");
+ strncpy(c_file, (q) ? q + 1 : path, sizeof(c_file) - 1);
+ c_file[sizeof(c_file) - 1] = '\0';
+ strncat(c_file, ".c", sizeof(c_file) - 1 - strlen(c_file));
*p = '.';
output_file = fopen(c_file, "w+");
diff --git a/src/util/ss/utils.c b/src/util/ss/utils.c
index 9698e70..c578001 100644
--- a/src/util/ss/utils.c
+++ b/src/util/ss/utils.c
@@ -61,13 +61,12 @@ char * generate_rqte(func_name, info_string, cmds, options)
var_name = generate_cmds_string(cmds);
generate_function_definition(func_name);
size = 6; /* " { " */
- size += strlen(var_name)+7; /* "quux, " */
- size += strlen(func_name)+7; /* "foo, " */
- size += strlen(info_string)+9; /* "\"Info!\", " */
+ size += strlen(var_name)+8; /* "quux, " */
+ size += strlen(func_name)+8; /* "foo, " */
+ size += strlen(info_string)+8; /* "\"Info!\", " */
sprintf(numbuf, "%d", options);
- size += strlen(numbuf);
- size += 4; /* " }," + NL */
- string = malloc(size * sizeof(char *));
+ size += strlen(numbuf)+5; /* " }," + NL + NUL */
+ string = malloc(size);
strcpy(string, " { ");
strcat(string, var_name);
strcat(string, ",\n ");