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/autoconf/autoconf.info262
-rw-r--r--src/util/db2/ChangeLog47
-rw-r--r--src/util/db2/btree/bt_close.c3
-rw-r--r--src/util/db2/btree/bt_debug.c21
-rw-r--r--src/util/db2/btree/bt_page.c2
-rw-r--r--src/util/db2/btree/bt_seq.c410
-rw-r--r--src/util/db2/btree/bt_split.c5
-rw-r--r--src/util/db2/btree/extern.h13
-rw-r--r--src/util/db2/hash/dbm.c5
-rw-r--r--src/util/db2/hash/hash_debug.c1
-rw-r--r--src/util/db2/include/ChangeLog6
-rw-r--r--src/util/db2/include/db.h2
-rw-r--r--src/util/db2/test/ChangeLog14
-rw-r--r--src/util/db2/test/btree.tests/ChangeLog14
-rw-r--r--src/util/db2/test/btree.tests/main.c83
-rw-r--r--src/util/db2/test/dbtest.c14
-rw-r--r--src/util/db2/test/run.test19
-rw-r--r--src/util/et/ChangeLog52
-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/et/test_et.c4
-rw-r--r--src/util/makeshlib.sh8
-rw-r--r--src/util/mkrel34
-rw-r--r--src/util/profile/ChangeLog32
-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.pbexp24
-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
58 files changed, 3145 insertions, 737 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/autoconf/autoconf.info b/src/util/autoconf/autoconf.info
index bd1806e..66effd8 100644
--- a/src/util/autoconf/autoconf.info
+++ b/src/util/autoconf/autoconf.info
@@ -1,5 +1,5 @@
-This is Info file autoconf.info, produced by Makeinfo version 1.67 from
-the input file /home/bje/autoconf-2.13/autoconf.texi.
+This is Info file autoconf.info, produced by Makeinfo version 1.68 from
+the input file ./autoconf.texi.
START-INFO-DIR-ENTRY
* Autoconf: (autoconf). Create source code configuration scripts.
@@ -759,7 +759,7 @@ macro is `AC_INIT' (*note Input::.).
`make' variable `MAKE'. Most versions of `make' set `MAKE' to the name
of the `make' program plus any options it was given. (But many do not
include in it the values of any variables set on the command line, so
-those are not passed on automatically.) Some old versions of `make' do
+those are not passed on automatically.) Some old versions of `make' do
not set this variable. The following macro allows you to use it even
with those versions.
@@ -4824,9 +4824,9 @@ Changed Macro Writing
When defining your own macros, you should now use `AC_DEFUN' instead
of `define'. `AC_DEFUN' automatically calls `AC_PROVIDE' and ensures
that macros called via `AC_REQUIRE' do not interrupt other macros, to
-prevent nested `checking...' messages on the screen. There's no actual
-harm in continuing to use the older way, but it's less convenient and
-attractive. *Note Macro Definitions::.
+prevent nested `checking...' messages on the screen. There's no
+actual harm in continuing to use the older way, but it's less
+convenient and attractive. *Note Macro Definitions::.
You probably looked at the macros that came with Autoconf as a guide
for how to do things. It would be a good idea to take a look at the new
@@ -5047,7 +5047,7 @@ added some auxiliary utilities that I had developed to help convert
source code packages to use Autoconf. With the help of Franc,ois
Pinard, I made the macros not interrupt each others' messages. (That
feature revealed some performance bottlenecks in GNU `m4', which he
-hastily corrected!) I reorganized the documentation around problems
+hastily corrected!) I reorganized the documentation around problems
people want to solve. And I began a testsuite, because experience had
shown that Autoconf has a pronounced tendency to regress when we change
it.
@@ -5298,8 +5298,8 @@ how this is done.
* build_cpu: System Type Variables.
* build_os: System Type Variables.
* build_vendor: System Type Variables.
-* CC <1>: UNIX Variants.
-* CC: Particular Programs.
+* CC <1>: Particular Programs.
+* CC: UNIX Variants.
* CFLAGS <1>: Particular Programs.
* CFLAGS: Preset Output Variables.
* configure_input: Preset Output Variables.
@@ -5307,8 +5307,8 @@ how this is done.
* CPPFLAGS: Preset Output Variables.
* CXX: Particular Programs.
* CXXCPP: Particular Programs.
-* CXXFLAGS <1>: Particular Programs.
-* CXXFLAGS: Preset Output Variables.
+* CXXFLAGS <1>: Preset Output Variables.
+* CXXFLAGS: Particular Programs.
* datadir: Preset Output Variables.
* DEFS: Preset Output Variables.
* exec_prefix: Preset Output Variables.
@@ -5335,11 +5335,11 @@ how this is done.
* LEXLIB: Particular Programs.
* libdir: Preset Output Variables.
* libexecdir: Preset Output Variables.
-* LIBOBJS <1>: Structures.
+* LIBOBJS <1>: Particular Functions.
* LIBOBJS <2>: Generic Functions.
-* LIBOBJS: Particular Functions.
-* LIBS <1>: UNIX Variants.
-* LIBS: Preset Output Variables.
+* LIBOBJS: Structures.
+* LIBS <1>: Preset Output Variables.
+* LIBS: UNIX Variants.
* LN_S: Particular Programs.
* localstatedir: Preset Output Variables.
* mandir: Preset Output Variables.
@@ -5636,8 +5636,8 @@ list easier to use, the macros are listed without their preceding `AC_'.
* ST_BLKSIZE: Old Macro Names.
* ST_BLOCKS: Old Macro Names.
* ST_RDEV: Old Macro Names.
-* STAT_MACROS_BROKEN <1>: Old Macro Names.
-* STAT_MACROS_BROKEN: Structures.
+* STAT_MACROS_BROKEN <1>: Structures.
+* STAT_MACROS_BROKEN: Old Macro Names.
* STDC_HEADERS: Old Macro Names.
* STRCOLL: Old Macro Names.
* STRUCT_ST_BLKSIZE: Structures.
@@ -5685,119 +5685,119 @@ list easier to use, the macros are listed without their preceding `AC_'.

Tag Table:
-Node: Top1209
-Node: Introduction9711
-Node: Making configure Scripts13551
-Node: Writing configure.in16632
-Node: Invoking autoscan20365
-Node: Invoking ifnames22670
-Node: Invoking autoconf24160
-Node: Invoking autoreconf25998
-Node: Setup28834
-Node: Input29739
-Node: Output31476
-Node: Makefile Substitutions35113
-Node: Preset Output Variables36716
-Node: Build Directories41585
-Node: Automatic Remaking43218
-Node: Configuration Headers45304
-Node: Header Templates47818
-Node: Invoking autoheader49027
-Node: Subdirectories52175
-Node: Default Prefix53570
-Node: Versions54974
-Node: Existing Tests56878
-Node: Alternative Programs58426
-Node: Particular Programs59113
-Node: Generic Programs67165
-Node: Libraries70471
-Node: Library Functions73545
-Node: Particular Functions74103
-Node: Generic Functions81297
-Node: Header Files83401
-Node: Particular Headers83960
-Node: Generic Headers90952
-Node: Structures92254
-Node: Typedefs94491
-Node: Particular Typedefs94997
-Node: Generic Typedefs96214
-Node: C Compiler Characteristics96671
-Node: Fortran 77 Compiler Characteristics99542
-Node: System Services101245
-Node: UNIX Variants104381
-Node: Writing Tests106400
-Node: Examining Declarations108393
-Node: Examining Syntax110885
-Node: Examining Libraries112330
-Node: Run Time116040
-Node: Test Programs117028
-Node: Guidelines119356
-Node: Test Functions120545
-Node: Portable Shell122088
-Node: Testing Values and Files124020
-Node: Multiple Cases125675
-Node: Language Choice126873
-Node: Results128975
-Node: Defining Symbols129737
-Node: Setting Output Variables133033
-Node: Caching Results134879
-Node: Cache Variable Names137625
-Node: Cache Files139109
-Node: Printing Messages141946
-Node: Writing Macros145394
-Node: Macro Definitions146041
-Node: Macro Names147169
-Node: Quoting149620
-Node: Dependencies Between Macros151522
-Node: Prerequisite Macros152169
-Node: Suggested Ordering153660
-Node: Obsolete Macros155190
-Node: Manual Configuration156414
-Node: Specifying Names157313
-Node: Canonicalizing159214
-Node: System Type Variables160726
-Node: Using System Type161473
-Node: Site Configuration162967
-Node: External Software163740
-Node: Package Options166943
-Node: Site Details169690
-Node: Transforming Names170913
-Node: Transformation Options172091
-Node: Transformation Examples172584
-Node: Transformation Rules174152
-Node: Site Defaults175561
-Node: Invoking configure179467
-Node: Basic Installation180416
-Node: Compilers and Options182996
-Node: Multiple Architectures183645
-Node: Installation Names184631
-Node: Optional Features185815
-Node: System Type186585
-Node: Sharing Defaults187607
-Node: Operation Controls188231
-Node: Invoking config.status189217
-Node: Questions192605
-Node: Distributing193137
-Node: Why GNU m4194281
-Node: Bootstrapping195094
-Node: Why Not Imake195710
-Node: Upgrading200119
-Node: Changed File Names201640
-Node: Changed Makefiles202394
-Node: Changed Macros203490
-Node: Invoking autoupdate204737
-Node: Changed Results206328
-Node: Changed Macro Writing208430
-Node: History209693
-Node: Genesis210485
-Node: Exodus211674
-Node: Leviticus214723
-Node: Numbers216246
-Node: Deuteronomy218162
-Node: Old Macro Names220826
-Node: Environment Variable Index223875
-Node: Output Variable Index224889
-Node: Preprocessor Symbol Index230087
-Node: Macro Index235373
+Node: Top1187
+Node: Introduction9689
+Node: Making configure Scripts13529
+Node: Writing configure.in16610
+Node: Invoking autoscan20343
+Node: Invoking ifnames22648
+Node: Invoking autoconf24138
+Node: Invoking autoreconf25976
+Node: Setup28812
+Node: Input29717
+Node: Output31454
+Node: Makefile Substitutions35092
+Node: Preset Output Variables36695
+Node: Build Directories41564
+Node: Automatic Remaking43197
+Node: Configuration Headers45283
+Node: Header Templates47797
+Node: Invoking autoheader49006
+Node: Subdirectories52154
+Node: Default Prefix53549
+Node: Versions54953
+Node: Existing Tests56857
+Node: Alternative Programs58405
+Node: Particular Programs59092
+Node: Generic Programs67144
+Node: Libraries70450
+Node: Library Functions73524
+Node: Particular Functions74082
+Node: Generic Functions81276
+Node: Header Files83380
+Node: Particular Headers83939
+Node: Generic Headers90931
+Node: Structures92233
+Node: Typedefs94470
+Node: Particular Typedefs94976
+Node: Generic Typedefs96193
+Node: C Compiler Characteristics96650
+Node: Fortran 77 Compiler Characteristics99521
+Node: System Services101224
+Node: UNIX Variants104360
+Node: Writing Tests106379
+Node: Examining Declarations108372
+Node: Examining Syntax110864
+Node: Examining Libraries112309
+Node: Run Time116019
+Node: Test Programs117007
+Node: Guidelines119335
+Node: Test Functions120524
+Node: Portable Shell122067
+Node: Testing Values and Files123999
+Node: Multiple Cases125654
+Node: Language Choice126852
+Node: Results128954
+Node: Defining Symbols129716
+Node: Setting Output Variables133012
+Node: Caching Results134858
+Node: Cache Variable Names137604
+Node: Cache Files139088
+Node: Printing Messages141925
+Node: Writing Macros145373
+Node: Macro Definitions146020
+Node: Macro Names147148
+Node: Quoting149599
+Node: Dependencies Between Macros151501
+Node: Prerequisite Macros152148
+Node: Suggested Ordering153639
+Node: Obsolete Macros155169
+Node: Manual Configuration156393
+Node: Specifying Names157292
+Node: Canonicalizing159193
+Node: System Type Variables160705
+Node: Using System Type161452
+Node: Site Configuration162946
+Node: External Software163719
+Node: Package Options166922
+Node: Site Details169669
+Node: Transforming Names170892
+Node: Transformation Options172070
+Node: Transformation Examples172563
+Node: Transformation Rules174131
+Node: Site Defaults175540
+Node: Invoking configure179446
+Node: Basic Installation180395
+Node: Compilers and Options182975
+Node: Multiple Architectures183624
+Node: Installation Names184610
+Node: Optional Features185794
+Node: System Type186564
+Node: Sharing Defaults187586
+Node: Operation Controls188210
+Node: Invoking config.status189196
+Node: Questions192584
+Node: Distributing193116
+Node: Why GNU m4194260
+Node: Bootstrapping195073
+Node: Why Not Imake195689
+Node: Upgrading200098
+Node: Changed File Names201619
+Node: Changed Makefiles202373
+Node: Changed Macros203469
+Node: Invoking autoupdate204716
+Node: Changed Results206307
+Node: Changed Macro Writing208409
+Node: History209673
+Node: Genesis210465
+Node: Exodus211654
+Node: Leviticus214703
+Node: Numbers216226
+Node: Deuteronomy218142
+Node: Old Macro Names220807
+Node: Environment Variable Index223856
+Node: Output Variable Index224870
+Node: Preprocessor Symbol Index230068
+Node: Macro Index235354

End Tag Table
diff --git a/src/util/db2/ChangeLog b/src/util/db2/ChangeLog
index 7972728..9c9768c 100644
--- a/src/util/db2/ChangeLog
+++ b/src/util/db2/ChangeLog
@@ -1,3 +1,50 @@
+2002-08-28 Tom Yu <tlyu@mit.edu>
+
+ * btree/bt_split.c (bt_psplit): Correctly account for
+ sizeof(indx_t) when computing space used in a page by an item.
+ [patch from www.sleepycat.com]
+ [pullup from trunk]
+
+2002-08-26 Tom Yu <tlyu@mit.edu>
+
+ * Makefile.in (LIBMINOR): Bump due to addition of bt_rseq().
+
+ * hash/hash_debug.c: Remove inclusion of compat.h, as we don't
+ have it in our build system.
+
+ * btree/extern.h: Add missing prototypes/renames for
+ __bt_dmpage(). Add renames for bt_rseq() support functions.
+
+ * btree/bt_seq.c (bt_rseq): New function; like __bt_seq() but does
+ recursive descent rather than using the prev/next pointers. This
+ will catch some pages that might be missed if the database is
+ inconsistent. Added support functions for bt_rseq() as well.
+
+ * btree/bt_page.c (__bt_free): Set B_METADIRTY when updating free
+ list.
+ (__bt_new): Set B_METADIRTY when updating free list.
+ [patch from www.sleepycat.com]
+
+ * btree/bt_debug.c (__bt_dump): Bound loop by number of pages
+ actually in file to avoid getting a nigh-infinite number of
+ all-zeroes pages.
+ (__bt_dmpage): Print a newline after dumping the meta page.
+ (__bt_dpage): Add DB* parameter; use this to get pagesize in order
+ to limit dumping of page contents, in case NEXTINDEX(h) happens to
+ be bogus.
+ (__bt_stat): Bound loop by number of pages actually in file so as
+ to stop counting pages after the actual end of file.
+
+ * btree/bt_close.c (__bt_sync): Apply a Kerbnet fix from long ago;
+ don't return prematurely when B_METADIRTY is set but B_MODIFIED is
+ clear.
+
+ [pullups from trunk]
+
+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/btree/bt_close.c b/src/util/db2/btree/bt_close.c
index b731dcb..11be134 100644
--- a/src/util/db2/btree/bt_close.c
+++ b/src/util/db2/btree/bt_close.c
@@ -137,7 +137,8 @@ __bt_sync(dbp, flags)
return (RET_ERROR);
}
- if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
+ if (F_ISSET(t, B_INMEM | B_RDONLY)
+ || !F_ISSET(t, B_MODIFIED | B_METADIRTY))
return (RET_SUCCESS);
if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
diff --git a/src/util/db2/btree/bt_debug.c b/src/util/db2/btree/bt_debug.c
index 8cf1cda..d36256b 100644
--- a/src/util/db2/btree/bt_debug.c
+++ b/src/util/db2/btree/bt_debug.c
@@ -114,10 +114,9 @@ __bt_dump(dbp)
(void)fprintf(tracefp, ")\n");
}
#undef X
-
- for (i = P_ROOT;
+ for (i = P_ROOT; i < t->bt_mp->npages &&
(h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
- __bt_dpage(h);
+ __bt_dpage(dbp, h);
(void)fflush(tracefp);
return (0);
}
@@ -156,6 +155,7 @@ __bt_dmpage(h)
X(R_RECNO, "RECNO");
(void)fprintf(tracefp, ")");
}
+ (void)fprintf(tracefp, "\n");
(void)fflush(tracefp);
return (0);
}
@@ -178,7 +178,7 @@ __bt_dnpage(dbp, pgno)
t = dbp->internal;
if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL)
- __bt_dpage(h);
+ __bt_dpage(dbp, h);
(void)fflush(tracefp);
return (0);
}
@@ -190,14 +190,16 @@ __bt_dnpage(dbp, pgno)
* h: pointer to the PAGE
*/
int
-__bt_dpage(h)
+__bt_dpage(dbp, h)
+ DB *dbp;
PAGE *h;
{
BINTERNAL *bi;
BLEAF *bl;
RINTERNAL *ri;
RLEAF *rl;
- indx_t cur, top;
+ u_long pgsize;
+ indx_t cur, top, lim;
char *sep;
__bt_dinit();
@@ -223,10 +225,13 @@ __bt_dpage(h)
if (h->flags & P_OVERFLOW)
return;
+ pgsize = ((BTREE *)dbp->internal)->bt_mp->pagesize;
+ lim = (pgsize - BTDATAOFF) / sizeof(indx_t);
top = NEXTINDEX(h);
+ lim = top > lim ? lim : top;
(void)fprintf(tracefp, " lower %3d upper %3d nextind %d\n",
h->lower, h->upper, top);
- for (cur = 0; cur < top; cur++) {
+ for (cur = 0; cur < lim; cur++) {
(void)fprintf(tracefp, "\t[%03d] %4d ", cur, h->linp[cur]);
switch (h->flags & P_TYPE) {
case P_BINTERNAL:
@@ -307,7 +312,7 @@ __bt_stat(dbp)
t = dbp->internal;
pcont = pinternal = pleaf = 0;
nkeys = ifree = lfree = 0;
- for (i = P_ROOT;
+ for (i = P_ROOT; i < t->bt_mp->npages &&
(h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
switch (h->flags & P_TYPE) {
case P_BINTERNAL:
diff --git a/src/util/db2/btree/bt_page.c b/src/util/db2/btree/bt_page.c
index cb65040..3663cf7 100644
--- a/src/util/db2/btree/bt_page.c
+++ b/src/util/db2/btree/bt_page.c
@@ -65,6 +65,7 @@ __bt_free(t, h)
h->prevpg = P_INVALID;
h->nextpg = t->bt_free;
t->bt_free = h->pgno;
+ F_SET(t, B_METADIRTY);
/* Make sure the page gets written back. */
return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
@@ -92,6 +93,7 @@ __bt_new(t, npg)
(h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
*npg = t->bt_free;
t->bt_free = h->nextpg;
+ F_SET(t, B_METADIRTY);
return (h);
}
return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT));
diff --git a/src/util/db2/btree/bt_seq.c b/src/util/db2/btree/bt_seq.c
index 3e68c66..c16d4a2 100644
--- a/src/util/db2/btree/bt_seq.c
+++ b/src/util/db2/btree/bt_seq.c
@@ -1,3 +1,27 @@
+/*
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, 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.
+ */
+
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -488,3 +512,389 @@ __bt_setcur(t, pgno, index)
t->bt_cursor.pg.index = index;
F_SET(&t->bt_cursor, CURS_INIT);
}
+
+/* Recursive descent cursor. */
+typedef struct rcursor_ {
+ CURSOR cursor;
+ size_t ssize;
+ EPGNO *stack;
+ EPGNO *sp;
+} RCURSOR;
+#define RCURSOR_MINSS 64
+
+static int bt_rcinit(void **);
+static void bt_rcdestroy(void **);
+static int bt_rcpush(RCURSOR *, db_pgno_t, u_int);
+static EPGNO *bt_rcpop(RCURSOR *);
+static void bt_rcclr(RCURSOR *);
+static int bt_rcgrowstk(RCURSOR *);
+static int bt_rseqset(BTREE *, EPG *, DBT *, RCURSOR *, int);
+static int bt_rseqadv(BTREE *, EPG *, RCURSOR *, int);
+
+static int
+bt_rcinit(curs)
+ void **curs;
+{
+ RCURSOR *rc;
+
+ rc = *curs = malloc(sizeof(RCURSOR));
+ if (rc == NULL) {
+ errno = ENOMEM;
+ return RET_ERROR;
+ }
+ memset(rc, 0, sizeof(*rc));
+
+ rc->ssize = RCURSOR_MINSS;
+ rc->stack = malloc(rc->ssize * sizeof(EPGNO));
+ if (rc->stack == NULL) {
+ free(rc);
+ errno = ENOMEM;
+ return RET_ERROR;
+ }
+ bt_rcclr(rc);
+ return RET_SUCCESS;
+}
+
+static void
+bt_rcdestroy(curs)
+ void **curs;
+{
+ RCURSOR *rc;
+
+ rc = *curs;
+ free(rc->stack);
+ free(rc);
+ *curs = NULL;
+}
+
+static int
+bt_rcpush(rc, p, i)
+ RCURSOR *rc;
+ db_pgno_t p;
+ u_int i;
+{
+ int status;
+
+ rc->sp->pgno = p;
+ rc->sp->index = i;
+ if (++rc->sp > rc->stack + rc->ssize) {
+ status = bt_rcgrowstk(rc);
+ if (status != RET_SUCCESS)
+ return status;
+ }
+ return RET_SUCCESS;
+}
+
+static EPGNO *
+bt_rcpop(rc)
+ RCURSOR *rc;
+{
+ return (rc->sp == rc->stack) ? NULL : --rc->sp;
+}
+
+static void
+bt_rcclr(rc)
+ RCURSOR *rc;
+{
+ rc->sp = rc->stack;
+}
+
+static int
+bt_rcgrowstk(rc)
+ RCURSOR *rc;
+{
+ size_t osize;
+ EPGNO *e;
+
+ osize = rc->ssize;
+ rc->ssize *= 2;
+ e = realloc(rc->stack, rc->ssize * sizeof(EPGNO));
+ if (e == NULL) {
+ rc->ssize = osize;
+ errno = ENOMEM;
+ return RET_ERROR;
+ }
+ rc->stack = e;
+ return RET_SUCCESS;
+}
+
+/*
+ * bt_rseq --
+ * Like __bt_seq but does recursive descent tree traversal
+ * instead of using the prev/next pointers.
+ */
+int
+bt_rseq(dbp, key, data, curs, flags)
+ const DB *dbp;
+ DBT *key, *data;
+ void **curs;
+ u_int flags;
+{
+ RCURSOR *rc;
+ BTREE *t;
+ EPG e;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ if (curs == NULL) {
+ errno = EINVAL;
+ return RET_ERROR;
+ }
+ if (*curs == NULL) {
+ status = bt_rcinit(curs);
+ if (status != RET_SUCCESS)
+ return RET_ERROR;
+ }
+ rc = *curs;
+
+ /*
+ * If scan unitialized as yet, or starting at a specific record, set
+ * the scan to a specific key. Both bt_rseqset and bt_rseqadv pin
+ * the page the cursor references if they're successful.
+ */
+ switch (flags) {
+ case R_NEXT:
+ case R_PREV:
+ if (F_ISSET(&rc->cursor, CURS_INIT)) {
+ status = bt_rseqadv(t, &e, rc, flags);
+ break;
+ }
+ /* FALLTHROUGH */
+ case R_FIRST:
+ case R_LAST:
+ case R_CURSOR:
+ status = bt_rseqset(t, &e, key, rc, flags);
+ break;
+ default:
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (status == RET_SUCCESS) {
+ status =
+ __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
+
+ /*
+ * If the user is doing concurrent access, we copied the
+ * key/data, toss the page.
+ */
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e.page, 0);
+ else
+ t->bt_pinned = e.page;
+ } else if (status == RET_SPECIAL)
+ bt_rcdestroy(curs);
+ return (status);
+}
+
+/*
+ * bt_rseqset --
+ * Set the sequential scan to a specific key.
+ *
+ * Parameters:
+ * t: tree
+ * ep: storage for returned key
+ * key: key for initial scan position
+ * rc: recursion cursor
+ * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
+ *
+ * Side effects:
+ * Pins the page the cursor references.
+ * Updates rc's stack and cursor.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+bt_rseqset(t, ep, key, rc, flags)
+ BTREE *t;
+ EPG *ep;
+ DBT *key;
+ RCURSOR *rc;
+ int flags;
+{
+ PAGE *h;
+ db_pgno_t pg;
+ int status;
+
+ /*
+ * Find the first, last or specific key in the tree and point the
+ * cursor at it. The cursor may not be moved until a new key has
+ * been found.
+ */
+ switch (flags) {
+ case R_CURSOR: /* Not implemented. */
+ errno = EINVAL;
+ return RET_ERROR;
+ case R_FIRST: /* First record. */
+ case R_NEXT:
+ bt_rcclr(rc);
+ /* Walk down the left-hand side of the tree. */
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Check for an empty tree. */
+ if (NEXTINDEX(h) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ }
+
+ if (h->flags & (P_BLEAF | P_RLEAF))
+ break;
+ pg = GETBINTERNAL(h, 0)->pgno;
+ status = bt_rcpush(rc, h->pgno, 0);
+ mpool_put(t->bt_mp, h, 0);
+ if (status != RET_SUCCESS)
+ return status;
+ }
+ ep->page = h;
+ ep->index = 0;
+ break;
+ case R_LAST: /* Last record. */
+ case R_PREV:
+ bt_rcclr(rc);
+ /* Walk down the right-hand side of the tree. */
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Check for an empty tree. */
+ if (NEXTINDEX(h) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ }
+
+ if (h->flags & (P_BLEAF | P_RLEAF))
+ break;
+ pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
+ status = bt_rcpush(rc, h->pgno, NEXTINDEX(h) - 1);
+ mpool_put(t->bt_mp, h, 0);
+ if (status != RET_SUCCESS)
+ return status;
+ }
+ ep->page = h;
+ ep->index = NEXTINDEX(h) - 1;
+ break;
+ }
+ rc->cursor.pg.pgno = ep->page->pgno;
+ rc->cursor.pg.index = ep->index;
+ F_CLR(&rc->cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+ F_SET(&rc->cursor, CURS_INIT);
+ return (RET_SUCCESS);
+}
+
+/*
+ * bt_rseqadvance --
+ * Advance the sequential scan.
+ *
+ * Parameters:
+ * t: tree
+ * ep: return page
+ * rc: recursion cursor
+ * flags: R_NEXT, R_PREV
+ *
+ * Side effects:
+ * Pins the page the new key/data record is on.
+ * Updates rc's stack and cursor.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+bt_rseqadv(t, ep, rc, flags)
+ BTREE *t;
+ EPG *ep;
+ RCURSOR *rc;
+ int flags;
+{
+ CURSOR *c;
+ PAGE *h;
+ indx_t idx;
+ db_pgno_t pg;
+ int status;
+ EPGNO *e;
+
+ /*
+ * There are a couple of states that we can be in. The cursor has
+ * been initialized by the time we get here, but that's all we know.
+ */
+ c = &rc->cursor;
+
+ /* Get the page referenced by the cursor. */
+ if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+ return (RET_ERROR);
+
+ /*
+ * Find the next/previous record in the tree and point the cursor at
+ * it. The cursor may not be moved until a new key has been found.
+ */
+ switch (flags) {
+ case R_NEXT: /* Next record. */
+ idx = c->pg.index;
+ while (++idx == NEXTINDEX(h)) {
+ /* Crawl up if we hit the right edge. */
+ e = bt_rcpop(rc);
+ mpool_put(t->bt_mp, h, 0);
+ if (e == NULL) /* Hit the right edge of root. */
+ return RET_SPECIAL;
+ idx = e->index;
+ pg = e->pgno;
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ }
+ while (!(h->flags & (P_BLEAF | P_RLEAF))) {
+ /* Crawl down the left until we hit a leaf. */
+ status = bt_rcpush(rc, h->pgno, idx);
+ pg = GETBINTERNAL(h, idx)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ if (status != RET_SUCCESS)
+ return status;
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ idx = 0;
+ }
+ break;
+ case R_PREV: /* Previous record. */
+ idx = c->pg.index;
+ while (!idx) {
+ /* Crawl up if we hit the left edge. */
+ e = bt_rcpop(rc);
+ mpool_put(t->bt_mp, h, 0);
+ if (e == NULL) /* Hit the left edge of root. */
+ return RET_SPECIAL;
+ idx = e->index;
+ pg = e->pgno;
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ }
+ idx--;
+ while (!(h->flags & (P_BLEAF | P_RLEAF))) {
+ /* Crawl down the right until we hit a leaf. */
+ status = bt_rcpush(rc, h->pgno, idx);
+ pg = GETBINTERNAL(h, idx)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ if (status != RET_SUCCESS)
+ return status;
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ idx = NEXTINDEX(h) - 1;
+ }
+ break;
+ }
+
+ ep->page = h;
+ ep->index = idx;
+ c->pg.pgno = h->pgno;
+ c->pg.index = idx;
+ F_CLR(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+ F_SET(c, CURS_INIT);
+ return (RET_SUCCESS);
+}
diff --git a/src/util/db2/btree/bt_split.c b/src/util/db2/btree/bt_split.c
index 0fc95ba..0cc6cf0 100644
--- a/src/util/db2/btree/bt_split.c
+++ b/src/util/db2/btree/bt_split.c
@@ -673,7 +673,8 @@ bt_psplit(t, h, l, r, pskip, ilen)
* where we decide to try and copy too much onto the left page.
* Make sure that doesn't happen.
*/
- if (skip <= off && used + nbytes >= full || nxt == top - 1) {
+ if ((skip <= off && used + nbytes + sizeof(indx_t) >= full)
+ || nxt == top - 1) {
--off;
break;
}
@@ -686,7 +687,7 @@ bt_psplit(t, h, l, r, pskip, ilen)
memmove((char *)l + l->upper, src, nbytes);
}
- used += nbytes;
+ used += nbytes + sizeof(indx_t);
if (used >= half) {
if (!isbigkey || bigkeycnt == 3)
break;
diff --git a/src/util/db2/btree/extern.h b/src/util/db2/btree/extern.h
index 70a8807..3aa8841 100644
--- a/src/util/db2/btree/extern.h
+++ b/src/util/db2/btree/extern.h
@@ -58,10 +58,20 @@
#define __ovfl_get __kdb2_ovfl_get
#define __ovfl_put __kdb2_ovfl_put
#define __bt_dnpage __kdb2_bt_dnpage
+#define __bt_dmpage __kdb2_bt_dmpage
#define __bt_dpage __kdb2_bt_dpage
#define __bt_dump __kdb2_bt_dump
#define __bt_stat __kdb2_bt_stat
+#define bt_rcinit kdb2_bt_rcinit
+#define bt_rcdestroy kdb2_bt_rcdestroy
+#define bt_rcpush kdb2_bt_rcpush
+#define bt_rcpop kdb2_bt_rcpop
+#define bt_rcclr kdb2_bt_rcclr
+#define bt_rcgrowstk kdb2_bt_rcgrowstk
+#define bt_rseqset kdb2_bt_rseqset
+#define bt_rseqadv kdb2_bt_rseqadv
+
int __bt_close __P((DB *));
int __bt_cmp __P((BTREE *, const DBT *, EPG *));
int __bt_crsrdel __P((BTREE *, EPGNO *));
@@ -91,7 +101,8 @@ int __ovfl_put __P((BTREE *, const DBT *, db_pgno_t *));
#ifdef DEBUG
int __bt_dnpage __P((DB *, db_pgno_t));
-int __bt_dpage __P((PAGE *));
+int __bt_dpage __P((DB *, PAGE *));
+int __bt_dmpage __P((PAGE *));
int __bt_dump __P((DB *));
#endif
#ifdef STATISTICS
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/db2/hash/hash_debug.c b/src/util/db2/hash/hash_debug.c
index ed99c69..69229fc 100644
--- a/src/util/db2/hash/hash_debug.c
+++ b/src/util/db2/hash/hash_debug.c
@@ -56,7 +56,6 @@ static char sccsid[] = "@(#)hash_debug.c 8.4 (Berkeley) 11/7/95";
#include "hash.h"
#include "page.h"
#include "extern.h"
-#include "compat.h"
void
__dump_bucket(hashp, bucket)
diff --git a/src/util/db2/include/ChangeLog b/src/util/db2/include/ChangeLog
index 4d3d16d..7b25e55 100644
--- a/src/util/db2/include/ChangeLog
+++ b/src/util/db2/include/ChangeLog
@@ -1,3 +1,9 @@
+2002-08-26 Tom Yu <tlyu@mit.edu>
+
+ * db.h: Add rename and prototype for bt_rseq(); this is a kludge
+ to avoid stuffing more things into the DB handle.
+ [pullup from trunk]
+
Fri Feb 13 14:39:25 1998 Tom Yu <tlyu@mit.edu>
* db-int.h: Additional renaming.
diff --git a/src/util/db2/include/db.h b/src/util/db2/include/db.h
index 2eaf0bc..980145a 100644
--- a/src/util/db2/include/db.h
+++ b/src/util/db2/include/db.h
@@ -166,8 +166,10 @@ typedef struct {
#endif
#define dbopen kdb2_dbopen
+#define bt_rseq kdb2_bt_rseq /* XXX kludge */
__BEGIN_DECLS
DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
+int bt_rseq(const DB*, DBT *, DBT *, void **, u_int); /* XXX kludge */
__END_DECLS
#endif /* !_DB_H_ */
diff --git a/src/util/db2/test/ChangeLog b/src/util/db2/test/ChangeLog
index 4e147d7..fc2f691 100644
--- a/src/util/db2/test/ChangeLog
+++ b/src/util/db2/test/ChangeLog
@@ -1,3 +1,17 @@
+2002-08-26 Tom Yu <tlyu@mit.edu>
+
+ * dbtest.c: Include btree.h if we're compiled with -DSTATISTICS.
+ [pullup from trunk]
+
+2001-12-21 Ken Raeburn <raeburn@mit.edu>
+
+ * dbtest.c (compare): Make comparison failures fatal.
+ (get): Make no-such-key errors fatal.
+
+ * run.test (main, test3, test8): Use "/bin/." instead of "/bin" in
+ find commands, in case /bin itself is a symlink.
+ (test8): Do check exit status of program.
+
1998-05-06 Theodore Ts'o <tytso@rsts-11.mit.edu>
* dbtest.c (main): POSIX states that getopt returns -1
diff --git a/src/util/db2/test/btree.tests/ChangeLog b/src/util/db2/test/btree.tests/ChangeLog
index cfd0b18..b70f64e 100644
--- a/src/util/db2/test/btree.tests/ChangeLog
+++ b/src/util/db2/test/btree.tests/ChangeLog
@@ -1,3 +1,17 @@
+2002-08-26 Tom Yu <tlyu@mit.edu>
+
+ * main.c: Disable append(); we don't have R_APPEND in this release
+ of DB for some reason. Disable load() due to lack of fgetline().
+ Conditionalize lots of things on -DSTATISTICS or -DDEBUG as
+ appropriate.
+ (rlist): New function; does recursive listing of principals.
+ (main): Fix up naming of *_ENDIAN macros. Default to read-only
+ open, with new "-w" option for opening read/write. Actually call
+ db->sync with the correct number of arguments.
+ (show): Update call to __bt_dpage().
+ (usage): Update.
+ [pullup from trunk]
+
1998-05-06 Theodore Ts'o <tytso@rsts-11.mit.edu>
* main.c (main): POSIX states that getopt returns -1
diff --git a/src/util/db2/test/btree.tests/main.c b/src/util/db2/test/btree.tests/main.c
index bbf1fcf..06f02b3 100644
--- a/src/util/db2/test/btree.tests/main.c
+++ b/src/util/db2/test/btree.tests/main.c
@@ -59,12 +59,18 @@ typedef struct cmd_table {
int stopstop;
DB *globaldb;
+#if 0
void append __P((DB *, char **));
+#endif
+#ifdef STATISTICS
void bstat __P((DB *, char **));
+#endif
void cursor __P((DB *, char **));
void delcur __P((DB *, char **));
void delete __P((DB *, char **));
+#ifdef DEBUG
void dump __P((DB *, char **));
+#endif
void first __P((DB *, char **));
void get __P((DB *, char **));
void help __P((DB *, char **));
@@ -75,23 +81,36 @@ void insert __P((DB *, char **));
void keydata __P((DBT *, DBT *));
void last __P((DB *, char **));
void list __P((DB *, char **));
+#if 0
void load __P((DB *, char **));
+#endif
+#ifdef STATISTICS
void mstat __P((DB *, char **));
+#endif
void next __P((DB *, char **));
int parse __P((char *, char **, int));
void previous __P((DB *, char **));
+#ifdef DEBUG
void show __P((DB *, char **));
+#endif
+void rlist __P((DB *, char **));
void usage __P((void));
void user __P((DB *));
cmd_table commands[] = {
"?", 0, 0, help, "help", NULL,
+#if 0
"a", 2, 1, append, "append key def", "append key with data def",
+#endif
+#ifdef STATISTICS
"b", 0, 0, bstat, "bstat", "stat btree",
+#endif
"c", 1, 1, cursor, "cursor word", "move cursor to word",
"delc", 0, 0, delcur, "delcur", "delete key the cursor references",
"dele", 1, 1, delete, "delete word", "delete word",
+#ifdef DEBUG
"d", 0, 0, dump, "dump", "dump database",
+#endif
"f", 0, 0, first, "first", "move cursor to first record",
"g", 1, 1, get, "get key", "locate key",
"h", 0, 0, help, "help", "print command summary",
@@ -101,13 +120,20 @@ cmd_table commands[] = {
"in", 2, 1, insert, "insert key def", "insert key with data def",
"la", 0, 0, last, "last", "move cursor to last record",
"li", 1, 1, list, "list file", "list to a file",
+#if 0
"loa", 1, 0, load, "load file", NULL,
+#endif
"loc", 1, 1, get, "get key", NULL,
+#ifdef STATISTICS
"m", 0, 0, mstat, "mstat", "stat memory pool",
+#endif
"n", 0, 0, next, "next", "move cursor forward one record",
"p", 0, 0, previous, "previous", "move cursor back one record",
"q", 0, 0, NULL, "quit", "quit",
+ "rli", 1, 1, rlist, "rlist file", "list to a file (recursive)",
+#ifdef DEBUG
"sh", 1, 0, show, "show page", "dump a page",
+#endif
{ NULL },
};
@@ -121,11 +147,13 @@ main(argc, argv)
char **argv;
{
int c;
+ int omode;
DB *db;
BTREEINFO b;
progname = *argv;
+ omode = O_RDONLY;
b.flags = 0;
b.cachesize = 0;
b.maxkeypage = 0;
@@ -135,10 +163,10 @@ main(argc, argv)
b.prefix = NULL;
b.lorder = 0;
- while ((c = getopt(argc, argv, "bc:di:lp:ru")) != -1) {
+ while ((c = getopt(argc, argv, "bc:di:lp:ruw")) != -1) {
switch (c) {
case 'b':
- b.lorder = BIG_ENDIAN;
+ b.lorder = DB_BIG_ENDIAN;
break;
case 'c':
b.cachesize = atoi(optarg);
@@ -150,7 +178,7 @@ main(argc, argv)
dict = optarg;
break;
case 'l':
- b.lorder = LITTLE_ENDIAN;
+ b.lorder = DB_LITTLE_ENDIAN;
break;
case 'p':
b.psize = atoi(optarg);
@@ -161,6 +189,9 @@ main(argc, argv)
case 'u':
b.flags = 0;
break;
+ case 'w':
+ omode = O_RDWR;
+ break;
default:
usage();
}
@@ -169,10 +200,10 @@ main(argc, argv)
argv += optind;
if (recno)
- db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR|O_BINARY,
+ db = dbopen(*argv == NULL ? NULL : *argv, omode|O_BINARY,
0, DB_RECNO, NULL);
else
- db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR|O_BINARY,
+ db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|omode|O_BINARY,
0600, DB_BTREE, &b);
if (db == NULL) {
@@ -240,7 +271,7 @@ user(db)
uselast: last = i;
(*commands[i].func)(db, argv);
}
- if ((db->sync)(db) == RET_ERROR)
+ if ((db->sync)(db, 0) == RET_ERROR)
perror("dbsync");
else if ((db->close)(db) == RET_ERROR)
perror("dbclose");
@@ -269,6 +300,7 @@ parse(lbuf, argv, maxargc)
return (argc);
}
+#if 0
void
append(db, argv)
DB *db;
@@ -298,6 +330,7 @@ append(db, argv)
break;
}
}
+#endif
void
cursor(db, argv)
@@ -366,6 +399,7 @@ delete(db, argv)
}
}
+#ifdef DEBUG
void
dump(db, argv)
DB *db;
@@ -373,6 +407,7 @@ dump(db, argv)
{
__bt_dump(db);
}
+#endif
void
first(db, argv)
@@ -598,10 +633,37 @@ list(db, argv)
(void)fprintf(fp, "%s\n", key.data);
status = (*db->seq)(db, &key, &data, R_NEXT);
}
+ (void)fclose(fp);
+ if (status == RET_ERROR)
+ perror("list/seq");
+}
+
+void
+rlist(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ FILE *fp;
+ int status;
+ void *cookie;
+
+ cookie = NULL;
+ if ((fp = fopen(argv[1], "w")) == NULL) {
+ (void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+ return;
+ }
+ status = bt_rseq(db, &key, &data, &cookie, R_FIRST);
+ while (status == RET_SUCCESS) {
+ (void)fprintf(fp, "%s\n", key.data);
+ status = bt_rseq(db, &key, &data, &cookie, R_NEXT);
+ }
+ (void)fclose(fp);
if (status == RET_ERROR)
perror("list/seq");
}
+#if 0
DB *BUGdb;
void
load(db, argv)
@@ -657,6 +719,7 @@ load(db, argv)
}
(void)fclose(fp);
}
+#endif
void
next(db, argv)
@@ -704,6 +767,7 @@ previous(db, argv)
}
}
+#ifdef DEBUG
void
show(db, argv)
DB *db;
@@ -722,10 +786,12 @@ show(db, argv)
if (pg == 0)
__bt_dmpage(h);
else
- __bt_dpage(h);
+ __bt_dpage(db, h);
mpool_put(t->bt_mp, h, 0);
}
+#endif
+#ifdef STATISTICS
void
bstat(db, argv)
DB *db;
@@ -743,6 +809,7 @@ mstat(db, argv)
(void)printf("MPOOL\n");
mpool_stat(((BTREE *)db->internal)->bt_mp);
}
+#endif
void
keydata(key, data)
@@ -759,7 +826,7 @@ void
usage()
{
(void)fprintf(stderr,
- "usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n",
+ "usage: %s [-bdluw] [-c cache] [-i file] [-p page] [file]\n",
progname);
exit (1);
}
diff --git a/src/util/db2/test/dbtest.c b/src/util/db2/test/dbtest.c
index f499047..315b13c 100644
--- a/src/util/db2/test/dbtest.c
+++ b/src/util/db2/test/dbtest.c
@@ -54,6 +54,9 @@ static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94";
#include <unistd.h>
#include "db-int.h"
+#ifdef STATISTICS
+#include "btree.h"
+#endif
enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
@@ -344,13 +347,13 @@ compare(db1, db2)
register u_char *p1, *p2;
if (db1->size != db2->size)
- printf("compare failed: key->data len %lu != data len %lu\n",
+ err("compare failed: key->data len %lu != data len %lu\n",
db1->size, db2->size);
len = MIN(db1->size, db2->size);
for (p1 = db1->data, p2 = db2->data; len--;)
if (*p1++ != *p2++) {
- printf("compare failed at offset %d\n",
+ err("compare failed at offset %d\n",
p1 - (u_char *)db1->data);
break;
}
@@ -374,10 +377,11 @@ get(dbp, kp)
/* NOTREACHED */
case 1:
#define NOSUCHKEY "get failed, no such key\n"
- if (ofd != STDOUT_FILENO)
+ if (ofd != STDOUT_FILENO) {
(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
- else
- (void)fprintf(stderr, "%d: %.*s: %s",
+ exit (1);
+ } else
+ err(stderr, "%d: %.*s: %s",
lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
#undef NOSUCHKEY
break;
diff --git a/src/util/db2/test/run.test b/src/util/db2/test/run.test
index 462a9c2..c3922c8 100644
--- a/src/util/db2/test/run.test
+++ b/src/util/db2/test/run.test
@@ -31,6 +31,8 @@ main()
dictsize=`wc -l < $DICT`
+ bindir=/bin/.
+
if [ $# -eq 0 ]; then
for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
test$t
@@ -141,15 +143,15 @@ test2()
fi
}
-# Insert the programs in /bin with their paths as their keys.
+# Insert the programs in $bindir with their paths as their keys.
test3()
{
echo "Test 3: hash: small key, big data pairs"
rm -f $TMP1
- (find /bin -type f -exec test -r {} \; -print | xargs cat) > $TMP1
+ (find $bindir -type f -exec test -r {} \; -print | xargs cat) > $TMP1
for type in hash; do
rm -f $TMP2 $TMP3
- for i in `find /bin -type f -exec test -r {} \; -print`; do
+ for i in `find $bindir -type f -exec test -r {} \; -print`; do
echo p
echo k$i
echo D$i
@@ -168,7 +170,7 @@ test3()
echo " page size $psize"
for type in btree; do
rm -f $TMP2 $TMP3
- for i in `find /bin -type f -exec test -r {} \; -print`; do
+ for i in `find $bindir -type f -exec test -r {} \; -print`; do
echo p
echo k$i
echo D$i
@@ -185,7 +187,7 @@ test3()
done
echo "Test 3: recno: big data pairs"
rm -f $TMP2 $TMP3
- find /bin -type f -exec test -r {} \; -print |
+ find $bindir -type f -exec test -r {} \; -print |
awk '{
++i;
printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
@@ -415,7 +417,12 @@ test8()
printf("r\nkkey1\nr\nkkey2\n");
}
}' > $TMP1
- $PROG btree $TMP1
+ if $PROG btree $TMP1 ; then
+ true
+ else
+ echo "test8: btree tests failed"
+ exit 1
+ fi
# $PROG hash $TMP1
# No explicit test for success.
}
diff --git a/src/util/et/ChangeLog b/src/util/et/ChangeLog
index 345416e..b277f07 100644
--- a/src/util/et/ChangeLog
+++ b/src/util/et/ChangeLog
@@ -1,3 +1,55 @@
+2001-12-18 Ken Raeburn <raeburn@mit.edu>
+
+ * test_et.c (main): Only use sys_nerr tests if HAVE_SYS_ERRLIST.
+
+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/et/test_et.c b/src/util/et/test_et.c
index ff638a2..efeaf62 100644
--- a/src/util/et/test_et.c
+++ b/src/util/et/test_et.c
@@ -14,8 +14,10 @@ main()
printf("Msg TGT-expired is '%s'\n", error_message(KRB_MK_AP_TGTEXP));
printf("Msg EPERM is '%s'\n", error_message(EPERM));
printf("Msg FOO_ERR is '%s'\n", error_message(FOO_ERR));
+#ifdef HAVE_SYS_ERRLIST
printf("Msg {sys_nerr-1} is '%s'\n", error_message(sys_nerr-1));
printf("Msg {sys_nerr} is '%s'\n", error_message(sys_nerr));
+#endif
printf("Msg 0 is '%s'\n", error_message(0));
printf("With 0: tgt-expired -> %s\n", error_message(KRB_MK_AP_TGTEXP));
@@ -35,7 +37,9 @@ main()
printf("Msg for TGT-expired is '%s'\n",
error_message(KRB_MK_AP_TGTEXP));
+#ifdef HAVE_SYS_ERRLIST
printf("Msg {sys_nerr-1} is '%s'\n", error_message(sys_nerr-1));
+#endif
printf("Msg FOO_ERR is '%s'\n", error_message(FOO_ERR));
printf("Msg KRB_SKDC_CANT is '%s'\n",
error_message(KRB_SKDC_CANT));
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..9a1da21 100644
--- a/src/util/profile/ChangeLog
+++ b/src/util/profile/ChangeLog
@@ -1,3 +1,35 @@
+2002-02-28 Alexandra Ellwood <lxs@mit.edu>
+ * profile.pbexp: Restrict Mac OS X export list to public functions
+
+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..427a9d4
--- /dev/null
+++ b/src/util/profile/profile.pbexp
@@ -0,0 +1,24 @@
+#
+# _profile library Macintosh export file
+#
+# $Header$
+
+_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
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 ");